|
| 1 | +# Research: Implement BPT Sync Recovery |
| 2 | + |
| 3 | +## Summary |
| 4 | + |
| 5 | +This research documents the existing infrastructure and identifies requirements for implementing BPT-level sync recovery. The codebase already has partial implementations for state sync, snapshot restoration, and certificate synchronization. BPT sync recovery needs to build on these foundations to provide: (1) requesting missing BPT entries from neighbors, (2) background BPT walk to fill gaps, (3) validation passes until all nodes valid, and (4) filling missing chain entries. |
| 6 | + |
| 7 | +## Verified Facts |
| 8 | + |
| 9 | +### Fact 1: BPT Structure - Binary Patricia Tree Implementation |
| 10 | +- **Source**: `pkg/database/bpt/bpt.go:16-153` and `pkg/database/bpt/node.go:17-37` |
| 11 | +- **Content**: BPT is a Binary Patricia Tree with three node types: `emptyNode`, `leaf`, and `branch`. Each node implements the `node` interface with methods: `Type()`, `IsDirty()`, `getHash()`, `copyWith()`, `writeTo()`, `readFrom()`. |
| 12 | +- **Confidence**: HIGH |
| 13 | + |
| 14 | +### Fact 2: BPT Entry Format - Key-Value Pairs |
| 15 | +- **Source**: `pkg/database/bpt/bpt.go:16-19` |
| 16 | +- **Content**: |
| 17 | +```go |
| 18 | +type KeyValuePair struct { |
| 19 | + Key *record.Key |
| 20 | + Value []byte |
| 21 | +} |
| 22 | +``` |
| 23 | +- **Confidence**: HIGH |
| 24 | + |
| 25 | +### Fact 3: BPT Root Hash Computation |
| 26 | +- **Source**: `pkg/database/bpt/bpt.go:30-49` |
| 27 | +- **Content**: `GetRootHash()` executes pending updates, loads root node, and returns the hash. Branch hashes are computed by combining left/right child hashes with SHA-256. |
| 28 | +- **Confidence**: HIGH |
| 29 | + |
| 30 | +### Fact 4: BPT Iteration Support |
| 31 | +- **Source**: `pkg/database/bpt/iterate.go:28-80` |
| 32 | +- **Content**: `Iterate(window int)` returns an `Iterator` that walks the BPT in order, returning `KeyValuePair` slices. Uses `walkRange()` to traverse branches and collect leaf values. |
| 33 | +- **Confidence**: HIGH |
| 34 | + |
| 35 | +### Fact 5: BPT Snapshot Save/Load |
| 36 | +- **Source**: `pkg/database/bpt/bpt_savestate.go:21-210` |
| 37 | +- **Content**: `SaveSnapshotV1()` writes: 8-byte node count, then for each node: 32-byte key, 32-byte hash, 8-byte offset to value. Values follow with 8-byte length prefix. `LoadSnapshotV1()` reads this format and calls `storeState()` for each entry. |
| 38 | +- **Confidence**: HIGH |
| 39 | + |
| 40 | +### Fact 6: BPT Receipt Generation (Merkle Proofs) |
| 41 | +- **Source**: `pkg/database/bpt/bpt_receipt.go:18-93` |
| 42 | +- **Content**: `GetReceipt()` constructs a Merkle proof by walking from leaf to root, collecting sibling hashes at each level. Returns a `*merkle.Receipt` with start value, entries, and anchor. |
| 43 | +- **Confidence**: HIGH |
| 44 | + |
| 45 | +### Fact 7: Existing State Sync Framework |
| 46 | +- **Source**: `pkg/consensus/snapshot/sync.go:27-32` |
| 47 | +- **Content**: Protocol IDs defined: |
| 48 | +```go |
| 49 | +ProtocolSnapshotList = "/acc/consensus/snapshot/list/1.0.0" |
| 50 | +ProtocolSnapshotFetch = "/acc/consensus/snapshot/fetch/1.0.0" |
| 51 | +ProtocolSnapshotChunk = "/acc/consensus/snapshot/chunk/1.0.0" |
| 52 | +ProtocolStateSync = "/acc/consensus/state-sync/1.0.0" |
| 53 | +``` |
| 54 | +- **Confidence**: HIGH |
| 55 | + |
| 56 | +### Fact 8: StateSync Implementation |
| 57 | +- **Source**: `pkg/consensus/snapshot/sync.go:216-354` |
| 58 | +- **Content**: `StateSync` struct handles discovery, download, verify, and apply phases. Uses `SnapshotStore` and `Restorer`. Sync flow: discover snapshots from peers → select best → download → verify → apply → resume. |
| 59 | +- **Confidence**: HIGH |
| 60 | + |
| 61 | +### Fact 9: Snapshot Structure |
| 62 | +- **Source**: `pkg/consensus/snapshot/snapshot.go:58-85` |
| 63 | +- **Content**: Snapshot contains: Version, Height, Round, StateHash ([32]byte), Committee, Certificates array, Timestamp, and optional Metadata. |
| 64 | +- **Confidence**: HIGH |
| 65 | + |
| 66 | +### Fact 10: Certificate Sync Mechanism |
| 67 | +- **Source**: `pkg/consensus/primary/cert_sync.go:94-127` |
| 68 | +- **Content**: `CertSyncer` handles requesting missing certificates from peers. Implements batching (`BatchInterval`), deduplication (`DeduplicationInterval`), and retry logic (`MaxRetries = 10`). |
| 69 | +- **Confidence**: HIGH |
| 70 | + |
| 71 | +### Fact 11: Gossip Layer Topics |
| 72 | +- **Source**: `pkg/consensus/gossip/gossip.go:39-46` |
| 73 | +- **Content**: GossipLayer provides channels for: batches, headers, votes, certificates, syncRequests, and syncResponses. |
| 74 | +- **Confidence**: HIGH |
| 75 | + |
| 76 | +### Fact 12: State Hash Tracking |
| 77 | +- **Source**: `pkg/consensus/types/state_verification.go:179-206` |
| 78 | +- **Content**: `StateHashTracker` tracks local and remote state hashes by round. Detects divergence when hashes don't match. Used for cross-validator state verification. |
| 79 | +- **Confidence**: HIGH |
| 80 | + |
| 81 | +### Fact 13: Recovery Manager |
| 82 | +- **Source**: `pkg/consensus/recovery.go:106-168` |
| 83 | +- **Content**: `RecoveryManager.Recover()` steps: load checkpoint → validate → restore state (primary round, bullshark last commit, DAG) → catch up with peers via certificate sync. |
| 84 | +- **Confidence**: HIGH |
| 85 | + |
| 86 | +### Fact 14: Database Snapshot Restore |
| 87 | +- **Source**: `internal/database/snapshot/restore.go:32-271` |
| 88 | +- **Content**: `RestoreVisitor` processes accounts, transactions, and signatures from snapshots. Calls `batch.UpdateBPT()` after restoring entries. Uses batching (10000 items per batch). |
| 89 | +- **Confidence**: HIGH |
| 90 | + |
| 91 | +### Fact 15: Light Client Chain Sync |
| 92 | +- **Source**: `exp/light/sync.go:32-203` |
| 93 | +- **Content**: `PullAccount()` and `PullAccountWithChains()` fetch account state and chain entries. Compares local vs remote chain heads, identifies mismatches via `identifyBadEntry()`, and pulls missing entries in batches of 1000. |
| 94 | +- **Confidence**: HIGH |
| 95 | + |
| 96 | +### Fact 16: BPT-Centric Architecture |
| 97 | +- **Source**: `docs/architecture/consensus-and-state-optimization.md:77-113` |
| 98 | +- **Content**: Layered sync model: Layer 1 (BPT + Major Block Proof), Layer 2 (Catch-up Sync for recent data), Layer 3 (Interesting Chains), Layer 4 (Full Archival). BPT is authoritative state. |
| 99 | +- **Confidence**: HIGH |
| 100 | + |
| 101 | +### Fact 17: State Divergence Handling in Service |
| 102 | +- **Source**: `internal/node/dagbft/service.go:530-562` |
| 103 | +- **Content**: `onStateDivergence()` halts the service when state divergence is detected. Sets `halted = true`, records `haltReason`, emits event. |
| 104 | +- **Confidence**: HIGH |
| 105 | + |
| 106 | +### Fact 18: Request State Sync Stub |
| 107 | +- **Source**: `internal/node/dagbft/service.go:648-667` |
| 108 | +- **Content**: `RequestStateSync()` is a stub that logs intent but doesn't implement actual sync. Comment indicates sync would be via `snapshot.StateSync`. |
| 109 | +- **Confidence**: HIGH |
| 110 | + |
| 111 | +### Fact 19: Resume After Sync |
| 112 | +- **Source**: `internal/node/dagbft/service.go:669-696` |
| 113 | +- **Content**: `ResumeAfterSync()` resets halt state, updates `lastBlockIndex`, and records new state hash. Requires service to be halted. |
| 114 | +- **Confidence**: HIGH |
| 115 | + |
| 116 | +### Fact 20: BPT Mutation Operations |
| 117 | +- **Source**: `pkg/database/bpt/mutate.go:24-77` |
| 118 | +- **Content**: `Insert()` adds to pending map (deferred), `Delete()` marks for deletion. `executePending()` applies all mutations to tree. |
| 119 | +- **Confidence**: HIGH |
| 120 | + |
| 121 | +## Code References |
| 122 | + |
| 123 | +### Primary Implementation Files |
| 124 | +- `pkg/database/bpt/bpt.go` - BPT core operations, Get, GetRootHash |
| 125 | +- `pkg/database/bpt/node.go` - Node types (emptyNode, leaf, branch) |
| 126 | +- `pkg/database/bpt/iterate.go` - BPT iteration for walking entries |
| 127 | +- `pkg/database/bpt/bpt_savestate.go` - Snapshot save/load |
| 128 | +- `pkg/database/bpt/bpt_receipt.go` - Merkle proof generation |
| 129 | +- `pkg/database/bpt/mutate.go` - Insert/Delete operations |
| 130 | + |
| 131 | +### Sync/Recovery Infrastructure |
| 132 | +- `pkg/consensus/snapshot/sync.go` - State sync protocol |
| 133 | +- `pkg/consensus/snapshot/snapshot.go` - Snapshot structure |
| 134 | +- `pkg/consensus/snapshot/restore.go` - Snapshot restoration |
| 135 | +- `pkg/consensus/primary/cert_sync.go` - Certificate synchronization |
| 136 | +- `pkg/consensus/recovery.go` - Recovery manager |
| 137 | + |
| 138 | +### Service Integration |
| 139 | +- `internal/node/dagbft/service.go` - DAG-BFT service with state verification |
| 140 | +- `internal/database/snapshot/restore.go` - Database snapshot restoration |
| 141 | + |
| 142 | +### Light Client Reference |
| 143 | +- `exp/light/sync.go` - Chain entry sync implementation (reference for chain gap filling) |
| 144 | + |
| 145 | +## Architecture for BPT Sync Recovery |
| 146 | + |
| 147 | +Based on the research, BPT sync recovery should follow this architecture: |
| 148 | + |
| 149 | +### 1. Request Missing BPT Entries from Neighbors |
| 150 | + |
| 151 | +**Existing infrastructure to leverage:** |
| 152 | +- `pkg/consensus/gossip/gossip.go` - GossipLayer for peer communication |
| 153 | +- `pkg/consensus/primary/cert_sync.go` - Batching/deduplication patterns |
| 154 | + |
| 155 | +**Required new components:** |
| 156 | +- BPT sync request/response messages (similar to `CertSyncRequest/CertSyncResponse`) |
| 157 | +- Protocol ID for BPT entry requests (e.g., `/acc/consensus/bpt-sync/1.0.0`) |
| 158 | +- Request format: list of BPT node keys (32-byte hashes) |
| 159 | +- Response format: list of `KeyValuePair` entries |
| 160 | + |
| 161 | +### 2. Background BPT Walk to Fill Gaps |
| 162 | + |
| 163 | +**Existing infrastructure to leverage:** |
| 164 | +- `pkg/database/bpt/iterate.go` - BPT iteration |
| 165 | +- `pkg/database/bpt/node.go:150-181` - Node loading mechanism |
| 166 | + |
| 167 | +**Required new components:** |
| 168 | +- Gap detection: compare local branch hashes against received hashes |
| 169 | +- Walk algorithm: DFS/BFS from root, identify branches where local hash differs from expected |
| 170 | +- Background goroutine: rate-limited BPT walk that doesn't block consensus |
| 171 | + |
| 172 | +**Algorithm sketch:** |
| 173 | +``` |
| 174 | +1. Get expected root hash from anchor/certificate |
| 175 | +2. Walk BPT from root: |
| 176 | + a. Load local node |
| 177 | + b. Compare hash to expected |
| 178 | + c. If match: skip subtree |
| 179 | + d. If mismatch: |
| 180 | + - If branch: recursively check children |
| 181 | + - If leaf: request entry from peers |
| 182 | + - If empty/missing: request subtree |
| 183 | +3. Queue missing entries for sync |
| 184 | +``` |
| 185 | + |
| 186 | +### 3. Validation Passes Until All Nodes Valid |
| 187 | + |
| 188 | +**Existing infrastructure to leverage:** |
| 189 | +- `pkg/database/bpt/bpt_receipt.go` - Receipt/proof validation |
| 190 | +- `pkg/consensus/types/state_verification.go` - State hash verification |
| 191 | + |
| 192 | +**Required new components:** |
| 193 | +- Validation pass coordinator |
| 194 | +- Incremental validation: validate subtrees as they're filled |
| 195 | +- Convergence tracking: count of invalid nodes, retry logic |
| 196 | + |
| 197 | +**Validation approach:** |
| 198 | +``` |
| 199 | +1. After sync batch completes: |
| 200 | + a. Recompute affected branch hashes |
| 201 | + b. Compare to expected hashes |
| 202 | + c. If still mismatched: re-queue for sync |
| 203 | +2. Track convergence: |
| 204 | + - Count remaining invalid nodes |
| 205 | + - If unchanged after N passes: escalate (halt or full resync) |
| 206 | +``` |
| 207 | + |
| 208 | +### 4. Fill Missing Chain Entries |
| 209 | + |
| 210 | +**Existing infrastructure to leverage:** |
| 211 | +- `exp/light/sync.go` - Chain entry sync patterns |
| 212 | +- `internal/database/snapshot/restore.go` - Chain restoration |
| 213 | + |
| 214 | +**Required new components:** |
| 215 | +- Chain entry gap detection (compare chain head vs BPT entry) |
| 216 | +- Chain entry request protocol |
| 217 | +- Chain entry insertion with proof verification |
| 218 | + |
| 219 | +**Algorithm:** |
| 220 | +``` |
| 221 | +1. For each BPT entry representing a chain: |
| 222 | + a. Load chain head |
| 223 | + b. Compare to BPT value (chain anchor) |
| 224 | + c. If mismatch: identify missing entries |
| 225 | + d. Request entries from peers |
| 226 | + e. Insert entries, update chain head |
| 227 | + f. Verify BPT entry matches new chain anchor |
| 228 | +``` |
| 229 | + |
| 230 | +## Open Questions |
| 231 | + |
| 232 | +1. **Priority ordering**: Should BPT sync prioritize certain accounts (e.g., system accounts, validators)? |
| 233 | + |
| 234 | +2. **Bandwidth throttling**: What rate limits should apply to BPT sync requests to avoid network congestion? |
| 235 | + |
| 236 | +3. **Concurrent sync limits**: How many concurrent BPT subtree syncs are allowed? |
| 237 | + |
| 238 | +4. **Proof verification**: Should each synced BPT entry include a proof from a trusted root, or is the final root hash comparison sufficient? |
| 239 | + |
| 240 | +5. **Partial recovery**: Can the node participate in consensus while BPT sync is ongoing (for non-critical subtrees)? |
| 241 | + |
| 242 | +6. **Chain entry format**: What's the exact format for chain entry sync requests/responses? |
| 243 | + |
| 244 | +## Contradictions |
| 245 | + |
| 246 | +No contradictions found between sources. The codebase is consistent in: |
| 247 | +- BPT as authoritative state |
| 248 | +- Hash-based verification at each level |
| 249 | +- Snapshot-based bulk sync + incremental sync for catch-up |
| 250 | +- Service halting on state divergence (requires explicit recovery) |
0 commit comments