Saltar al contenido principal

Pipeline de Transacciones

El pipeline de transacciones gestiona el ciclo de vida completo desde la creación hasta la finalización.

Visión General

Usuario/SDK
│ construcción + firma (Ed25519)

JSON-RPC (savitri_sendRawTransaction)
│ decodificación hex → bytes_to_raw_tx

Admisión al Mempool
│ guardas sin estado → guardas con estado

Puntuación por Lote SIMD
│ fee * 0.7 + class_priority * 0.3

Propositor de Bloque (drain_for_block_production)
│ top-N por puntuación, ordenados por nonce por remitente

Producción de Bloque
│ cómputo de tx_root, state_root

Difusión Gossipsub (/savitri/block/1)


Votación BFT (quórum 2f+1)
│ Certificado de Aceptación de Bloque

Confirmación en RocksDB
│ CF_BLOCKS, CF_TRANSACTIONS, CF_ACCOUNTS

Finalizado

Formato de Transacción

Mensaje de Firma Canónico

from (bytes hex) || to (bytes hex) || amount (u64 LE) || nonce (u64 LE) || fee (u128 LE)

Este mensaje es hasheado con SHA-256 y luego firmado con Ed25519.

Formato de Transmisión (raw_tx_hex)

from_hex_bytes || to_hex_bytes || amount_le_u64 || nonce_le_u64 || fee_le_u128 || pubkey (32B) || signature (64B) || data (opcional)

Se envía como cadena codificada en hex a savitri_sendRawTransaction.

Admisión al Mempool

Guardas Sin Estado (sin acceso al almacenamiento)

  1. Validación del formato de firma (64 bytes ed25519)
  2. Validación del formato de clave pública (32 bytes ed25519)
  3. Verificación de firma contra el hash del mensaje
  4. Límites de tamaño de transacción

Guardas Con Estado (requieren acceso al almacenamiento)

  1. Verificación de nonce: tx.nonce >= account.nonce (tolerancia de brecha hasta 5000)
  2. Verificación de saldo: account.balance >= tx.amount + tx.fee
  3. Verificación de cuota: Límites por clase y por remitente

Clases de Transacciones

ClasePrioridadCuota Máxima
FederatedUpdate1.0 (más alta)50,000
Financial0.850,000
IoTData0.5100,000
Governance0.750,000

Sistema de Cuotas

  • Límites por clase: Financial 50K, IoT 100K, Global 100K
  • Límite por remitente: 512 transacciones pendientes por remitente
  • Drenaje equitativo: drain_fair_batch() respeta las cuotas y llama a record_removal()

Puntuación SIMD

El despachador puntúa las transacciones usando cómputo por lote optimizado con SIMD:

score = fee_normalized * fee_weight + class_priority * class_weight

Pesos por defecto: fee_weight = 0.7, class_weight = 0.3.

Implementación SIMD

ArquitecturaConjunto de InstruccionesCarrilesUmbral
x86_64AVX2 + FMA4 doubles32 TXs
ARM (aarch64)NEON2 doubles32 TXs
FallbackEscalar1Siempre

Para lotes con menos de 32 transacciones se usa cómputo escalar (el costo inicial de SIMD supera el beneficio).

Caché de Puntuaciones

La caché LRU evita recalcular puntuaciones para transacciones que permanecen en el mempool entre bloques.

Pesos Adaptativos

Con el indicador de característica adaptive_weights, los pesos se ajustan dinámicamente según:

  • Distribución de comisiones en el mempool
  • Diversidad de clases
  • Rendimiento histórico

Producción de Bloque

El propositor elegido:

  1. Llama a drain_for_block_production(max_block_txs)
  2. Obtiene las top-N transacciones ordenadas por puntuación
  3. Ejecuta final_validation con seguimiento de pending_nonces (previene el rechazo por nonce desactualizado)
  4. Calcula la raíz de transacciones: etiqueta de hoja "TXv1", acumulador progresivo
  5. Calcula la raíz de estado: semilla "STATEv1-LE", instantánea lexicográfica
  6. Firma el bloque con Ed25519
  7. Difunde vía gossipsub

Manejo de Nonce

  • final_validation rastrea el HashMap pending_nonces para las TX drenadas pero no confirmadas
  • Corrección de arranque en frío: Acepta el nonce disponible más bajo cuando storage_nonce=0 AND pending_nonces=0
  • Restablecimiento de nonce: El generador de TX restablece cuando el nonce local > storage_nonce + 200

Almacenamiento

Los bloques confirmados se almacenan en familias de columnas de RocksDB:

Familia de ColumnaClaveValor
CF_BLOCKSaltura (u64 LE)Bloque (bincode)
CF_TRANSACTIONStx_hashTransacción (bincode)
CF_ACCOUNTSdirección (32 bytes)Cuenta (bincode)
CF_METADATA"chain_head"Último bloque (bincode)

Las cuentas vacías (balance=0, nonce=0) nunca se persisten.