Skip to content

V2 api.at(hash) storage map entries() queries the latest state #753

Description

@rossbulat

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions