Skip to content

fix(icp-rosetta): give ledger blocks ledger parents in Rosetta blocks mode - #11964

Open
basvandijk wants to merge 1 commit into
masterfrom
ai/icp-rosetta-ledger-block-parents-2026-10-27
Open

basvandijk wants to merge 1 commit into
masterfrom
ai/icp-rosetta-ledger-block-parents-2026-10-27

Conversation

@basvandijk

@basvandijk basvandijk commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

In Rosetta blocks mode, ICP Rosetta's /block serves ledger blocks below the first Rosetta block index F, and Rosetta blocks from F on. A Rosetta block holds one or more ledger blocks, so from F on, Rosetta block indices fall behind ledger block indices. create_parent_block_id resolves a parent at index F or above as a Rosetta block. That is right for Rosetta blocks, but the request handler also used it for ledger blocks:

  • /call query_block_range gave ledger blocks Rosetta blocks as parents. When no Rosetta block had the parent's index, as for the newest ledger blocks, it failed with Block not found.
  • /search/transactions failed the same way. It computed each block's parent only to discard it.
  • /block and /account/balance with only the hash of a ledger block returned a Rosetta parent, or panicked: get_block treats an InvalidBlockId error from the ledger lookup as a Rosetta block hash, and calls todo!("Fetching Rosetta Blocks by hash is not supported yet").

The first two were reported in #11962. This PR builds on its create_parent_block_id over &Blocks.

Fix

  • New ledger_block_parent_id: the parent of a ledger block is the previous ledger block, looked up as with Rosetta blocks disabled. It must be verified, and the genesis block is its own parent.
  • query_block_range, and hashed_block_to_rosetta_core_block, which converts the ledger blocks of /block, /block/transaction, /account/balance and /network/status, use it.
  • /search/transactions builds each block identifier and transaction directly from the ledger block, without a parent.
  • create_parent_block_id is renamed rosetta_block_parent_id and is now only used for Rosetta blocks. Below F it uses ledger_block_parent_id.

With Rosetta blocks disabled, responses don't change, with one exception: /search/transactions no longer fails with Block not found when its result includes the oldest block of a pruned store. That block is the first one after the pruned blocks, which /network/status reports as oldest_block_identifier, and its parent is gone. That is the only change in the released image, which is built without the rosetta-blocks feature.

In Rosetta blocks mode, query_block_range ranges that reach unverified ledger blocks now fail with the same retriable InvalidBlockId error as with Rosetta blocks disabled, instead of Block not found.

Testing

New tests in request_handler/tests.rs build their stores the way a sync does:

  • test_ledger_blocks_have_ledger_parents_in_rosetta_blocks_mode uses F = 0, with three ledger blocks per Rosetta block.
  • test_ledger_blocks_have_ledger_parents_after_the_first_rosetta_block uses F = 2, from a store reopened with Rosetta blocks enabled.

Both check that query_block_range (every range from the genesis block), /search/transactions and /block by the hash of every ledger block return the same as with Rosetta blocks disabled. They also check that Rosetta blocks keep their Rosetta parents.

test_search_transactions_in_pruned_store searches a pruned store with Rosetta blocks disabled.

request_handler.rs F = 0 F = 2 pruned store
#11962 fails fails fails
only query_block_range fixed fails fails fails
everything fixed except /block by hash fails fails passes
below F, the ledger parent of the parent index (off by one) passes fails passes
/search/transactions resolves ledger parents passes passes fails
this PR passes passes passes

With this PR, only Rosetta blocks reach rosetta_block_parent_id, the method that deadlocked in #11962. So #11962's test_requests_do_not_deadlock_with_concurrent_writer now also runs with Rosetta blocks enabled. A variant of this PR that takes the read lock again in that method fails only the new Rosetta blocks run.

All 11 non-system test targets that depend on the changed files pass locally, including rosetta-integration_tests and the ICRC Rosetta suites. So do the four _local variants of the rs/tests/financial_integrations/rosetta system tests, which PR CI doesn't run because they're tagged long_test. Their Farm variants weren't run.

