Skip to content

fix: Make sure entire tree get's restored#253

Open
cichaczem wants to merge 4 commits intomainfrom
cichaczem/local-setup
Open

fix: Make sure entire tree get's restored#253
cichaczem wants to merge 4 commits intomainfrom
cichaczem/local-setup

Conversation

@cichaczem
Copy link
Contributor

@cichaczem cichaczem commented Jan 22, 2026

Note

Fully restores the in-memory Merkle tree when loading from mmap by rehydrating sparse leaves from the database and validating the root before replay.

  • Add fetch_sparse_leaves query and integrate into tree initialization/sync to rebuild leaves beyond the dense prefix; verify restored root before event replay
  • Update backfill to throttle with INDEXER_POLL_INTERVAL_SECS and wire through config/env; propagate to tests
  • Extend tests: numerous updates to include poll_interval_secs and a new sparse-leaf restoration test ensuring roots match on-chain after restart
  • Improve local tooling: add check-db.sh and test-create-account.sh; enhance local-setup.sh to capture forge output, load .env, and pass deployed registry to gateway
  • Update .env.example with INDEXER_POLL_INTERVAL_SECS and minor defaults

Written by Cursor Bugbot for commit 50ad2ea. This will update automatically on new commits. Configure here.

Copy link

@cursor cursor bot left a comment

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 and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if restored_root != metadata.root_hash {
anyhow::bail!(
"Root mismatch: expected {}, got {}",
"Root mismatch after sparse restore: expected {}, got {}",
Copy link

Choose a reason for hiding this comment

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

Sparse leaf restoration causes unnecessary full rebuilds

Medium Severity

The sparse leaf restoration fetches leaves from the accounts table (current state) but then verifies the root against metadata.root_hash (historical state). When events_behind > 0 and any pending events modified sparse leaves, the accounts table already contains updated values, causing root mismatch. The code interprets this as cache corruption and triggers a full rebuild, even though incremental replay would be correct. In sync_with_db, this happens every time the external indexer updates a sparse leaf, defeating the purpose of incremental sync.

Additional Locations (1)

Fix in Cursor Fix in Web

.parse::<U256>()
.map_err(|e| anyhow::anyhow!("Failed to parse commitment: {}", e))?;
tree = tree.update_with_mutation(*leaf_index, &commitment);
}
Copy link

Choose a reason for hiding this comment

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

Missing leaf index bounds validation in sparse restoration

Medium Severity

The sparse leaf restoration code passes leaf_index values from the database directly to update_with_mutation without validating they are within tree capacity (2^tree_depth). The comparable full rebuild path in fetch_and_parse_leaves_batch explicitly validates that leaf_index < capacity before use. If the database contains a corrupted or malformed leaf index exceeding tree capacity (from data corruption or manual DB manipulation), calling update_with_mutation with an out-of-bounds index could cause a panic or undefined behavior.

Additional Locations (1)

Fix in Cursor Fix in Web

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