@@ -81,7 +81,7 @@ org namespace (per-organization)
8181- [ Durability & Finality Model] ( #durability--finality-model )
8282- [ Persistent Storage Architecture] ( #persistent-storage-architecture )
8383 - [ Directory Layout] ( #directory-layout )
84- - [ Storage Backend: redb ] ( #storage-backend-redb )
84+ - [ Storage Backend: inkwell ] ( #storage-backend-inkwell )
8585 - [ Block Archive Format] ( #block-archive-format )
8686 - [ Snapshot Format] ( #snapshot-format )
8787 - [ Crash Recovery] ( #crash-recovery )
@@ -394,7 +394,7 @@ graph TD
394394
395395** What's NOT merkleized per-write:**
396396
397- - Individual index entries (stored in redb for O(1) lookup)
397+ - Individual index entries (stored in inkwell for O(1) lookup)
398398- Dual indexes for relationship traversal
399399
400400** Verification approach:**
@@ -405,7 +405,7 @@ graph TD
405405
406406``` rust
407407struct StateLayer {
408- // Fast K/V storage for queries (redb )
408+ // Fast K/V storage for queries (inkwell )
409409 kv : Database ,
410410
411411 // Indexes for relationship traversal
@@ -550,7 +550,7 @@ fn decode_storage_key(storage_key: &[u8]) -> (VaultId, u8, &[u8]) {
550550
551551#### Per-Vault Bucket Structure
552552
553- Each vault maintains independent bucket tracking. Vaults in the same shard share a redb instance but compute separate ` state_root ` values.
553+ Each vault maintains independent bucket tracking. Vaults in the same shard share an inkwell database but compute separate ` state_root ` values.
554554
555555``` rust
556556struct ShardState {
@@ -655,7 +655,7 @@ impl ShardState {
655655State root computation must be identical on all nodes:
656656
6576571 . ** Hash function** : seahash for bucket assignment, SHA-256 for roots
658- 2 . ** Iteration order** : redb guarantees lexicographic key order within range
658+ 2 . ** Iteration order** : inkwell guarantees lexicographic key order within range
6596593 . ** Key-value encoding** : Length-prefixed (prevents ambiguous concatenation)
6606604 . ** Empty bucket** : Hash of empty input → ` SHA-256("") `
661661
@@ -1590,7 +1590,7 @@ Scaling dimensions:
15901590
15911591| Metric | Target | Measurement | Rationale |
15921592| ------------------ | --------------- | ------------------------------ | --------------------------------- |
1593- | Read (p50) | <0.5ms | Single key, no proof, follower | redb lookup + gRPC |
1593+ | Read (p50) | <0.5ms | Single key, no proof, follower | inkwell lookup + gRPC |
15941594| Read (p99) | <2ms | Single key, no proof, follower | Tail latency from GC/compaction |
15951595| Read + proof (p99) | <10ms | With merkle proof generation | Bucket-based O(k) proof |
15961596| Write (p50) | <10ms | Single tx, quorum commit | Raft RTT + fsync |
@@ -1600,7 +1600,7 @@ Scaling dimensions:
16001600
16011601** Why these targets are achievable:**
16021602
1603- - ** Read p99 <2ms** : Follower reads bypass Raft consensus. redb B- tree lookup is O(log n). etcd achieves ~ 2ms p99 for serializable reads.
1603+ - ** Read p99 <2ms** : Follower reads bypass Raft consensus. inkwell B+ tree lookup is O(log n). etcd achieves ~ 2ms p99 for serializable reads.
16041604- ** Write p99 <50ms** : Aggressive for blockchain but achievable because:
16051605 - Bucket-based state root: O(k) where k = dirty keys, not O(n) full tree
16061606 - Single Raft RTT: ~ 1-2ms same datacenter
@@ -2583,17 +2583,17 @@ Each node uses a single data directory with subdirectories per concern:
25832583├── shards/
25842584│ ├── _system/ # System Raft group
25852585│ │ ├── raft/ # Openraft storage
2586- │ │ │ ├── log.redb # Raft log entries
2586+ │ │ │ ├── log.inkwell # Raft log entries
25872587│ │ │ └── vote # Current term + voted_for
2588- │ │ ├── state.redb # State machine (system registry)
2588+ │ │ ├── state.inkwell # State machine (system registry)
25892589│ │ └── snapshots/
25902590│ │ ├── 000001000.snap # Snapshot at height 1000
25912591│ │ └── 000002000.snap # Snapshot at height 2000
25922592│ ├── shard_0001/ # User shard group
25932593│ │ ├── raft/
2594- │ │ │ ├── log.redb
2594+ │ │ │ ├── log.inkwell
25952595│ │ │ └── vote
2596- │ │ ├── state.redb # State for all vaults in shard
2596+ │ │ ├── state.inkwell # State for all vaults in shard
25972597│ │ ├── blocks/
25982598│ │ │ ├── segment_000000.blk # Blocks 0-9999
25992599│ │ │ ├── segment_000001.blk # Blocks 10000-19999
@@ -2610,26 +2610,26 @@ Each node uses a single data directory with subdirectories per concern:
26102610| Decision | Rationale |
26112611| ----------------------------- | ---------------------------------------------------------- |
26122612| Per-shard directories | Matches Raft group boundaries; independent failure domains |
2613- | Separate raft/ and state.redb | Raft log is append-heavy; state is random-access heavy |
2613+ | Separate raft/ and state.inkwell | Raft log is append-heavy; state is random-access heavy |
26142614| Block segments | Append-only writes; easy archival of old segments |
26152615| Snapshots by height | Predictable naming; simple retention policy |
26162616
2617- ### Storage Backend: redb
2617+ ### Storage Backend: inkwell
26182618
2619- [ redb ] ( https://github.com/cberner/redb ) provides ACID transactions with a simple API . Each shard uses two redb databases:
2619+ inkwell is our custom B+ tree storage engine providing ACID transactions with MVCC . Each shard uses two inkwell databases:
26202620
2621- ** raft/log.redb ** — Raft log storage:
2621+ ** raft/log.inkwell ** — Raft log storage:
26222622
26232623``` rust
2624- // Tables in log.redb
2624+ // Tables in log.inkwell
26252625const LOG_ENTRIES : TableDefinition <u64 , & [u8 ]> = TableDefinition :: new (" log" );
26262626const LOG_META : TableDefinition <& str , & [u8 ]> = TableDefinition :: new (" meta" );
26272627
2628- struct RedbLogStorage {
2628+ struct InkwellLogStorage {
26292629 db : Database ,
26302630}
26312631
2632- impl RaftLogStorage <TypeConfig > for RedbLogStorage {
2632+ impl RaftLogStorage <TypeConfig > for InkwellLogStorage {
26332633 async fn get_log_state (& mut self ) -> Result <LogState <TypeConfig >> {
26342634 let txn = self . db. begin_read ()? ;
26352635 let table = txn . open_table (LOG_META )? ;
@@ -2712,10 +2712,10 @@ impl RaftLogStorage<TypeConfig> for RedbLogStorage {
27122712}
27132713```
27142714
2715- ** state.redb ** — State machine storage:
2715+ ** state.inkwell ** — State machine storage:
27162716
27172717``` rust
2718- // Tables in state.redb (per shard, contains all vaults)
2718+ // B+ tree tables in state.inkwell (per shard, contains all vaults)
27192719const RELATIONSHIPS : TableDefinition <& [u8 ], & [u8 ]> = TableDefinition :: new (" rel" );
27202720const ENTITIES : TableDefinition <& [u8 ], & [u8 ]> = TableDefinition :: new (" ent" );
27212721const OBJ_INDEX : TableDefinition <& [u8 ], & [u8 ]> = TableDefinition :: new (" obj_idx" );
@@ -2730,7 +2730,7 @@ fn make_key(vault_id: VaultId, key: &[u8]) -> Vec<u8> {
27302730}
27312731```
27322732
2733- ** Per-shard isolation** : All vaults in a shard share a single redb instance . Keys are prefixed with ` vault_id ` for isolation. This reduces file handle count and enables cross-vault operations within a shard if needed.
2733+ ** Per-shard isolation** : All vaults in a shard share a single inkwell database . Keys are prefixed with ` vault_id ` for isolation. This reduces file handle count and enables cross-vault operations within a shard if needed.
27342734
27352735### Block Archive Format
27362736
@@ -2886,7 +2886,7 @@ impl Node {
28862886 let shard_id = parse_shard_id (& shard_dir . file_name ())? ;
28872887
28882888 // 3. Recover Raft state
2889- let raft_storage = RedbLogStorage :: open (shard_dir . join (" raft/log.redb " ))? ;
2889+ let raft_storage = RedbLogStorage :: open (shard_dir . join (" raft/log.inkwell " ))? ;
28902890 let vote = raft_storage . read_vote (). await ? ;
28912891 let log_state = raft_storage . get_log_state (). await ? ;
28922892
@@ -2936,7 +2936,7 @@ impl Node {
29362936| Failure Mode | Recovery Action |
29372937| -------------------- | --------------------------------------------- |
29382938| Clean shutdown | Replay from last snapshot + committed log |
2939- | Crash during write | Incomplete redb txn rolled back automatically |
2939+ | Crash during write | Incomplete inkwell txn rolled back automatically |
29402940| Corrupted snapshot | Skip to older snapshot, replay more log |
29412941| Corrupted log entry | Fetch from peer, or rebuild from snapshot |
29422942| Missing segment file | Fetch from peer (block archive is replicated) |
@@ -2962,7 +2962,7 @@ impl Node {
29622962### Storage Invariants
29632963
2964296430 . ** Raft log durability** : Log entries are fsync'd before Raft acknowledgment
2965- 31 . ** State consistency** : ` state.redb ` reflects all applied log entries up to ` applied_index `
2965+ 31 . ** State consistency** : ` state.inkwell ` reflects all applied log entries up to ` applied_index `
2966296632 . ** Block archive append-only** : Segment files are never modified after creation (only new segments appended)
2967296733 . ** Snapshot validity** : Snapshot ` state_root ` matches block header at ` shard_height `
29682968
0 commit comments