fix(prevrandao): bring the seed fork up to its siblings' rollout scaffolding - #1319
Open
MavenRain wants to merge 8 commits into
Open
fix(prevrandao): bring the seed fork up to its siblings' rollout scaffolding#1319MavenRain wants to merge 8 commits into
MavenRain wants to merge 8 commits into
Conversation
…folding Closes #1310. - log PREVRANDAO_FORK_EPOCH in the adiri startup fork schedule and name prevrandao_seed in the non-adiri genesis-active message - wire TN_PREVRANDAO_FORK_EPOCH as a third sibling: Makefile default (dormant), exported on the fork-pinned lanes only, and added to the e2e harness pin loop, so a seed-armed lane no longer arms PREVRANDAO as a side effect and a seeded lane arms both knobs deliberately - dispatch the engine basefee-penalty mix-hash oracle on prevrandao_seed_active, recomposing whichever derivation the build's fork schedule selects (fixes the red adiri run), and add tn-engine to the adiri CI lane so the pre-fork legacy arm runs somewhere - fork-boundary keeper deriving both grid points from the constant (adiri: legacy XOR byte-identical below the fork, seeded at the fork epoch; non-adiri: seeded everywhere) with anti-vacuity tripwires, plus a conjunction pin: seed-dormant epochs stay legacy regardless of the fork point - document the fork-gated derivation with indexer guidance and the accepted last-actor bias in docs/src/evm-compatibility.md, the tn-reth README, and at the derivation sites Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Onyeka Obi <softwareengineerasaservant@isurvivable.cv>
…caffolding Signed-off-by: Onyeka Obi <softwareengineerasaservant@isurvivable.cv>
…caffolding Signed-off-by: Onyeka Obi <softwareengineerasaservant@isurvivable.cv>
…caffolding Signed-off-by: Onyeka Obi <softwareengineerasaservant@isurvivable.cv> # Conflicts: # crates/telcoin-network-cli/src/node.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1310. (Cantina #9)
Problem
#1249 (fix #1247) moved the
mix_hash/PREVRANDAOderivation behind a fork gate, but did not land the rollout scaffolding the repo wraps around every epoch-gated fork, established twice over by the seed-signature (#1032) and multi-workers (#554) forks:PREVRANDAO_FORK_EPOCH, so operators cannot diff the compiled schedule across the fleet before an arming PR; the non-adiri arm's genesis-active message omits the fork entirely.TN_PREVRANDAO_FORK_EPOCHexists in code but nothing sets it: the Makefile declares and exports only the two sibling variables, and the e2e harness pins only those two on spawned nodes, so the seeded derivation is unreachable in every default e2e lane. Worse, on non-adiri builds arming the seed fork alone silently arms PREVRANDAO too (prevrandao_seed_activeconjoins the two gates, and the PREVRANDAO fork point is genesis-active off adiri), breaking the harness's documented arm-independently property.prev_randaotest builds its leader at epoch 0, so each build compiles and runs exactly one arm selected by the feature set, and the fail-closed conjunction has zero direct coverage.--features adiri, where the fork is dormant and the fixture leader sits at epoch 0. CI cannot see the failure because the adiri test lane omits tn-engine, violating the lane's own stated rule.docs/src/evm-compatibility.mdand the tn-reth README still describe only the legacy XOR, and nothing at the EVM-visible surface records the accepted last-actor bias.Changes
crates/telcoin-network-cli/src/node.rs: logprevrandao_fork_epochin the adiri fork-schedule line; nameprevrandao_seedin the non-adiri genesis-active message.crates/types/src/forks.rs: carry the siblings' fleet-diff rationale and the accepted-bias note onPREVRANDAO_FORK_EPOCH; new conjunction pinprevrandao_stays_legacy_while_seed_fork_is_dormant, which pins the seed fork to never-fires and the fork point to genesis in its own process (loud OnceLock-latch guards, anti-vacuity assertion that the fork point is actually active) and asserts every seed-dormant epoch stays on the legacy arm.Makefile: declareTN_PREVRANDAO_FORK_EPOCH ?= 4294967295(dormant) and export it on exactly the recipe lines that pin the two siblings, never a bare--workspacerun, so the override's inertness test keeps a clean process. The comment documents the deliberate two-knob arming:TN_SEED_SIGNATURE_FORK_EPOCH=0 TN_PREVRANDAO_FORK_EPOCH=0 make test-e2e.crates/e2e-tests/src/lib.rs: add the variable to the harness pin loop so spawned nodes default it to dormant, with the conjunction documented. A seed-armed lane no longer arms PREVRANDAO as a side effect.crates/engine/tests/it/main.rs: the hand-composed mix-hash oracle intest_simple_basefee_penaltynow dispatches onprevrandao_seed_active, the same predicate production dispatches on, recomposing by hand whichever derivation the build's fork schedule selects (legacy XOR under adiri at epoch 0, seeded elsewhere).etc/ci-lanes.sh: tn-engine joins the adiri lane (-p tn-engine,tn-engine/adiri), so the pre-fork legacy arm actually runs in CI.crates/types/src/primary/output.rs: fork-boundary keeperprev_randao_flips_arms_exactly_at_the_fork_epochderives both grid points from the constant, so an arming PR retargets it with no edit. Under adiri the legacy XOR must replay byte-identically atPREVRANDAO_FORK_EPOCH - 1and the seeded derivation must fire at the fork epoch itself (>=, not>); without adiri every epoch must take the seeded arm. Anti-vacuity tripwires fail loudly on ambient overrides.docs/src/evm-compatibility.mdgets the fork-gatedmix_hashrow plus a "Deriving the mix_hash field" section with indexer guidance (branch on the block's epoch, recoverable from the upper 32 bits ofnonce; the seed chain value advances per commit, with the closing commit's value published asextra_dataon the epoch's closing block). The tn-reth README row is updated to match, and the bias note lands on the derivation docs, the fork constant, the payload attribute, and the EVM block module.Threat model
The seeded derivation closes payload grinding: every input (domain tag, digest-pinned seed chain value, consensus block number, batch index) is fixed by the committed order, so a leader cannot generate candidate values by re-cutting its payload. The gate is fail-closed: the
seed_signature_activeconjunct means a mis-ordered fork schedule keeps the status quo instead of promoting the forkable legacy leader-aggregate seed intoPREVRANDAO, and the new conjunction test observes that ordering directly. What remains, and is now recorded at every reader-facing surface, is the accepted last-actor residual: the committing leader sees every value its commit will produce before broadcasting and keeps one propose-or-withhold choice per commit, so contracts needing unbiasable randomness must not usePREVRANDAOalone. No consensus behavior changes in this PR: the gate stays dormant on adiri (Epoch::MAXplaceholder) and the non-adiri derivation is unchanged.Testing
cargo +nightly-2026-03-20 fmt --all -- --checkgreen.~/Documents/tn-1310-gate.log): scopedcargo check --all-targetsover the five touched crates; the prevrandao/basefee test filter under default features and again undertn-types/adiri,tn-engine/adiri. . . the arm CI could not previously see; and a mutation-confirm that drops the seed conjunct fromprevrandao_seed_activeand watches the new conjunction test fail, with a compile pre-check so a broken mutant cannot masquerade as caught.cargo +1.94attest runs on the second machine post-push.