Repository navigation
fix(icp-rosetta): give ledger blocks ledger parents in Rosetta blocks mode - #11964
Open
basvandijk wants to merge 1 commit into
Open
basvandijk wants to merge 1 commit into
basvandijk wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
🟢 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
|
✅ No security or compliance issues detected. Reviewed everything up to ab080c8. Security OverviewDetected Code Changes
|
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
force-pushed
the
ai/icp-rosetta-ledger-block-parents-2026-10-27
branch
from
October 28, 2026 10:32
9a0e9d3 to
ab080c8
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In Rosetta blocks mode, ICP Rosetta's
/blockserves 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_idresolves 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:/callquery_block_rangegave ledger blocks Rosetta blocks as parents. When no Rosetta block had the parent's index, as for the newest ledger blocks, it failed withBlock not found./search/transactionsfailed the same way. It computed each block's parent only to discard it./blockand/account/balancewith only the hash of a ledger block returned a Rosetta parent, or panicked:get_blocktreats anInvalidBlockIderror from the ledger lookup as a Rosetta block hash, and callstodo!("Fetching Rosetta Blocks by hash is not supported yet").The first two were reported in #11962. This PR builds on its
create_parent_block_idover&Blocks.Fix
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, andhashed_block_to_rosetta_core_block, which converts the ledger blocks of/block,/block/transaction,/account/balanceand/network/status, use it./search/transactionsbuilds each block identifier and transaction directly from the ledger block, without a parent.create_parent_block_idis renamedrosetta_block_parent_idand is now only used for Rosetta blocks. Below F it usesledger_block_parent_id.With Rosetta blocks disabled, responses don't change, with one exception:
/search/transactionsno longer fails withBlock not foundwhen its result includes the oldest block of a pruned store. That block is the first one after the pruned blocks, which/network/statusreports asoldest_block_identifier, and its parent is gone. That is the only change in the released image, which is built without therosetta-blocksfeature.In Rosetta blocks mode,
query_block_rangeranges that reach unverified ledger blocks now fail with the same retriableInvalidBlockIderror as with Rosetta blocks disabled, instead ofBlock not found.Testing
New tests in
request_handler/tests.rsbuild their stores the way a sync does:test_ledger_blocks_have_ledger_parents_in_rosetta_blocks_modeuses F = 0, with three ledger blocks per Rosetta block.test_ledger_blocks_have_ledger_parents_after_the_first_rosetta_blockuses F = 2, from a store reopened with Rosetta blocks enabled.Both check that
query_block_range(every range from the genesis block),/search/transactionsand/blockby 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_storesearches a pruned store with Rosetta blocks disabled.request_handler.rsquery_block_rangefixed/blockby hash/search/transactionsresolves ledger parentsWith this PR, only Rosetta blocks reach
rosetta_block_parent_id, the method that deadlocked in #11962. So #11962'stest_requests_do_not_deadlock_with_concurrent_writernow 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_testsand the ICRC Rosetta suites. So do the four_localvariants of thers/tests/financial_integrations/rosettasystem tests, which PR CI doesn't run because they're taggedlong_test. Their Farm variants weren't run.Not changed here
query_block_rangeand/search/transactionsstill return ledger block identifiers (the TODO inquery_block_range), while from F on/blockserves Rosetta blocks at those indices. This PR makes the ledger blocks they return consistent with each other, not with the Rosetta blocks./blockby the hash of a stored but unverified ledger block still panics in thetodo!()./account/balanceat Rosetta blockrreturns the balance at ledger blockr, not at the last ledger block in Rosetta blockr./blockandquery_block_rangestill fail for the oldest block of a pruned store, whose parent is gone, although/network/statusreports 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