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)
- Validación del formato de firma (64 bytes ed25519)
- Validación del formato de clave pública (32 bytes ed25519)
- Verificación de firma contra el hash del mensaje
- Límites de tamaño de transacción
Guardas Con Estado (requieren acceso al almacenamiento)
- Verificación de nonce:
tx.nonce >= account.nonce(tolerancia de brecha hasta 5000) - Verificación de saldo:
account.balance >= tx.amount + tx.fee - Verificación de cuota: Límites por clase y por remitente
Clases de Transacciones
| Clase | Prioridad | Cuota Máxima |
|---|---|---|
| FederatedUpdate | 1.0 (más alta) | 50,000 |
| Financial | 0.8 | 50,000 |
| IoTData | 0.5 | 100,000 |
| Governance | 0.7 | 50,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 arecord_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
| Arquitectura | Conjunto de Instrucciones | Carriles | Umbral |
|---|---|---|---|
| x86_64 | AVX2 + FMA | 4 doubles | 32 TXs |
| ARM (aarch64) | NEON | 2 doubles | 32 TXs |
| Fallback | Escalar | 1 | Siempre |
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:
- Llama a
drain_for_block_production(max_block_txs) - Obtiene las top-N transacciones ordenadas por puntuación
- Ejecuta
final_validationcon seguimiento depending_nonces(previene el rechazo por nonce desactualizado) - Calcula la raíz de transacciones: etiqueta de hoja
"TXv1", acumulador progresivo - Calcula la raíz de estado: semilla
"STATEv1-LE", instantánea lexicográfica - Firma el bloque con Ed25519
- Difunde vía gossipsub
Manejo de Nonce
final_validationrastrea el HashMappending_noncespara 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 Columna | Clave | Valor |
|---|---|---|
CF_BLOCKS | altura (u64 LE) | Bloque (bincode) |
CF_TRANSACTIONS | tx_hash | Transacción (bincode) |
CF_ACCOUNTS | dirección (32 bytes) | Cuenta (bincode) |
CF_METADATA | "chain_head" | Último bloque (bincode) |
Las cuentas vacías (balance=0, nonce=0) nunca se persisten.