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

Архитектура мемпула

Мемпул управляет ожидающими транзакциями — от приёма через оценку до извлечения при производстве блока.

Конвейер

Network (gossipsub /savitri/tx/1)


Prevalidation (stateless)
│ signature format, size limits

Admission Control
│ quota check, per-sender cap

Stateful Validation
│ nonce, balance, fee limits

SIMD Batch Scoring
│ fee * 0.7 + class * 0.3

Score Cache (LRU)


Pending Pool


drain_for_block_production()
│ top-N by score, final_validation

Block Proposer

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

КлассПриоритетПрименение
FederatedUpdate1.0 (наивысший)Обновления FL-модели
Financial0.8Переводы токенов
Governance0.7Голоса, предложения
IoTData0.5Данные датчиков

Квоты приёма

КлассМакс. ожидающихЛимит на отправителя
Financial50 000512
IoT100 000512
Global100 000512

Функция drain_fair_batch() вызывает record_removal() для корректного уменьшения счётчиков классов при извлечении транзакций (исправлено в Round 6).

SIMD-оценка

Формула оценки

score = fee_normalized * fee_weight + class_priority * class_weight

По умолчанию: fee_weight = 0.7, class_weight = 0.3.

Реализация для конкретных архитектур

АрхитектураИнструкцииКаналыМин. размер пакета
x86_64 (AVX2+FMA)_mm256_set1_pd, _mm256_fmadd_pd4 double32
ARM (NEON)vdupq_n_f64, vfmaq_f642 double32
РезервныйСкалярный цикл1Всегда

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

Адаптивные веса (опционально)

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

  • Распределение комиссий: при кластеризации комиссий в высоком диапазоне увеличивается fee_weight
  • Разнообразие классов: при большом количестве разных классов увеличивается class_weight
  • Историческая пропускная способность: корректировка на основе последних блоков

Параметры:

base_fee_weight = 0.7
base_class_weight = 0.3
adaptation_rate = 0.1 (сглаживание)
fee_threshold_high = 2,000,000,000
fee_threshold_low = 500,000,000
class_diversity_threshold = 0.5

Кеш оценок

LRU-кеш позволяет избежать повторного вычисления оценок:

ПараметрРазработкаПродакшн
Размер кеша100 записей10 000 записей
TTL60 секунд300 секунд

Управление nonce

Стандартный процесс

  1. Транзакция поступает с nonce N
  2. Проверка: N >= account.storage_nonce
  3. Отслеживание в pending_nonces HashMap при извлечении
  4. Фиксация nonce после финализации блока

Допуск пробелов

Пробел в nonce до 5000 принимается для восстановления после длительных задержек (увеличено с 1000 в Round 11).

Исправление холодного старта

При storage_nonce=0 AND pending_nonces=0 в качестве начальной точки принимается наименьший доступный nonce. Это обрабатывает случай, когда транзакции были извлечены, но блок так и не был зафиксирован предыдущим предложителем.

Сброс nonce

Генератор транзакций сбрасывает локальный nonce при local_nonce > storage_nonce + 200 (MAX_NONCE_AHEAD). Ранее локальные nonce могли уйти в дрейф до 2000+, тогда как storage находился на 84, что приводило к отклонению всех транзакций.

Защита от повторного использования

Хеши транзакций отслеживаются для предотвращения атак повторного воспроизведения. После обнаружения хеша транзакции повторные отправки отклоняются.

Валидация комиссий

FeeLimits {
min_fee: 100_000_000_000_000, // 0.0001 SAVT
max_fee: 1_000_000_000_000_000_000, // 1.0 SAVT
}

Флаги функций

ФлагОписание
simdSIMD-оптимизированная оценка (по умолчанию)
cacheКеш оценок (по умолчанию)
adaptive_weightsДинамическая корректировка весов