Description
With a JSON-RPC v2 client, enumerating a storage map through a historical client created by api.at(blockHash) returns entries from the latest chain state instead of the requested block.
Keyed historical queries use the requested block correctly. The problem is specific to map enumeration methods backed by descendantsValues, including entries().
Reproduction
const historical = await api.at(historicalBlockHash)
const historicalEntries = await historical.query.staking.validators.entries()
const currentEntries = await api.query.staking.validators.entries()
// Unexpected: historicalEntries contains the same validator set as currentEntries.
At the same historical block:
- querying raw storage for a validator introduced later returns no value;
- legacy RPC
historical.query.staking.validators.entries() excludes that validator;
- V2
historical.query.staking.validators.entries() includes it and matches the current set.
The same behavior was observed with an era-prefixed map query such as erasStakersOverview.entries(era).
Root cause
StorageQueryExecutorV2.exposeStorageMapMethods() calls:
this.chainHead.storage([{ type: 'descendantsValues', key }])
without forwarding this.atBlockHash. Other V2 storage query paths pass the historical hash as the third argument.
Expected behavior
All storage operations exposed by an api.at(blockHash) client, including map entries(), should resolve against blockHash.
Environment
Reproduced with @dedot/api 1.0.4. The same call path is present in 1.3.0.
Description
With a JSON-RPC v2 client, enumerating a storage map through a historical client created by
api.at(blockHash)returns entries from the latest chain state instead of the requested block.Keyed historical queries use the requested block correctly. The problem is specific to map enumeration methods backed by
descendantsValues, includingentries().Reproduction
At the same historical block:
historical.query.staking.validators.entries()excludes that validator;historical.query.staking.validators.entries()includes it and matches the current set.The same behavior was observed with an era-prefixed map query such as
erasStakersOverview.entries(era).Root cause
StorageQueryExecutorV2.exposeStorageMapMethods()calls:without forwarding
this.atBlockHash. Other V2 storage query paths pass the historical hash as the third argument.Expected behavior
All storage operations exposed by an
api.at(blockHash)client, including mapentries(), should resolve againstblockHash.Environment
Reproduced with
@dedot/api1.0.4. The same call path is present in 1.3.0.