Архитектура хранилища
Savitri Network использует RocksDB в качестве основного бэкенда хранилища со столбцовыми семействами для изоляции данных и эффективных паттернов доступа.
Столбцовые семейства
| Столбцовое семейство | Ключ | Значение | Назначение |
|---|---|---|---|
CF_BLOCKS | высота (u64 LE) | Block (bincode) | Хранение блоков |
CF_TRANSACTIONS | tx_hash (32 байта) | Transaction (bincode) | Поиск транзакций |
CF_ACCOUNTS | адрес (32 байта) | Account (24 байта) | Баланс + nonce |
CF_METADATA | строковый ключ | разные | Голова цепи, конфигурация |
CF_RECEIPTS | tx_hash | Receipt (bincode) | Квитанции транзакций |
CF_CONTRACTS | адрес | ContractInfo | Состояние смарт-контракта |
CF_GOVERNANCE | proposal_id | Proposal (bincode) | Предложения управления |
CF_ORACLE | feed_id | OracleData | Потоки оракулов |
CF_BONDS | адрес | Bond amount | Залоги валидаторов |
CF_VOTE_TOKENS | адрес | VoteToken balance | Токены голосования управления |
CF_TREASURY | ключ | Treasury state | Казначейство сети |
CF_VESTING | schedule_id | VestingSchedule | Вестинг токенов |
CF_REWARD_COINS | адрес | Reward balance | Вознаграждения нод |
CF_FEE_METRICS | ключ | Fee data | Отслеживание комиссий |
CF_SUPPLY_METRICS | ключ | Supply data | Объём токенов |
CF_ACTIVE_NODES | node_id | Activity | Активность нод |
CF_MONOLITHS | monolith_id | Monolith | Сжатие блоков |
CF_FL | ключ | FL data | Федеративное обучение |
CF_POU | node_id | PoU score | Оценки консенсуса |
Кодирование аккаунтов
Аккаунты используют компактное 24-байтовое кодирование фиксированной ширины:
Байты 0-15: balance (u128, little-endian)
Байты 16-23: nonce (u64, little-endian)
Обратно совместимо: старый 16-байтовый формат (только balance, nonce=0) по-прежнему поддерживается.
Пустые аккаунты (balance=0, nonce=0) никогда не сохраняются для экономии места в хранилище.
Корень состояния
Корень состояния вычисляется через лексикографический снимок базы данных:
seed = H("STATEv1-LE")
leaf = H("STATE" || key || value) для каждой пары ключ-значение
root = rolling_accumulate(seed, leaf_1, leaf_2, ..., leaf_n)
Ключи итерируются в лексикографическом порядке для детерминизма.
Трейт хранилища
Все бэкенды хранилища реализуют StorageTrait:
pub trait StorageTrait: Send + Sync {
fn get_cf(&self, cf: &str, key: &[u8]) -> Result<Option<Vec<u8>>>;
fn put_cf(&self, cf: &str, key: &[u8], value: &[u8]) -> Result<()>;
fn delete_cf(&self, cf: &str, key: &[u8]) -> Result<()>;
fn get_cf_prefix(&self, cf: &str, prefix: &[u8]) -> Result<Vec<(Vec<u8>, Vec<u8>)>>;
// ... пакетные операции, итерация и т.д.
}
Безопасная десериализация
Вся десериализация bincode использует максимальное ограничение размера для предотвращения исчерпания памяти:
const MAX_BINCODE_SIZE: u64 = 16 * 1024 * 1024; // 16MB
Кеширование
Уровень LRU-кеша для часто запрашиваемых данных:
- Кеш аккаунтов: уменьшает количество чтений RocksDB при проверке баланса/nonce
- Кеш хранилища контрактов: кеширует результаты SLOAD в пределах выполнения контракта
- Кеш оценок: LRU-кеш для оценки транзакций в мемпуле (избегает повторного вычисления)
Конфигурация RocksDB
| Параметр | Разработка | Продакшн |
|---|---|---|
| Размер кеша | 256 МБ | 1024 МБ |
| Буфер записи | 16 МБ | 64 МБ |
| Макс. открытых файлов | 100 | 1000 |
| Интервал синхронизации | 5с | 30с |
| Сжатие | Отключено | Включено |
Пакетные операции
Атомарные пакетные записи обеспечивают согласованность:
let mut batch = storage.batch();
batch.put_cf(CF_ACCOUNTS, &addr, &account.encode());
batch.put_cf(CF_TRANSACTIONS, &tx_hash, &tx_bytes);
batch.put_cf(CF_BLOCKS, &height_key, &block_bytes);
batch.commit()?;
Система вестинга
Расписания вестинга токенов поддерживают три типа:
| Тип | Поведение |
|---|---|
Linear | Токены высвобождаются линейно на протяжении периода |
Cliff | Нет токенов до периода клиффа, затем линейно |
Staged | Режим совместимости с генезисом |
Флаги функций
| Флаг | Описание |
|---|---|
rocksdb | Бэкенд RocksDB (по умолчанию) |
memory | Бэкенд в памяти (тестирование) |
prometheus | Экспорт метрик Prometheus |
tempfile | Временное хранилище для тестов |