Skip to content

fix(nonce): prevent computing nonces from incomplete chain data#76

Merged
wcatz merged 1 commit intomasterfrom
fix/nonce-incomplete-sync-guard
Feb 12, 2026
Merged

fix(nonce): prevent computing nonces from incomplete chain data#76
wcatz merged 1 commit intomasterfrom
fix/nonce-incomplete-sync-guard

Conversation

@wcatz
Copy link
Copy Markdown
Owner

@wcatz wcatz commented Feb 12, 2026

Summary

  • Root cause: GetNonceForEpoch in full mode called ComputeEpochNonce during sync, when the DB only had blocks for epochs 208-222 plus live epoch 612. The 390-epoch gap produced a garbage nonce that got permanently cached.
  • Fix: Check GetLastSyncedSlot vs the target epoch's end slot before computing locally. Falls through to Koios when sync is incomplete.
  • Deleted the bad nonces and schedules from goduckbot_test DB already.

What changed

  • GetNonceForEpoch now only computes from local chain data when sync has passed the target epoch
  • When sync is incomplete, falls through to Koios (previously only used in lite mode)

Test plan

  • go build && go vet && go test — all pass
  • Deploy to test — verify nonces come from Koios during sync, then from local computation after sync completes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Improvements

    • Enhanced nonce retrieval: uses local chain data only when fully synced, otherwise falls back to Koios; successful chain or Koios results are cached.
    • Improved logging for sync-vs-fallback scenarios to increase visibility.
  • New Features

    • Commands now check sync status and will notify users when historical synchronization is in progress, delaying certain operations (e.g., leaderlog, nonce, validate, nextblock) until sync completes.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 12, 2026

📝 Walkthrough

Walkthrough

GetNonceForEpoch in nonce.go was changed to be sync-aware: it computes the epoch nonce from chain data only if the node has synced past the epoch end; otherwise it falls back to Koios. Sync state gating was added across command handlers and the indexer lifecycle to avoid running while historical sync is in progress.

Changes

Cohort / File(s) Summary
Nonce sync-aware logic
nonce.go
GetNonceForEpoch now checks last synced slot vs. epoch end; if fully synced it computes nonce from chain and caches it, otherwise falls back to Koios and caches Koios result. Logging updated to indicate sync-based fallback.
Indexer sync flag & gating
main.go
Added historicalSyncDone int32 to Indexer, isSynced() helper, set flag for lite mode and at sync completion; leaderlog scheduling now skips while historical sync is incomplete.
Command handlers sync guard
commands.go
Added requireSynced(m *telebot.Message) bool and applied it to several commands (Leaderlog, Nonce, Validate, NextBlock) to prevent execution during historical sync.

Sequence Diagram

sequenceDiagram
    participant Caller as Caller
    participant Indexer as Indexer / isSynced
    participant GetNonce as GetNonceForEpoch
    participant Chain as Chain Data Compute
    participant Koios as Koios Service
    participant DB as Nonce Cache (DB)

    Caller->>GetNonce: Request epoch nonce
    GetNonce->>Indexer: Check last synced slot / isSynced
    alt synced_slot >= epoch_end_slot
        GetNonce->>Chain: Compute nonce from chain data
        Chain-->>GetNonce: Computed nonce
        GetNonce->>DB: Cache nonce
        DB-->>GetNonce: Cached
        GetNonce-->>Caller: Return chain-derived nonce
    else not synced
        GetNonce->>Koios: Request nonce (fallback)
        Koios-->>GetNonce: Koios nonce
        GetNonce->>DB: Cache Koios nonce
        DB-->>GetNonce: Cached
        GetNonce-->>Caller: Return Koios nonce
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Hopping through slots with careful delight,

If sync's not complete, Koios keeps things right.
When chains are all caught up, compute and then store,
Cache the true nonce — then hop off once more.
A rabbit's small cheer for sync-aware lore! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(nonce): prevent computing nonces from incomplete chain data' directly and clearly summarizes the main change: adding a guard to prevent nonce computation when chain data is incomplete.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/nonce-incomplete-sync-guard

No actionable comments were generated in the recent review. 🎉


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.

Two fixes:

1. GetNonceForEpoch sync guard: In full mode, check GetLastSyncedSlot
   against the target epoch's end slot before computing locally. Falls
   through to Koios when sync is incomplete, preventing garbage nonces
   from being cached.

2. Historical sync gate: Add historicalSyncDone atomic flag. All
   data-dependent commands (leaderlog, nonce, nextblock, validate)
   and the auto leaderlog trigger return early with "sync in progress"
   until historical sync completes. Lite mode starts synced.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wcatz wcatz force-pushed the fix/nonce-incomplete-sync-guard branch from d91cb20 to e74180e Compare February 12, 2026 18:13
@wcatz wcatz merged commit 196a3ef into master Feb 12, 2026
2 checks passed
@wcatz wcatz deleted the fix/nonce-incomplete-sync-guard branch February 12, 2026 18:23
wcatz added a commit that referenced this pull request Feb 18, 2026
Two fixes:

1. GetNonceForEpoch sync guard: In full mode, check GetLastSyncedSlot
   against the target epoch's end slot before computing locally. Falls
   through to Koios when sync is incomplete, preventing garbage nonces
   from being cached.

2. Historical sync gate: Add historicalSyncDone atomic flag. All
   data-dependent commands (leaderlog, nonce, nextblock, validate)
   and the auto leaderlog trigger return early with "sync in progress"
   until historical sync completes. Lite mode starts synced.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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