Skip to content

Use consistent chain-state snapshots for multi-query RPC methods #10550

Description

@mpguerra

Motivation

Several RPC methods issue multiple sequential ReadStateService queries and combine the results into a single response. Each oneshot call independently samples the latest best chain, so a reorg or tip advance between queries can produce internally inconsistent responses. The getrawtransaction instance of this pattern was fixed in PR #10523; three sibling sites remain.

Affected methods

getblock (verbosity 1 and 2) — resolves the header by height, then fetches transactions using the original height instead of the resolved hash. A reorg between the two reads can mix block A's header with block B's transactions. For verbosity 2, transactions from the wrong block are labeled with the resolved block's hash.

getblockheader (verbose) — resolves the header, then fetches SaplingTree and Depth in separate queries. The confirmations field derived from Depth can be stale if the tip advances between queries. The maintainer comment at methods.rs:1494 already acknowledges the reorg race for SaplingTree.

gettxout — issues three separate queries: Tip, Transaction, and IsTransparentOutputSpent. A block landing between the transaction fetch and the spent check can produce a false "unspent" response for an already-spent output. The maintainer TODO at methods.rs:3113-3114 acknowledges this gap.

Fix

Apply the same pattern as the patched getrawtransaction (PR #10523): after the first state query resolves a concrete block hash, use that hash for all subsequent queries. For gettxout, capture the tip from the transaction query rather than issuing a separate Tip request.

Reported by x15-eth (getblock) and lynchmobb (getblockheader, gettxout).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions