Skip to content

fix: start onchain events ingest from latest block by default - #745

Open
aditiharini wants to merge 3 commits into
mainfrom
start-onchain-events-from-current
Open

fix: start onchain events ingest from latest block by default#745
aditiharini wants to merge 3 commits into
mainfrom
start-onchain-events-from-current

Conversation

@aditiharini

@aditiharini aditiharini commented Jan 9, 2026

Copy link
Copy Markdown
Contributor

When starting a new validator node we end up picking up all blocks from beginning of history by default rather than starting at current. Fix this by starting at current if no explicit bounds are specified.


Note

Medium Risk
Alters default ingest scope for new nodes (recent blocks only unless configured), which is intentional but could surprise operators expecting full historical backfill without an explicit start block.

Overview
Changes the default live-sync start block when start_block_number is unset. Fresh nodes no longer begin at contract deployment (first_block); they start at chain tip minus 500 blocks, floored at first_block.

If the local DB already has a block checkpoint, live sync still resumes from that checkpoint even when it lags far behind the tip, so restarts after downtime do not skip events in the gap.

Adds live_sync_start_block and unit tests for tip-offset, genesis clamping, and checkpoint resume behavior.

Reviewed by Cursor Bugbot for commit 81257a0. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel

vercel Bot commented Jan 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
snapchain-docs Ready Ready Preview, Comment Jul 15, 2026 9:48pm

Request Review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adjusts the default onchain events ingestion start point so new validator nodes don’t backfill from the beginning of chain history when no explicit bounds are configured.

Changes:

  • Introduces a default live-sync start offset from the chain head (LIVE_SYNC_BLOCK_OFFSET).
  • Updates the Subscriber::run() default start-block logic to use (latest_on_chain - offset) as the baseline.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/connectors/onchain_events/mod.rs Outdated
Comment thread src/connectors/onchain_events/mod.rs Outdated
Comment thread src/connectors/onchain_events/mod.rs Outdated
@github-actions

Copy link
Copy Markdown

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • src/connectors/onchain_events/mod.rs (87.2%): Missing lines 1293-1297

Summary

  • Total: 39 lines
  • Missing: 5 lines
  • Coverage: 87%

src/connectors/onchain_events/mod.rs

  1289         );
  1290         let live_sync_block;
  1291         match self.start_block_number {
  1292             None => {
! 1293                 live_sync_block = Some(Self::live_sync_start_block(
! 1294                     latest_block_on_chain,
! 1295                     latest_block_in_db,
! 1296                     Self::first_block(self.chain),
! 1297                 ));
  1298             }
  1299             Some(start_block_number) => {
  1300                 let historical_sync_start_block = latest_block_in_db.max(start_block_number);
  1301                 let historical_sync_stop_block = latest_block_on_chain

@topocount topocount self-assigned this Apr 29, 2026
aditiharini and others added 3 commits July 15, 2026 16:47
Three issues raised in review:

1. Silent skip when DB is behind tip - offset (regression). The original
   default_start.max(latest_block_in_db) only protects when the DB is
   ahead of the offset window. After long downtime or restoring from a
   stale snapshot, latest_block_in_db < tip - offset, so the node would
   jump forward and permanently miss onchain events in the gap. Resume
   from the DB checkpoint whenever one exists; only use the offset for a
   truly fresh start.

2. default_start could fall below the contract-deployment block on chains
   where the tip is near genesis (testnets, future chains). Clamp to
   first_block(chain) so we don't issue invalid pre-deployment RPC log
   queries.

3. No unit coverage for the start-block selection. Extract the logic into
   a pure associated fn (live_sync_start_block) and cover: empty DB →
   tip - offset, empty DB near genesis → clamps to first_block, empty
   DB with tiny tip (saturating_sub edge) → clamps to first_block,
   DB ahead of default → resume from DB, DB behind default → resume from
   DB (the regression guard).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 81257a0. Configure here.

first_block: u64,
) -> u64 {
if latest_block_in_db > 0 {
latest_block_in_db

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checkpoint not clamped to first

Medium Severity

The live_sync_start_block function can return a latest_block_in_db value that's earlier than first_block. If latest_block_in_db is non-zero but below the chain's actual first block, the system might attempt to query events from before contracts existed.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 81257a0. Configure here.

latest_block_on_chain
.saturating_sub(LIVE_SYNC_BLOCK_OFFSET)
.max(first_block)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storage read failure mimics empty

High Severity

live_sync_start_block treats latest_block_in_db == 0 as a fresh node and starts at tip - LIVE_SYNC_BLOCK_OFFSET. latest_block_in_db() also returns 0 when reading the checkpoint fails, so a transient storage error at startup can jump ahead of a real checkpoint and skip onchain events in the gap.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 81257a0. Configure here.

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.

4 participants