Not changed here

  • In Rosetta blocks mode, query_block_range and /search/transactions still return ledger block identifiers (the TODO in query_block_range), while from F on /block serves Rosetta blocks at those indices. This PR makes the ledger blocks they return consistent with each other, not with the Rosetta blocks.
  • In Rosetta blocks mode, /block by the hash of a stored but unverified ledger block still panics in the todo!().
  • In Rosetta blocks mode, /account/balance at Rosetta block r returns the balance at ledger block r, not at the last ledger block in Rosetta block r.
  • With Rosetta blocks disabled, /block and query_block_range still fail for the oldest block of a pruned store, whose parent is gone, although /network/status reports it as the oldest block.

This PR fixes an issue reported in #11962, which was created following the steps in .claude/skills/fix-flaky-tests/SKILL.md.

🤖 Generated with Claude Code

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.

🟢 Approval recommended

The focused changes preserve Rosetta parent behavior, cover the affected boundaries with regression tests, and have no identified blocking issues.

No open issues 🎉

What changed in this PR

This PR fixes ledger-block parent identifiers in ICP Rosetta’s Rosetta blocks mode, building on the earlier read-lock deadlock fix.

Changes:

  • Separates ledger and Rosetta parent lookups while preserving the boundary between their chains.
  • Removes unnecessary parent lookups from transaction searches, allowing searches to include the oldest retained block after pruning.
  • Adds regression coverage for both Rosetta-mode boundaries, pruned stores, and concurrent writer access.
File Description
rs/​rosetta-api/​icp/​src/​request_handler/​tests.rs Adds parent-chain and pruning tests; extends concurrent-access coverage to Rosetta blocks mode.
rs/​rosetta-api/​icp/​src/​request_handler.rs Uses ledger-specific parent lookup and converts search results without resolving parents.

Review effort: Balanced

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.

🟢 Approval recommended

No active review issues remain for the ledger/Rosetta parent-resolution and transaction-search changes.

No open issues 🎉

Review effort: Balanced

@basvandijk
basvandijk marked this pull request as ready for review October 28, 2026 10:27
@basvandijk
basvandijk requested a review from a team as a code owner October 28, 2026 10:27
@github-actions github-actions Bot added the @defi label Oct 28, 2026
@zeropath-ai

zeropath-ai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

✅ No security or compliance issues detected. Reviewed everything up to ab080c8.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► rs/rosetta-api/icp/src/request_handler.rs
      Replace create_parent_block_id with ledger_block_parent_id in several call paths
► rs/rosetta-api/icp/src/request_handler.rs
      Rename create_parent_block_id to rosetta_block_parent_id and adjust usages
► rs/rosetta-api/icp/src/request_handler.rs
      Introduce ledger_block_parent_id helper and related logic
► rs/rosetta-api/icp/src/request_handler/tests.rs
      Update tests to accommodate new parent id logic and Rosetta blocks mode
► rs/rosetta-api/icp/src/request_handler/tests.rs
      Add tests for ledger block parent handling in Rosetta blocks mode
► rs/rosetta-api/icp/src/request_handler/tests.rs
      Add utility functions for ledger blocks creation and synchronization
► rs/rosetta-api/icp/src/request_handler/tests.rs
      Add tests for pruned store transaction search and Rosetta blocks interactions

Base automatically changed from ai/icp-rosetta-reentrant-read-deadlock-2026-10-27 to master October 28, 2026 10:32
… mode

In Rosetta blocks mode, create_parent_block_id looks up a parent at or
after the first Rosetta block index as a Rosetta block. The request
handler also used it for ledger blocks, whose indices differ from Rosetta
block indices from the first Rosetta block on. So query_block_range gave
ledger blocks Rosetta blocks as parents or failed with "Block not found",
/search/transactions failed the same way, and /block and /account/balance
with only the hash of a ledger block got a Rosetta parent or panicked in
get_block's todo!() for Rosetta block hashes.

Ledger blocks now get the previous ledger block as parent, looked up as
with Rosetta blocks disabled, and create_parent_block_id becomes
rosetta_block_parent_id, which only Rosetta blocks use.
/search/transactions no longer computes parents, which it never returned,
so it also no longer fails when it returns the oldest block of a pruned
store.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@basvandijk
basvandijk force-pushed the ai/icp-rosetta-ledger-block-parents-2026-10-27 branch from 9a0e9d3 to ab080c8 Compare October 28, 2026 10:32
@basvandijk
basvandijk requested a balanced review from Copilot October 28, 2026 10:36

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.

🟢 Approval recommended

No active review issues were identified for the ledger-parent and transaction-search changes.

No open issues 🎉

Review effort: Balanced

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants