Pipeline delle Transazioni
La pipeline delle transazioni gestisce l'intero ciclo di vita dalla creazione alla finalizzazione.
Panoramica
Utente/SDK
│ costruzione + firma (Ed25519)
▼
JSON-RPC (savitri_sendRawTransaction)
│ decodifica hex → bytes_to_raw_tx
▼
Ammissione al Mempool
│ guardie stateless → guardie stateful
▼
Valutazione Batch SIMD
│ fee * 0.7 + class_priority * 0.3
▼
Proposer del Blocco (drain_for_block_production)
│ top-N per punteggio, ordinati per nonce per mittente
▼
Produzione del Blocco
│ calcolo tx_root, state_root
▼
Broadcast Gossipsub (/savitri/block/1)
│
▼
Votazione BFT (quorum 2f+1)
│ Certificato di Accettazione del Blocco
▼
Commit su RocksDB
│ CF_BLOCKS, CF_TRANSACTIONS, CF_ACCOUNTS
▼
Finalizzato
Formato della Transazione
Messaggio di Firma Canonico
from (byte hex) || to (byte hex) || amount (u64 LE) || nonce (u64 LE) || fee (u128 LE)
Questo messaggio viene sottoposto ad hash SHA-256, poi firmato con Ed25519.
Formato Wire (raw_tx_hex)
from_hex_bytes || to_hex_bytes || amount_le_u64 || nonce_le_u64 || fee_le_u128 || pubkey (32B) || signature (64B) || data (opzionale)
Inviato come stringa codificata in hex a savitri_sendRawTransaction.
Ammissione al Mempool
Guardie Stateless (senza accesso allo storage)
- Validazione formato firma (ed25519 a 64 byte)
- Validazione formato chiave pubblica (ed25519 a 32 byte)
- Verifica della firma rispetto all'hash del messaggio
- Limiti di dimensione della transazione
Guardie Stateful (richiedono accesso allo storage)
- Verifica nonce:
tx.nonce >= account.nonce(tolleranza gap fino a 5000) - Verifica saldo:
account.balance >= tx.amount + tx.fee - Verifica quota: Limiti per classe e per mittente
Classi di Transazione
| Classe | Priorità | Quota Massima |
|---|---|---|
| FederatedUpdate | 1.0 (massima) | 50.000 |
| Financial | 0.8 | 50.000 |
| IoTData | 0.5 | 100.000 |
| Governance | 0.7 | 50.000 |
Sistema di Quote
- Limiti per classe: Financial 50K, IoT 100K, Globale 100K
- Limite per mittente: 512 transazioni in attesa per mittente
- Svuotamento equo:
drain_fair_batch()rispetta le quote e chiamarecord_removal()
Valutazione SIMD
Il dispatcher valuta le transazioni usando calcolo batch ottimizzato SIMD:
score = fee_normalized * fee_weight + class_priority * class_weight
Pesi predefiniti: fee_weight = 0.7, class_weight = 0.3.
Implementazione SIMD
| Architettura | Set di Istruzioni | Corsie | Soglia |
|---|---|---|---|
| x86_64 | AVX2 + FMA | 4 double | 32 TX |
| ARM (aarch64) | NEON | 2 double | 32 TX |
| Fallback | Scalare | 1 | Sempre |
Per batch con meno di 32 transazioni si utilizza il calcolo scalare (il costo di inizializzazione SIMD supera il beneficio).
Cache dei Punteggi
La cache LRU evita il ricalcolo dei punteggi per le transazioni che rimangono nel mempool tra un blocco e l'altro.
Pesi Adattativi
Con il flag di funzionalità adaptive_weights, i pesi si adattano dinamicamente in base a:
- Distribuzione delle commissioni nel mempool
- Diversità delle classi
- Throughput storico
Produzione del Blocco
Il proposer eletto:
- Chiama
drain_for_block_production(max_block_txs) - Ottiene le top-N transazioni ordinate per punteggio
- Esegue
final_validationcon tracciamentopending_nonces(previene il rifiuto per nonce non aggiornati) - Calcola la transaction root: tag foglia
"TXv1", accumulatore progressivo - Calcola la state root: seed
"STATEv1-LE", snapshot lessicografico - Firma il blocco con Ed25519
- Trasmette tramite gossipsub
Gestione del Nonce
final_validationtracciapending_noncesHashMap per le TX svuotate ma non ancora confermate- Correzione cold-start: Accetta il nonce disponibile più basso quando
storage_nonce=0 E pending_nonces=0 - Reset nonce: Il generatore TX resetta quando il nonce locale > storage_nonce + 200
Storage
I blocchi confermati sono salvati nelle column family di RocksDB:
| Column Family | Chiave | Valore |
|---|---|---|
CF_BLOCKS | altezza (u64 LE) | Blocco (bincode) |
CF_TRANSACTIONS | tx_hash | Transazione (bincode) |
CF_ACCOUNTS | indirizzo (32 byte) | Account (bincode) |
CF_METADATA | "chain_head" | Ultimo blocco (bincode) |
Gli account vuoti (saldo=0, nonce=0) non vengono mai salvati.