Skip to content

feat(consensus): migrate epoch_state to state trie post-fork (SIP-6, PR 4/N)#758

Merged
github-actions[bot] merged 1 commit into
mainfrom
feat/sip-6-epoch-state-trie
Jun 1, 2026
Merged

feat(consensus): migrate epoch_state to state trie post-fork (SIP-6, PR 4/N)#758
github-actions[bot] merged 1 commit into
mainfrom
feat/sip-6-epoch-state-trie

Conversation

@satyakwok
Copy link
Copy Markdown
Collaborator

@satyakwok satyakwok commented Jun 1, 2026

Summary

PR 4/N — the last off-trie consensus state piece migration. Closes the 4-class Bug A drift surface (pending_rewards in #756 + liveness/jail/total_minted in #757 + this PR's epoch_state).

Pre-fork (`STATE_IN_TRIE_HEIGHT == u64::MAX` default) = bit-identical chain history. Post-fork the current epoch's commitment-relevant fields ride along into state_root.

What this PR commits to the trie

Single fixed key (`epoch_state_key`), 80-byte fixed-layout value:

Field Bytes Source Drift class closed
`epoch_number` 0..8 (u64 BE) `EpochManager.current_epoch.epoch_number` Vals disagree which epoch we're in → divergent epoch-boundary handling
`start_height` 8..16 (u64 BE) same Boundary-anchor drift
`end_height` 16..24 (u64 BE) same Boundary-anchor drift
`total_staked` 24..32 (u64 BE) same Active-set stake frozen-at-boundary drift
`total_rewards` 32..40 (u64 BE) same Accumulator drift
`total_blocks_produced` 40..48 (u64 BE) same Accumulator drift
`validator_set_hash` 48..80 (SHA-256) same Active-set rotation drift (sorted before hashing for order-independence)

`history` (past epoch records) intentionally NOT committed — diagnostic only, never consumed by consensus.

What changes

  • `crates/sentrix-trie/src/address.rs` — `epoch_state_key()` (domain `b"sentrix/v1/epoch_state"`) + `epoch_state_value_bytes` (80-byte fixed encoder) + `epoch_state_value_decode`. 4 new unit tests including domain separation vs every other namespace and order-independence of `validator_set` hashing.
  • `crates/sentrix-trie/src/lib.rs` — re-export the 3 new symbols.
  • `crates/sentrix-core/src/blockchain_trie_ops.rs`:
    • New `struct EpochSnapshot` (named-fields, no more tuple-complexity warning) captured in Phase 1c.
    • Phase 2e (new) — write the 80-byte commitment under `epoch_state_key`.

Self-review (per feedback_smoke_test_and_code_review_every_change)

  • ✅ `cargo clippy --workspace --tests -- -D warnings` clean — matches the CI Test workflow's exact Clippy step (caught PR feat(consensus): migrate liveness + total_minted to state trie post-fork (SIP-6, PR 3/N) #757's `inconsistent_digit_grouping` + `type_complexity`; using a struct here pre-empts the latter).
  • ✅ 77/77 `sentrix-trie` tests pass — 4 new for epoch_state including order-independence assertion.
  • ✅ Borrow split: Phase 1c reads `self.epoch_manager.current_epoch` BEFORE the `state_trie.as_mut()` re-borrow.
  • ✅ Domain separation tested against every other namespace (balance, pending_rewards, liveness, total_minted).
  • ✅ Pre-fork: `epoch_snapshot = None` → no write → bit-identical.

Activation hazard (same as PR #756, #757)

First post-fork block writes the current epoch's snapshot. If accumulators / validator_set have already drifted across validators (the bug class this PR closes), state_root will diverge at the activation block. Mitigation via operator-set canonical override env vars at activation time, modelled on `STATE_ROOT_V2_TREASURY_BALANCE`. Out of scope here.

Closes the migration arc

After this PR merges, all 4 off-trie consensus state pieces flow through state_root post-fork:

State piece PR
`pending_rewards` #756
`liveness` + jail flags #757
`total_minted` #757
`epoch_state` this

Remaining work:

  • 5/N — pick testnet activation height, deploy, bake ≥1 week per SIP-6 § Activation Plan. Then SIP moves to Last Call. Then mainnet activation height picked at a halt-all + simul-start window with operator-set canonical override env vars.

Summary by CodeRabbit

  • New Features
    • Epoch consensus state (epoch number, validator set, staking totals, and block production metrics) is now recorded in the blockchain state trie for comprehensive historical state tracking and verification.

@github-actions github-actions Bot enabled auto-merge (squash) June 1, 2026 09:07
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions github-actions Bot merged commit 481caf8 into main Jun 1, 2026
17 of 18 checks passed
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR extends the blockchain state trie to persist epoch consensus state. Three new trie-encoding functions were added to serialize epoch snapshots into an 80-byte format (6 big-endian u64 scalars plus a 32-byte validator-set hash commitment). The block update logic was modified to capture epoch fields from the EpochManager and write the serialized snapshot to the trie during designated fork-height checkpoints, ensuring epoch state is reflected in committed state roots alongside existing per-account and per-validator fields.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • sentrix-labs/sentrix#750: Implements the F2 fix to move epoch consensus state off-chain into the state trie via new epoch snapshot encoding and block-update integration.

Possibly related PRs

  • sentrix-labs/sentrix#757: Both extend update_trie_for_block with additional SIP-6 trie-write phases for new state fields (epoch snapshot vs. liveness and total minted).
  • sentrix-labs/sentrix#755: Introduces the is_state_in_trie_height(block_index) fork-height predicate that gates the epoch snapshot write in this PR.
  • sentrix-labs/sentrix#661: Established the update_trie_for_block per-block trie ops implementation that this PR extends with epoch state commit phases.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately and concisely describes the main change: migrating epoch_state to the state trie post-fork as part of SIP-6 Bug A closure.
Description check ✅ Passed The PR description is comprehensive and covers summary, scope, specific implementation details, testing results, and deployment considerations matching the template structure.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sip-6-epoch-state-trie

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant