스토리지 아키텍처
Savitri Network는 데이터 격리와 효율적인 접근 패턴을 위해 컬럼 패밀리와 함께 RocksDB를 기본 스토리지 백엔드로 사용합니다.
컬럼 패밀리
| 컬럼 패밀리 | 키 | 값 | 목적 |
|---|---|---|---|
CF_BLOCKS | 높이 (u64 LE) | 블록 (bincode) | 블록 스토리지 |
CF_TRANSACTIONS | tx_hash (32바이트) | 트랜잭션 (bincode) | 트랜잭션 조회 |
CF_ACCOUNTS | 주소 (32바이트) | 계정 (24바이트) | 잔액 + 논스 |
CF_METADATA | 문자열 키 | 다양 | 체인 헤드, 설정 |
CF_RECEIPTS | tx_hash | 영수증 (bincode) | 트랜잭션 영수증 |
CF_CONTRACTS | 주소 | ContractInfo | 스마트 컨트랙트 상태 |
CF_GOVERNANCE | proposal_id | 제안 (bincode) | 거버넌스 제안 |
CF_ORACLE | feed_id | OracleData | 오라클 피드 |
CF_BONDS | 주소 | 보증금 금액 | 검증자 보증금 |
CF_VOTE_TOKENS | 주소 | VoteToken 잔액 | 거버넌스 투표 토큰 |
CF_TREASURY | 키 | 재무부 상태 | 네트워크 재무부 |
CF_VESTING | schedule_id | VestingSchedule | 토큰 베스팅 |
CF_REWARD_COINS | 주소 | 보상 잔액 | 노드 보상 |
CF_FEE_METRICS | 키 | 수수료 데이터 | 수수료 모니터링 |
CF_SUPPLY_METRICS | 키 | 공급량 데이터 | 토큰 공급량 |
CF_ACTIVE_NODES | node_id | 활동 | 노드 활성 상태 |
CF_MONOLITHS | monolith_id | Monolith | 블록 압축 |
CF_FL | 키 | FL 데이터 | 연합 학습 |
CF_POU | node_id | PoU 점수 | 합의 점수 |
계정 인코딩
계정은 24바이트 고정 너비 컴팩트 인코딩을 사용합니다:
바이트 0-15: 잔액 (u128, little-endian)
바이트 16-23: 논스 (u64, little-endian)
하위 호환성: 이전 16바이트 형식(잔액만, 논스=0)도 지원됩니다.
빈 계정(잔액=0, 논스=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 읽기 감소
- 컨트랙트 스토리지 캐시: 컨트랙트 실행 시 SLOAD 결과 메모이제이션
- 점수 캐시: 멤풀에서 TX 평가를 위한 LRU 캐시 (재계산 방지)
RocksDB 설정
| 매개변수 | 개발 | 운영 |
|---|---|---|
| 캐시 크기 | 256 MB | 1024 MB |
| 쓰기 버퍼 | 16 MB | 64 MB |
| 최대 열린 파일 | 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 | 테스트용 임시 스토리지 |