fix(nonce): correct TICKN candidate freeze and η_ph hash#88
Conversation
Three bugs in the live nonce pipeline that compound to produce wrong leader schedules from the auto-trigger at the stability window: 1. FreezeCandidate off-by-one: ProcessBlock evolved the nonce BEFORE FreezeCandidate was called externally, so the candidate included one extra block's contribution. Moved freeze logic inside ProcessBlock before evolution, matching ComputeEpochNonce. 2. TICKN η_ph used wrong hash: GetLastBlockHashForEpoch returns the last block's own hash, but η_ph = prevHash of last block = hash of the second-to-last block. Added GetPrevHashOfLastBlock method. 3. RecomputeCurrentEpochNonce trusted stored nonce_value instead of recomputing from raw VRF output. Added GetVrfOutputsForEpoch and aligned with ComputeEpochNonce's recomputation approach. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review infoConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis change refactors nonce computation to rely on raw VRF outputs instead of stored nonce values. New database methods retrieve VRF outputs per epoch and the previous block's hash. Nonce candidate freezing moves from an explicit API call into ProcessBlock at the stability window. The NonceTracker's public FreezeCandidate method is removed in favor of internal epoch-driven logic. Changes
Sequence Diagram(s)sequenceDiagram
actor Client as Client
participant PB as ProcessBlock
participant NT as NonceTracker
participant Store as Store/Database
Client->>PB: ProcessBlock(slot, epoch, blockHash, vrfOutput)
activate PB
alt At Stability Window
PB->>NT: Freeze candidate nonce internally
activate NT
NT->>NT: Log & persist η_c = evolving nonce
deactivate NT
end
PB->>PB: Continue with normal processing
deactivate PB
Client->>NT: RecomputeCurrentEpochNonce(ctx, epoch)
activate NT
NT->>Store: GetVrfOutputsForEpoch(ctx, epoch)
activate Store
Store-->>NT: []VrfBlock (ordered by slot)
deactivate Store
loop For each VrfBlock
NT->>NT: Recompute nonce from VRF output
end
NT->>Store: GetPrevHashOfLastBlock(ctx, epoch-1)
activate Store
Store-->>NT: Previous epoch's second-to-last block hash (η_ph)
deactivate Store
NT->>NT: Persist recomputed nonce & update in-memory state
deactivate NT
Client->>NT: GetNonceForEpoch(epoch)
activate NT
NT->>Store: GetPrevHashOfLastBlock(ctx, epoch-1)
activate Store
Store-->>NT: η_ph for epoch transition
deactivate Store
NT->>NT: Compute η = H(η_c || η_ph)
NT-->>Client: []byte (derived nonce)
deactivate NT
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
Summary
GetPrevHashOfLastBlockstore method.RecomputeCurrentEpochNoncetrusted storednonce_valueinstead of recomputing from raw VRF output. AddedGetVrfOutputsForEpoch.Bugs 1+2 compound to produce completely wrong nonces on the auto-leaderlog trigger at the stability window. CLI/manual commands were unaffected (fall through to Koios).
Post-deploy
After deploying, clear cached wrong TICKN nonces:
Test plan
/nonce <epoch>and verify match🤖 Generated with Claude Code
Summary by CodeRabbit