polkascan / py-substrate-interface

Python Substrate Interface
https://polkascan.github.io/py-substrate-interface/
Apache License 2.0
240 stars 114 forks source link

substrateinterface.exceptions.StorageFunctionNotFound: Storage function "Substrate.Code" not found #190

Closed BulatSaif closed 2 years ago

BulatSaif commented 2 years ago

How to run build-in Storage functions? If my understanding is correct substrate has pallet functions (Example Sudo.Key) and build-in functions ( Example Substrate.Code)

From https://polkadot.js.org/ I can query both types, but SubstrateInterface fails to query build-in functions: image

image

Steps to reproduce

Start local node:

docker run -it --rm -p 9944:9944 parity/polkadot:v0.9.16 --unsafe-ws-external --chain rococo-local

Run this code

substrate = SubstrateInterface(
    url="ws://127.0.0.1:9944",
)

print(substrate.query(
        module='Sudo',
        storage_function='Key',
        params=[]
    ))

print(substrate.query(
        module='Substrate',
        storage_function='Code',
        params=[]
    ))

Current output

5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
Traceback (most recent call last):
  File "./balance_transfer.py", line 56, in <module>
    print(substrate.query(
  File "/home/bulat/.local/lib/python3.8/site-packages/substrateinterface/base.py", line 1276, in query
    raise StorageFunctionNotFound('Storage function "{}.{}" not found'.format(module, storage_function))
substrateinterface.exceptions.StorageFunctionNotFound: Storage function "Substrate.Code" not found

Expected output

5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
0x52bc537646db8e0528b52ffd00586c9b040ee485ef125520ceba9a0ec32bdabd…

Versions

$ python3 --version 
Python 3.8.10
$ pip list | grep subs
substrate-interface    1.2.0 
arjanz commented 2 years ago

I checked the storage functions in the metadata of the Rococo runtime (with substrate.get_metadata_storage_functions()), and indeed no pallet named Substrate. At this point I have no idea how PolkadotJS retrieves this, I will have to look into it.

arjanz commented 2 years ago

Ok mystery solved, apparently there is a list of 'well-known' storage keys in Substrate, that are not exposed in the metadata:

https://github.com/paritytech/substrate/blob/ded44948e2d5a398abcb4e342b0513cb690961bb/primitives/storage/src/lib.rs#L192-L238

I will have to add those keys manually in the library and for consistency I will use the same convention as in PolkadotJS

Until that is released what you can do is use the encoded storage key as shown in PolkadotJS:

Screenshot 2022-02-12 at 15 08 15

And use that to retrieve the raw result:

block_hash = substrate.get_chain_head()
code_result = substrate.get_storage_by_key(block_hash, "0x3a636f6465")
BulatSaif commented 2 years ago

Thank you for a solution, It works, I was wondering, how to use an encoded storage key