Конвейер транзакций
Конвейер транзакций обеспечивает полный жизненный цикл — от создания до финализации.
Обзор
User/SDK
│ build + sign (Ed25519)
▼
JSON-RPC (savitri_sendRawTransaction)
│ hex decode → bytes_to_raw_tx
▼
Mempool Admission
│ stateless guards → stateful guards
▼
SIMD Batch Scoring
│ fee * 0.7 + class_priority * 0.3
▼
Block Proposer (drain_for_block_production)
│ top-N by score, nonce-ordered per sender
▼
Block Production
│ compute tx_root, state_root
▼
Gossipsub Broadcast (/savitri/block/1)
│
▼
BFT Voting (2f+1 quorum)
│ Block Acceptance Certificate
▼
RocksDB Commit
│ CF_BLOCKS, CF_TRANSACTIONS, CF_ACCOUNTS
▼
Finalized
Формат транзакции
Каноническое сообщение для подписи
from (hex bytes) || to (hex bytes) || amount (u64 LE) || nonce (u64 LE) || fee (u128 LE)
Это сообщение хешируется через SHA-256, затем подписывается с помощью Ed25519.
Формат для передачи (raw_tx_hex)
from_hex_bytes || to_hex_bytes || amount_le_u64 || nonce_le_u64 || fee_le_u128 || pubkey (32B) || signature (64B) || data (optional)
Отправляется в виде hex-строки в savitri_sendRawTransaction.
Приём в мемпул
Без доступа к хранилищу (stateless guards)
- Проверка формата подписи (64 байта ed25519)
- Проверка формата публичного ключа (32 байта ed25519)
- Верификация подписи по хешу сообщения
- Проверка ограничений размера транзакции
С доступом к хранилищу (stateful guards)
- Проверка nonce:
tx.nonce >= account.nonce(допуск пробела до 5000) - Проверка баланса:
account.balance >= tx.amount + tx.fee - Проверка квоты: лимиты по классу и по отправителю
Классы транзакций
| Класс | Приоритет | Макс. квота |
|---|---|---|
| FederatedUpdate | 1.0 (наивысший) | 50 000 |
| Financial | 0.8 | 50 000 |
| IoTData | 0.5 | 100 000 |
| Governance | 0.7 | 50 000 |
Система квот
- Лимиты по классу: Financial 50K, IoT 100K, Global 100K
- Лимит на отправителя: 512 ожидающих транзакций на отправителя
- Справедливое извлечение:
drain_fair_batch()соблюдает квоты и вызываетrecord_removal()
SIMD-оценка
Диспетчер оценивает транзакции с использованием SIMD-оптимизированного пакетного вычисления:
score = fee_normalized * fee_weight + class_priority * class_weight
Веса по умолчанию: fee_weight = 0.7, class_weight = 0.3.
Реализация SIMD
| Архитектура | Набор инструкций | Каналы | Порог |
|---|---|---|---|
| x86_64 | AVX2 + FMA | 4 double | 32 транзакции |
| ARM (aarch64) | NEON | 2 double | 32 транзакции |
| Резервный | Скалярный | 1 | Всегда |
Для пакетов менее 32 транзакций используется скалярное вычисление (накладные расходы SIMD превышают выгоду).
Кеш оценок
LRU-кеш позволяет избежать повторного вычисления оценок для транзакций, остающихся в мемпуле между блоками.
Адаптивные веса
При включённом флаге функции adaptive_weights веса динамически корректируются на основе:
- Распределения комиссий в мемпуле
- Разнообразия классов
- Исторической пропускной способности
Производство блоков
Избранный предложитель:
- Вызывает
drain_for_block_production(max_block_txs) - Получает топ-N транзакций, упорядоченных по оценке
- Выполняет
final_validationс отслеживаниемpending_nonces(предотвращает отклонение из-за устаревшего nonce) - Вычисляет корень транзакций: листовой тег
"TXv1", нарастающий аккумулятор - Вычисляет корень состояния: начальное значение
"STATEv1-LE", лексикографический снимок - Подписывает блок с помощью Ed25519
- Транслирует через gossipsub
Обработка nonce
final_validationотслеживаетpending_noncesHashMap для извлечённых, но незафиксированных транзакций- Исправление холодного старта: принимает наименьший доступный nonce при
storage_nonce=0 AND pending_nonces=0 - Сброс nonce: генератор транзакций сбрасывает, когда локальный nonce > storage_nonce + 200
Хранилище
Зафиксированные блоки хранятся в столбцовых семействах RocksDB:
| Столбцовое семейство | Ключ | Значение |
|---|---|---|
CF_BLOCKS | высота (u64 LE) | Block (bincode) |
CF_TRANSACTIONS | tx_hash | Transaction (bincode) |
CF_ACCOUNTS | адрес (32 байта) | Account (bincode) |
CF_METADATA | "chain_head" | Последний блок (bincode) |
Пустые аккаунты (balance=0, nonce=0) никогда не сохраняются.