Перейти к основному содержимому

Конвейер транзакций

Конвейер транзакций обеспечивает полный жизненный цикл — от создания до финализации.

Обзор

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)

  1. Проверка формата подписи (64 байта ed25519)
  2. Проверка формата публичного ключа (32 байта ed25519)
  3. Верификация подписи по хешу сообщения
  4. Проверка ограничений размера транзакции

С доступом к хранилищу (stateful guards)

  1. Проверка nonce: tx.nonce >= account.nonce (допуск пробела до 5000)
  2. Проверка баланса: account.balance >= tx.amount + tx.fee
  3. Проверка квоты: лимиты по классу и по отправителю

Классы транзакций

КлассПриоритетМакс. квота
FederatedUpdate1.0 (наивысший)50 000
Financial0.850 000
IoTData0.5100 000
Governance0.750 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_64AVX2 + FMA4 double32 транзакции
ARM (aarch64)NEON2 double32 транзакции
РезервныйСкалярный1Всегда

Для пакетов менее 32 транзакций используется скалярное вычисление (накладные расходы SIMD превышают выгоду).

Кеш оценок

LRU-кеш позволяет избежать повторного вычисления оценок для транзакций, остающихся в мемпуле между блоками.

Адаптивные веса

При включённом флаге функции adaptive_weights веса динамически корректируются на основе:

  • Распределения комиссий в мемпуле
  • Разнообразия классов
  • Исторической пропускной способности

Производство блоков

Избранный предложитель:

  1. Вызывает drain_for_block_production(max_block_txs)
  2. Получает топ-N транзакций, упорядоченных по оценке
  3. Выполняет final_validation с отслеживанием pending_nonces (предотвращает отклонение из-за устаревшего nonce)
  4. Вычисляет корень транзакций: листовой тег "TXv1", нарастающий аккумулятор
  5. Вычисляет корень состояния: начальное значение "STATEv1-LE", лексикографический снимок
  6. Подписывает блок с помощью Ed25519
  7. Транслирует через gossipsub

Обработка nonce

  • final_validation отслеживает pending_nonces HashMap для извлечённых, но незафиксированных транзакций
  • Исправление холодного старта: принимает наименьший доступный nonce при storage_nonce=0 AND pending_nonces=0
  • Сброс nonce: генератор транзакций сбрасывает, когда локальный nonce > storage_nonce + 200

Хранилище

Зафиксированные блоки хранятся в столбцовых семействах RocksDB:

Столбцовое семействоКлючЗначение
CF_BLOCKSвысота (u64 LE)Block (bincode)
CF_TRANSACTIONStx_hashTransaction (bincode)
CF_ACCOUNTSадрес (32 байта)Account (bincode)
CF_METADATA"chain_head"Последний блок (bincode)

Пустые аккаунты (balance=0, nonce=0) никогда не сохраняются.