Skip to content

Commit 9367d83

Browse files
committed
WIP check-in
1 parent b675fa2 commit 9367d83

File tree

2 files changed

+253
-370
lines changed

2 files changed

+253
-370
lines changed

async_substrate_interface/async_substrate.py

Lines changed: 44 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
)
2424

2525
from bt_decode import MetadataV15, PortableRegistry, decode as decode_by_type_string
26-
from scalecodec.base import ScaleBytes, ScaleType, RuntimeConfigurationObject
26+
from scalecodec.base import ScaleBytes, ScaleType
2727
from scalecodec.types import (
2828
GenericCall,
2929
GenericExtrinsic,
@@ -787,15 +787,9 @@ def __init__(
787787
self.type_registry = type_registry
788788
self.type_registry_preset = type_registry_preset
789789
self.runtime_cache = RuntimeCache()
790-
self.runtime_config = RuntimeConfigurationObject(
791-
ss58_format=self.ss58_format, implements_scale_info=True
792-
)
793790
self._nonces = {}
794791
self.metadata_version_hex = "0x0f000000" # v15
795-
self.reload_type_registry()
796792
self._initializing = False
797-
self.registry_type_map = {}
798-
self.type_id_to_name = {}
799793
self._mock = _mock
800794

801795
async def __aenter__(self):
@@ -896,52 +890,31 @@ async def _load_registry_at_block(
896890
metadata_option_bytes = bytes.fromhex(metadata_option_hex_str[2:])
897891
metadata = MetadataV15.decode_from_metadata_option(metadata_option_bytes)
898892
registry = PortableRegistry.from_metadata_v15(metadata)
899-
self._load_registry_type_map(registry)
900893
return metadata, registry
901894

902-
async def _wait_for_registry(self, _attempt: int = 1, _retries: int = 3) -> None:
903-
async def _waiter():
904-
while self.runtime.registry is None:
905-
await asyncio.sleep(0.1)
906-
return
907-
908-
try:
909-
if not self.runtime.registry:
910-
await asyncio.wait_for(_waiter(), timeout=10)
911-
except TimeoutError:
912-
# indicates that registry was never loaded
913-
if not self._initializing:
914-
raise AttributeError(
915-
"Registry was never loaded. This did not occur during initialization, which usually indicates "
916-
"you must first initialize the AsyncSubstrateInterface object, either with "
917-
"`await AsyncSubstrateInterface.initialize()` or running with `async with`"
918-
)
919-
elif _attempt < _retries:
920-
await self._load_registry_at_block(None)
921-
return await self._wait_for_registry(_attempt + 1, _retries)
922-
else:
923-
raise AttributeError(
924-
"Registry was never loaded. This occurred during initialization, which usually indicates a "
925-
"connection or node error."
926-
)
927-
928895
async def encode_scale(
929-
self, type_string, value: Any, _attempt: int = 1, _retries: int = 3
896+
self,
897+
type_string,
898+
value: Any,
899+
block_hash: Optional[str] = None,
900+
runtime: Optional[Runtime] = None,
930901
) -> bytes:
931902
"""
932-
Helper function to encode arbitrary data into SCALE-bytes for given RUST type_string
903+
Helper function to encode arbitrary data into SCALE-bytes for given RUST type_string. If neither `block_hash`
904+
nor `runtime` are supplied, the runtime of the current block will be used.
933905
934906
Args:
935907
type_string: the type string of the SCALE object for decoding
936908
value: value to encode
937-
_attempt: the current number of attempts to load the registry needed to encode the value
938-
_retries: the maximum number of attempts to load the registry needed to encode the value
909+
block_hash: hash of the block where the desired runtime is located. Ignored if supplying `runtime`
910+
runtime: the runtime to use for the scale encoding. If supplied, `block_hash` is ignored
939911
940912
Returns:
941913
encoded bytes
942914
"""
943-
await self._wait_for_registry(_attempt, _retries)
944-
return self._encode_scale(type_string, value)
915+
if runtime is None:
916+
runtime = await self.init_runtime(block_hash=block_hash)
917+
return self._encode_scale(type_string, value, runtime=runtime)
945918

946919
async def decode_scale(
947920
self,
@@ -987,25 +960,26 @@ async def decode_scale(
987960
return obj
988961

989962
def load_runtime(self, runtime):
990-
self.runtime = runtime
991-
992963
# Update type registry
993-
self.reload_type_registry(use_remote_preset=False, auto_discover=True)
964+
runtime.reload_type_registry(use_remote_preset=False, auto_discover=True)
994965

995-
self.runtime_config.set_active_spec_version_id(runtime.runtime_version)
996-
if self.implements_scaleinfo:
997-
logger.debug("Add PortableRegistry from metadata to type registry")
998-
self.runtime_config.add_portable_registry(runtime.metadata)
966+
runtime.runtime_config.set_active_spec_version_id(runtime.runtime_version)
967+
runtime.runtime_config.set_active_spec_version_id(runtime.runtime_version)
968+
if runtime.implements_scaleinfo:
969+
logger.debug("Adding PortableRegistry from metadata to type registry")
970+
runtime.runtime_config.add_portable_registry(runtime.metadata)
999971
# Set runtime compatibility flags
1000972
try:
1001-
_ = self.runtime_config.create_scale_object("sp_weights::weight_v2::Weight")
1002-
self.config["is_weight_v2"] = True
1003-
self.runtime_config.update_type_registry_types(
973+
_ = runtime.runtime_config.create_scale_object(
974+
"sp_weights::weight_v2::Weight"
975+
)
976+
runtime.config["is_weight_v2"] = True
977+
runtime.runtime_config.update_type_registry_types(
1004978
{"Weight": "sp_weights::weight_v2::Weight"}
1005979
)
1006980
except NotImplementedError:
1007-
self.config["is_weight_v2"] = False
1008-
self.runtime_config.update_type_registry_types({"Weight": "WeightV1"})
981+
runtime.config["is_weight_v2"] = False
982+
runtime.runtime_config.update_type_registry_types({"Weight": "WeightV1"})
1009983

1010984
async def init_runtime(
1011985
self, block_hash: Optional[str] = None, block_id: Optional[int] = None
@@ -1288,6 +1262,7 @@ async def get_metadata_storage_functions(
12881262
storage_item=storage,
12891263
module=module,
12901264
spec_version_id=runtime.runtime_version,
1265+
runtime=runtime,
12911266
)
12921267
)
12931268

@@ -1407,21 +1382,21 @@ async def get_metadata_runtime_call_function(
14071382
self,
14081383
api: str,
14091384
method: str,
1410-
block_hash: str = None,
1385+
block_hash: Optional[str] = None,
14111386
runtime: Optional[Runtime] = None,
14121387
) -> GenericRuntimeCallDefinition:
14131388
"""
1414-
Get details of a runtime API call
1389+
Get details of a runtime API call. If not supplying `block_hash` or `runtime`, the runtime of the current block
1390+
will be used.
14151391
14161392
Args:
14171393
api: Name of the runtime API e.g. 'TransactionPaymentApi'
14181394
method: Name of the method e.g. 'query_fee_details'
1419-
block_hash: Hash of the block to query, unused if specifying `runtime`
1420-
runtime: Optional `Runtime` whose call functions to retrieve. If not specified, will fall back to the
1421-
runtime at the block hash specified. If that is not specified, will fall back to the current block.
1395+
block_hash: Hash of the block whose runtime to use, if not specifying `runtime`
1396+
runtime: The `Runtime` object whose metadata to use.
14221397
14231398
Returns:
1424-
runtime call function
1399+
GenericRuntimeCallDefinition
14251400
"""
14261401
if not runtime:
14271402
runtime = await self.init_runtime(block_hash=block_hash)
@@ -1439,7 +1414,7 @@ async def get_metadata_runtime_call_function(
14391414
raise ValueError(f"Runtime API Call '{api}.{method}' not found in registry")
14401415

14411416
# Add runtime API types to registry
1442-
self.runtime_config.update_type_registry_types(runtime_api_types)
1417+
runtime.runtime_config.update_type_registry_types(runtime_api_types)
14431418

14441419
runtime_call_def_obj = await self.create_scale_object(
14451420
"RuntimeCallDefinition", runtime=runtime
@@ -1448,41 +1423,6 @@ async def get_metadata_runtime_call_function(
14481423

14491424
return runtime_call_def_obj
14501425

1451-
async def get_metadata_runtime_call_function(
1452-
self, api: str, method: str
1453-
) -> GenericRuntimeCallDefinition:
1454-
"""
1455-
Get details of a runtime API call
1456-
1457-
Args:
1458-
api: Name of the runtime API e.g. 'TransactionPaymentApi'
1459-
method: Name of the method e.g. 'query_fee_details'
1460-
1461-
Returns:
1462-
GenericRuntimeCallDefinition
1463-
"""
1464-
await self.init_runtime(block_hash=block_hash)
1465-
1466-
try:
1467-
runtime_call_def = self.runtime_config.type_registry["runtime_api"][api][
1468-
"methods"
1469-
][method]
1470-
runtime_call_def["api"] = api
1471-
runtime_call_def["method"] = method
1472-
runtime_api_types = self.runtime_config.type_registry["runtime_api"][
1473-
api
1474-
].get("types", {})
1475-
except KeyError:
1476-
raise ValueError(f"Runtime API Call '{api}.{method}' not found in registry")
1477-
1478-
# Add runtime API types to registry
1479-
self.runtime_config.update_type_registry_types(runtime_api_types)
1480-
1481-
runtime_call_def_obj = await self.create_scale_object("RuntimeCallDefinition")
1482-
runtime_call_def_obj.encode(runtime_call_def)
1483-
1484-
return runtime_call_def_obj
1485-
14861426
async def _get_block_handler(
14871427
self,
14881428
block_hash: str,
@@ -2897,6 +2837,7 @@ async def _do_runtime_call_old(
28972837
method: str,
28982838
params: Optional[Union[list, dict]] = None,
28992839
block_hash: Optional[str] = None,
2840+
runtime: Optional[Runtime] = None,
29002841
) -> ScaleType:
29012842
logger.debug(
29022843
f"Decoding old runtime call: {api}.{method} with params: {params} at block hash: {block_hash}"
@@ -2927,10 +2868,14 @@ async def _do_runtime_call_old(
29272868

29282869
# RPC request
29292870
result_data = await self.rpc_request(
2930-
"state_call", [f"{api}_{method}", param_data.hex(), block_hash]
2871+
"state_call",
2872+
[f"{api}_{method}", param_data.hex(), block_hash],
2873+
runtime=runtime,
29312874
)
29322875
result_vec_u8_bytes = hex_to_bytes(result_data["result"])
2933-
result_bytes = await self.decode_scale("Vec<u8>", result_vec_u8_bytes)
2876+
result_bytes = await self.decode_scale(
2877+
"Vec<u8>", result_vec_u8_bytes, runtime=runtime
2878+
)
29342879

29352880
# Decode result
29362881
# Get correct type
@@ -2976,7 +2921,9 @@ async def runtime_call(
29762921
raise ValueError(f"Runtime API Call '{api}.{method}' not found in registry")
29772922

29782923
if _determine_if_old_runtime_call(runtime_call_def, metadata_v15_value):
2979-
result = await self._do_runtime_call_old(api, method, params, block_hash)
2924+
result = await self._do_runtime_call_old(
2925+
api, method, params, block_hash, runtime=runtime
2926+
)
29802927

29812928
return result
29822929

0 commit comments

Comments
 (0)