polkadot-js / api

Promise and RxJS APIs around Polkadot and Substrate based chains via RPC calls. It is dynamically generated based on what the Substrate runtime provides in terms of metadata.
Apache License 2.0
1.07k stars 350 forks source link

api.query.system.account.at throws error for old block hashes #3708

Closed fkbenjamin closed 3 years ago

fkbenjamin commented 3 years ago

Following the example at https://polkadot.js.org/docs/api/examples/promise/read-storage-at/, trying to query for the balance at an old block hash (e.g. Block 1: 0xcd9b8e2fc2f57c4570a86319b005832080e0c478ab41ae5d44e23705872f5ad3 or Block 1000000: 0xb267ffd706bbb93779eab04f47c7038031657b0a863794dbdd73170e3976c3e7)) results in the following error:

2021-06-28 13:35:55        RPC-CORE: getStorage(key: StorageKey, at?: BlockHash): StorageData:: Unable to decode storage system.account:: createType(AccountInfo):: {"nonce":"Index","refcount":"RefCount","data":"AccountData"}:: Decoded input doesn't match input, received 0x0000000000000000000000000000000000000000000000000000000000000000…0000000000000000000000000000000000000000000000000000000000000000 (80 bytes), created 0x0000000000000000000000000000000000000000000000000000000000000000…0000000000000000000000000000000000000000000000000000000000000000 (69 bytes)
Error: Unable to decode storage system.account:: createType(AccountInfo):: {"nonce":"Index","refcount":"RefCount","data":"AccountData"}:: Decoded input doesn't match input, received 0x0000000000000000000000000000000000000000000000000000000000000000…0000000000000000000000000000000000000000000000000000000000000000 (80 bytes), created 0x0000000000000000000000000000000000000000000000000000000000000000…0000000000000000000000000000000000000000000000000000000000000000 (69 bytes)
    at RpcCore._newType (/Users/user/kusama-genesis-balance/node_modules/@polkadot/rpc-core/index.cjs:457:13)
    at RpcCore._formatStorageData (/Users/user/kusama-genesis-balance/node_modules/@polkadot/rpc-core/index.cjs:391:17)
    at RpcCore._formatOutput (/Users/user/kusama-genesis-balance/node_modules/@polkadot/rpc-core/index.cjs:368:19)
    at callWithRegistry (/Users/user/kusama-genesis-balance/node_modules/@polkadot/rpc-core/index.cjs:247:42)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

I am using wss://kusama-rpc.polkadot.io/ for these queries, which is a confirmed archive node (https://guide.kusama.network/docs/kusama-endpoints/)

Polkadot API is at version 4.16.2

jacogr commented 3 years ago

Ok... now that I think through it.

So the issue is that at block 1, there was no api.query.system.account.at entry. So it will indeed return the current defaults. For really old just-post-genesis blocks the balances used to be stored in balances.freeBalance, then it moved to balances.account for a short while (< 7 days) and then into the current position at system.account.

haikoschol commented 3 years ago

I'm running into the same issue on Polkadot.

Example inputs:

Should it be possible to query balances from all three locations with the current version of polkadot-js/api? Or do I need to find a matching version?

In 4.16.2, both api.query.balances.freeBalance and api.query.balances.reservedBalance are undefined.

jacogr commented 3 years ago

Yes, so they will be undefined - since those storage locations don't exist anymore in the metadata. And the API endpoints are decorated based on the current metadata. The is the only way to solve that via #3585 - which is some way away, i.e. decorate API with historic stuff.

To query those current non-existing ones - you will need to manually construct a key, then query and then decode the values based on the types. (Until the above enhancement gos in at some point, i.e. get metadata first, decorate at that point, then only allow queries)

fkbenjamin commented 3 years ago

Hey @jacogr, thanks for clarifying. Does that mean it's currently not possible to get these historic balances from the chain?

jacogr commented 3 years ago

It is in the trie, so you can.

Query the storage with the correctly constructed key and decode. (As mentioned above) Since it is not decorated and not in the current metadata the API cannot provide help here. So you basically need to do it via getStorage RPC.

So the data is there, but the API provides no helpers to get to it.

haikoschol commented 3 years ago

@fkbenjamin Here's a great explanation on how to use the getStorage RPC and it even happens to use Balances.FreeBalance as an example: https://www.shawntabrizi.com/substrate/querying-substrate-storage-via-rpc/

fkbenjamin commented 3 years ago

Thanks @haikoschol , I'll check that link out! :)

jacogr commented 3 years ago

As of 4.17.1 the form such as api.at(<blockHash>).query.balances.freeBalance(<address>) will return the values

haikoschol commented 3 years ago

Thanks @jacogr!

One correction regarding my comment above: The changes to how balances are stored were made before Polkadot went live. That means, this issue only exists on Kusama and I was mistaken about the error I saw. The real issue was that some of the accounts I was querying simply didn't exist that far back. However, I'll have to do the same for Kusama and this will come in very handy!

polkadot-js-bot commented 3 years ago

This issue has been open for 21 days with no activity and is not labelled as an enhancement. It will be closed in 7 days.

polkadot-js-bot commented 3 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue if you think you have a related problem or query.