py-substrate-interface icon indicating copy to clipboard operation
py-substrate-interface copied to clipboard

Error composing call using latest substrate

Open DylanVerstraete opened this issue 2 years ago • 4 comments

When using using substrate on branch polkadot-0.9.42 we got the following error trying to compose a call:

File "/home/dylan/Projects/tfchain/substrate-node/tests/TfChainClient.py", line 178, in create_farm
    call = substrate.compose_call("TfgridModule", "create_farm",
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dylan/.local/lib/python3.11/site-packages/substrateinterface/base.py", line 1380, in compose_call
    call.encode({
  File "/home/dylan/.local/lib/python3.11/site-packages/scalecodec/base.py", line 925, in encode
    self.data = self.process_encode(self.value_serialized)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dylan/.local/lib/python3.11/site-packages/scalecodec/types.py", line 1687, in process_encode
    data += arg_obj.encode(param_value)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dylan/.local/lib/python3.11/site-packages/scalecodec/base.py", line 925, in encode
    self.data = self.process_encode(self.value_serialized)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dylan/.local/lib/python3.11/site-packages/scalecodec/types.py", line 663, in process_encode
    raise ValueError('Element count of value ({}) doesn\'t match type_definition ({})'.format(
ValueError: Element count of value (0) doesn't match type_definition (1)

DylanVerstraete avatar Jun 05 '23 12:06 DylanVerstraete

I'm not sure which runtime you are connecting to, but it seems the parameter structure changed/is incorrect for that call.

What you can do is to check the composition of the params for that call: https://polkascan.github.io/py-substrate-interface/usage/extrinsics/#type-decomposition-of-call-params

More information how to interpret that info: https://polkascan.github.io/py-substrate-metadata-docs/

If your runtime is already listed there you can directly lookup the call param composition info.

arjanz avatar Jun 07 '23 13:06 arjanz

Seems like on latest polkadot if a call has like a vector of something (some objects) as input, the input needs to be wrapped with another [ ] when using this library. See: https://github.com/threefoldtech/tfchain/blob/5605bca61c79742317d21f48c4689370392b9c2d/substrate-node/tests/TfChainClient.py#L250

DylanVerstraete avatar Jun 12 '23 11:06 DylanVerstraete

That is indeed strange. I can examine the structure in the PortableRegistry to see why, if it would be possible for you to share a public endpoint or the hex-data of state_getMetadata RPC call here?

arjanz avatar Jun 14 '23 12:06 arjanz

I ran some tests on the product endpoint I found on the tfchain Github, I could compose the call above as followed:

Retrieve the type composition with:

call_function = substrate.get_metadata_call_function("TfgridModule", "create_node")
params = call_function.get_param_info()
# {'farm_id': 'u32', 'resources': {'hru': 'u64', 'sru': 'u64', 'cru': 'u64', 'mru': 'u64'}, 'location': {'city': 'Bytes', 'country': 'Bytes', 'latitude': 'Bytes', 'longitude': 'Bytes'}, 'interfaces': [{'name': 'Bytes', 'mac': 'Bytes', 'ips': ['Bytes']}], 'secure_boot': 'bool', 'virtualized': 'bool', 'serial_number': (None, 'Bytes')}

Then entered some dummy data:

call = substrate.compose_call("TfgridModule", "create_node", {
    'farm_id': 1,
    'resources': {'hru': 1, 'sru': 1, 'cru': 1, 'mru': 1},
    'location': {'city': 'Test', 'country': 'Test', 'latitude': 'Test', 'longitude': 'Test'},
    'interfaces': [{'name': 'Test', 'mac': 'Test', 'ips': ['Test', 'Test2']}, {'name': 'Test2', 'mac': 'Test2', 'ips': ['Test', 'Test2']}],
    'secure_boot': True, 'virtualized': True, 'serial_number': None
})
# 0x0b0801000000010000000000000001000000000000000100000000000000010000000000000010546573741054657374105465737410546573740810546573741054657374081054657374145465737432145465737432145465737432081054657374145465737432010100

Seems my interface param is a bit more complex than the nested list you provided, or are you on a different network?

arjanz avatar Jun 15 '23 12:06 arjanz