Conversation
|
Claude finished @cicr99's task in 12m 42s —— View job Review summaryBlocker (1 issue, posted inline on both Swapping This isn't theoretical — this PR's own CI run already shows it: The underlying race is legitimate and worth fixing, but the fix needs a state accessor that pins to a specific block's global state root while still supporting trie reconstruction — e.g., resolving the state root at |
| } | ||
|
|
||
| state, closer, err := h.bcReader.HeadState() | ||
| state, closer, err := h.bcReader.StateAtBlockNumber(chainHeight) |
There was a problem hiding this comment.
Blocker: StateAtBlockNumber returns a state view that cannot serve tries, so this handler now always fails.
h.bcReader.StateAtBlockNumber(chainHeight) returns a stateHistory wrapper (see blockchain/statebackend/statebackend.go → core/state/history.go). Its ClassTrie(), ContractTrie(), and ContractStorageTrie() are explicitly stubbed to return ErrHistoricalTrieNotSupported:
func (s *stateHistory) ClassTrie() (core.TrieReader, error) {
return nil, ErrHistoricalTrieNotSupported
}StorageProof below (lines 215/220 and getContractStorageProof/buildContractLeavesData) calls exactly these methods, which are required to build the Merkle proofs. This makes every real (non-mocked) call to starknet_getStorageProof return ErrInternal.
This isn't hypothetical — this PR's own CI run (Juno Test job, ubuntu-latest, run 34593901648) already fails on the integration test that exercises the real blockchain/state stack:
--- FAIL: TestStorageProof_StorageRoots (1.00s)
--- FAIL: TestStorageProof_StorageRoots/get_contract_proof (0.00s)
Error: Expected nil, but got: &jsonrpc.Error{Code:-32603, Message:"Internal error", ...}
The unit tests in this PR pass only because they mock bcReader.StateAtBlockNumber to return a mock StateReader that doesn't have this trie limitation (storage_test.go, storage_bench_test.go), masking the regression.
The same issue applies to rpc/v9/storage.go:96.
HeadState() returns a plain *StateReader (real trie access), whereas StateAtBlockNumber returns the history-view used for point-in-time historical queries, which deliberately doesn't support trie reconstruction. Since this handler only ever proves state at the current chain height (never truly historical, since isBlockSupported restricts to head-only anyway), swapping to StateAtBlockNumber breaks proof generation. The original race is real, but this fix needs a state accessor that pins to a specific block's root while still supporting ClassTrie/ContractTrie/ContractStorageTrie — e.g. reading the state root at chainHeight directly and constructing a state.NewStateReader(stateRoot, ...), or extending the history path to support trie reads.
| } | ||
|
|
||
| state, closer, err := h.bcReader.HeadState() | ||
| state, closer, err := h.bcReader.StateAtBlockNumber(chainHeight) |
There was a problem hiding this comment.
Blocker: same issue as rpc/v10/storage.go:209. StateAtBlockNumber returns a stateHistory whose ClassTrie()/ContractTrie()/ContractStorageTrie() return ErrHistoricalTrieNotSupported, so this handler's calls to those methods below will always error. Confirmed failing in this PR's own CI: TestStorageProof_StorageRoots/get_contract_proof in rpc/v9 fails with ErrInternal. See the detailed comment on rpc/v10/storage.go:209 for the full explanation and suggested fix.
User description
Summary
Fixes a race condition in
starknet_getStorageProofwhen resolvinglatest. (Reference to the comment here)Before this change, the handler read the current chain height, validated the requested block against that height, and then opened
HeadState(). If a new block was accepted between those two operations, the response could use metadata from blocknwhile reading state from blockn + 1.This updates the handler to open state explicitly at the validated block number instead of using the moving head state.
Notes
This is a tactical fix for the existing inconsistency. A longer-term solution would be to use a DB snapshot so the chain height, header/hash lookup, and state access are all served from the same underlying database view.
PR Type
Bug fix, Tests
Description
Pin state to validated height
Replace
Update v9/v1 tests
File Walkthrough
storage.go
Pin state atrpc/v10/storage.go
Headwith `Preserve state to validated height
storage.go
Pin state atrpc/v9/storage.go
Headwith `Preserve existing-height validation
storage_bench_test.go
Update storage proof benchmark mocksrpc/v10/storage_bench_test.go
Use `
storage_test.go
Update storage test mocksrpc/v10/storage_test.go
Use `
storage_test.go
Update v test mocksrpc/v9/storage_test.go
Use `