Skip to content

Commit 4047dd9

Browse files
committed
Adds integration test for RetrySubtensor with Archive Node
1 parent c8e13c6 commit 4047dd9

File tree

5 files changed

+221
-4
lines changed

5 files changed

+221
-4
lines changed

bittensor/core/async_subtensor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ def _get_substrate(
321321
use_remote_preset=True,
322322
chain_name="Bittensor",
323323
_mock=_mock,
324-
archive_endpoints=archive_endpoints,
324+
archive_nodes=archive_endpoints,
325325
)
326326
return AsyncSubstrateInterface(
327327
url=self.chain_endpoint,

bittensor/core/subtensor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ def _get_substrate(
204204
fallback_chains=fallback_endpoints,
205205
retry_forever=retry_forever,
206206
_mock=_mock,
207-
archive_endpoints=archive_endpoints,
207+
archive_nodes=archive_endpoints,
208208
)
209209
return SubstrateInterface(
210210
url=self.chain_endpoint,

tests/helpers/helpers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import itertools
23
import json
34
import time
45
from collections import deque
@@ -204,6 +205,9 @@ def recv(self, *args, **kwargs):
204205
response = WEBSOCKET_RESPONSES[self.seed][item["method"]][
205206
json.dumps(item["params"])
206207
]
208+
if isinstance(response, itertools.cycle):
209+
# Allows us to cycle through different responses for the same method/params combo
210+
response = next(response)
207211
response["id"] = _id
208212
return json.dumps(response)
209213
except (KeyError, TypeError):

tests/helpers/integration_websocket_data.py

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# This is dictionary of raw websocket send vs recv data for given methods used for integration testing, essentially
22
# stubbing the network I/O only
33
# This is basically a JSON file, but is not a JSON file because of the discrepancies between JSON and Python types
4+
5+
from itertools import cycle
6+
7+
48
WEBSOCKET_RESPONSES = {
59
"blocks_since_last_update": {
610
"chain_getHead": {
@@ -9049,4 +9053,203 @@
90499053
},
90509054
"system_chain": {"[]": {"jsonrpc": "2.0", "result": "Bittensor"}},
90519055
},
9056+
"retry_archive": {
9057+
"system_chain": {"[]": {"jsonrpc": "2.0", "result": "Bittensor"}},
9058+
"chain_getHead": {
9059+
"[]": {
9060+
"jsonrpc": "2.0",
9061+
"result": "0xae6bd3bf8cc2a7660a315510f72a7e8c8dc31ad58c8d847e86682ee07c6e8938",
9062+
}
9063+
},
9064+
"chain_getHeader": {
9065+
'["0x0f28c25f01cc4b11bb1454c323bd3d04658e4e64b69fcd21ffa01bac0ae47b19"]': {
9066+
"jsonrpc": "2.0",
9067+
"result": {
9068+
"parentHash": "0x3c1304811d6b0f5741c0ce9fcd46416c3fe151561463134b0fa9b68f1bd0188d",
9069+
"number": "0x57c8bb",
9070+
"stateRoot": "0x48b804f020e871af4eae34fb9d1fae077ff988016e65fafc9e3acbcdc8cfc8d9",
9071+
"extrinsicsRoot": "0x9b28450ef2ca7730b29e104d85e65e23cf021d405fb0fb29226dd04b89d36182",
9072+
"digest": {
9073+
"logs": [
9074+
"0x06617572612023b8b00800000000",
9075+
"0x0466726f6e8801446b1f0502f0e66079329d4718fb2f5cd5660a74a1bc0c7556c9ecbd92b54b3700",
9076+
"0x05617572610101a8461545e8f4947dd540f2f2131fdf29117e471a9c46970a408ef9684dbf495cdaebeaf8a42efcf0a57fdf75ddf807fb1f4c21fb1fb74b6715cf59a23f24d98e",
9077+
]
9078+
},
9079+
},
9080+
},
9081+
"[null]": {
9082+
"jsonrpc": "2.0",
9083+
"result": {
9084+
"parentHash": "0x3c1304811d6b0f5741c0ce9fcd46416c3fe151561463134b0fa9b68f1bd0188d",
9085+
"number": "0x57c8bb",
9086+
"stateRoot": "0x48b804f020e871af4eae34fb9d1fae077ff988016e65fafc9e3acbcdc8cfc8d9",
9087+
"extrinsicsRoot": "0x9b28450ef2ca7730b29e104d85e65e23cf021d405fb0fb29226dd04b89d36182",
9088+
"digest": {
9089+
"logs": [
9090+
"0x06617572612023b8b00800000000",
9091+
"0x0466726f6e8801446b1f0502f0e66079329d4718fb2f5cd5660a74a1bc0c7556c9ecbd92b54b3700",
9092+
"0x05617572610101a8461545e8f4947dd540f2f2131fdf29117e471a9c46970a408ef9684dbf495cdaebeaf8a42efcf0a57fdf75ddf807fb1f4c21fb1fb74b6715cf59a23f24d98e",
9093+
]
9094+
},
9095+
},
9096+
},
9097+
'["0x0ba73c8d5a0b78f7336a3e394a2a1fa7b7dec0924937b1dfb05a50ac3dd5cfc1"]': {
9098+
"jsonrpc": "2.0",
9099+
"result": {
9100+
"parentHash": "0x6c0da8a9dd5994d374d43210dc401f000b2fe02541bc2e7cd54719655d751a18",
9101+
"number": "0x57c4d3",
9102+
"stateRoot": "0xc80611aa0e605bc2d0446479dcbce6bee0e1524d07b0a9c6293a190d6a500fef",
9103+
"extrinsicsRoot": "0x9ff58560a13b06d4a61af01ca9f0dd2a96cf5bfa6bbc2208fc7e6f763bad5590",
9104+
"digest": {
9105+
"logs": [
9106+
"0x0661757261203bb4b00800000000",
9107+
"0x0466726f6e880102e3f23c7b0347be401daa27b4bd35d09948dc1450bec025807957f499347c5800",
9108+
"0x05617572610101bcc856c718c722f327d3fbc3f94c34d97e0bfc794531e94f5590b44b3516c7598ca0ec488b81f9fbf5a9bbb5d18663bd69ca032d1c7134681d9c112387612a87",
9109+
]
9110+
},
9111+
},
9112+
},
9113+
'["0xae6bd3bf8cc2a7660a315510f72a7e8c8dc31ad58c8d847e86682ee07c6e8938"]': {
9114+
"jsonrpc": "2.0",
9115+
"result": {
9116+
"parentHash": "0x0f28c25f01cc4b11bb1454c323bd3d04658e4e64b69fcd21ffa01bac0ae47b19",
9117+
"number": "0x57c8bc",
9118+
"stateRoot": "0x87f0259d14e63525a311f4afabd7273519ac2e98e2dc70cf17292b615889b714",
9119+
"extrinsicsRoot": "0x24c53c5248e9e822fb29c381cee462e5f830bba62097d58607dead8da7f3b64b",
9120+
"digest": {
9121+
"logs": [
9122+
"0x06617572612024b8b00800000000",
9123+
"0x0466726f6e88016e91817304fa73ea8595ba3bd2e26fb838c7495ae83501bb266013b2307170f200",
9124+
"0x0561757261010152b29d8299665fd87748987347b6b91d206c04a5939ddb543e4776adcfb0ff47196fdaec1a0e2a2225e0485f1fa91b5c4421ff54944df488dcf35ecbc7a57087",
9125+
]
9126+
},
9127+
},
9128+
},
9129+
},
9130+
"state_getRuntimeVersion": {
9131+
'["0x3c1304811d6b0f5741c0ce9fcd46416c3fe151561463134b0fa9b68f1bd0188d"]': {
9132+
"jsonrpc": "2.0",
9133+
"result": {
9134+
"specName": "node-subtensor",
9135+
"implName": "node-subtensor",
9136+
"authoringVersion": 1,
9137+
"specVersion": 274,
9138+
"implVersion": 1,
9139+
"apis": [
9140+
["0xdf6acb689907609b", 5],
9141+
["0x37e397fc7c91f5e4", 2],
9142+
["0x40fe3ad401f8959a", 6],
9143+
["0xfbc577b9d747efd6", 1],
9144+
["0xd2bc9897eed08f15", 3],
9145+
["0xf78b278be53f454c", 2],
9146+
["0xdd718d5cc53262d4", 1],
9147+
["0xab3c0572291feb8b", 1],
9148+
["0xed99c5acb25eedf5", 3],
9149+
["0xbc9d89904f5b923f", 1],
9150+
["0x37c8bb1350a9a2a8", 4],
9151+
["0xf3ff14d5ab527059", 3],
9152+
["0x582211f65bb14b89", 5],
9153+
["0xe65b00e46cedd0aa", 2],
9154+
["0x42e62be4a39e5b60", 1],
9155+
["0x806df4ccaa9ed485", 1],
9156+
["0x8375104b299b74c5", 1],
9157+
["0x5d1fbfbe852f2807", 1],
9158+
["0xc6886e2f8e598b0a", 1],
9159+
],
9160+
"transactionVersion": 1,
9161+
"stateVersion": 1,
9162+
},
9163+
},
9164+
'["0x6c0da8a9dd5994d374d43210dc401f000b2fe02541bc2e7cd54719655d751a18"]': cycle(
9165+
(
9166+
{
9167+
"jsonrpc": "2.0",
9168+
"id": "oj19",
9169+
"error": {
9170+
"code": 4003,
9171+
"message": "Client error: Api called for an unknown Block: State already discarded for 0x6c0da8a9dd5994d374d43210dc401f000b2fe02541bc2e7cd54719655d751a18",
9172+
},
9173+
},
9174+
{
9175+
"jsonrpc": "2.0",
9176+
"result": {
9177+
"specName": "node-subtensor",
9178+
"implName": "node-subtensor",
9179+
"authoringVersion": 1,
9180+
"specVersion": 273,
9181+
"implVersion": 1,
9182+
"apis": [
9183+
["0xdf6acb689907609b", 5],
9184+
["0x37e397fc7c91f5e4", 2],
9185+
["0x40fe3ad401f8959a", 6],
9186+
["0xfbc577b9d747efd6", 1],
9187+
["0xd2bc9897eed08f15", 3],
9188+
["0xf78b278be53f454c", 2],
9189+
["0xdd718d5cc53262d4", 1],
9190+
["0xab3c0572291feb8b", 1],
9191+
["0xed99c5acb25eedf5", 3],
9192+
["0xbc9d89904f5b923f", 1],
9193+
["0x37c8bb1350a9a2a8", 4],
9194+
["0xf3ff14d5ab527059", 3],
9195+
["0x582211f65bb14b89", 5],
9196+
["0xe65b00e46cedd0aa", 2],
9197+
["0x42e62be4a39e5b60", 1],
9198+
["0x806df4ccaa9ed485", 1],
9199+
["0x8375104b299b74c5", 1],
9200+
["0x5d1fbfbe852f2807", 1],
9201+
["0xc6886e2f8e598b0a", 1],
9202+
],
9203+
"transactionVersion": 1,
9204+
"stateVersion": 1,
9205+
},
9206+
},
9207+
)
9208+
),
9209+
'["0x0f28c25f01cc4b11bb1454c323bd3d04658e4e64b69fcd21ffa01bac0ae47b19"]': {
9210+
"jsonrpc": "2.0",
9211+
"result": {
9212+
"specName": "node-subtensor",
9213+
"implName": "node-subtensor",
9214+
"authoringVersion": 1,
9215+
"specVersion": 274,
9216+
"implVersion": 1,
9217+
"apis": [
9218+
["0xdf6acb689907609b", 5],
9219+
["0x37e397fc7c91f5e4", 2],
9220+
["0x40fe3ad401f8959a", 6],
9221+
["0xfbc577b9d747efd6", 1],
9222+
["0xd2bc9897eed08f15", 3],
9223+
["0xf78b278be53f454c", 2],
9224+
["0xdd718d5cc53262d4", 1],
9225+
["0xab3c0572291feb8b", 1],
9226+
["0xed99c5acb25eedf5", 3],
9227+
["0xbc9d89904f5b923f", 1],
9228+
["0x37c8bb1350a9a2a8", 4],
9229+
["0xf3ff14d5ab527059", 3],
9230+
["0x582211f65bb14b89", 5],
9231+
["0xe65b00e46cedd0aa", 2],
9232+
["0x42e62be4a39e5b60", 1],
9233+
["0x806df4ccaa9ed485", 1],
9234+
["0x8375104b299b74c5", 1],
9235+
["0x5d1fbfbe852f2807", 1],
9236+
["0xc6886e2f8e598b0a", 1],
9237+
],
9238+
"transactionVersion": 1,
9239+
"stateVersion": 1,
9240+
},
9241+
},
9242+
},
9243+
"chain_getBlockHash": {
9244+
"[5752019]": {
9245+
"jsonrpc": "2.0",
9246+
"result": "0x0ba73c8d5a0b78f7336a3e394a2a1fa7b7dec0924937b1dfb05a50ac3dd5cfc1",
9247+
}
9248+
},
9249+
"chain_getBlock": {
9250+
'["0x0ba73c8d5a0b78f7336a3e394a2a1fa7b7dec0924937b1dfb05a50ac3dd5cfc1"]': {
9251+
"result": {"block": {}}
9252+
}
9253+
},
9254+
},
90529255
}

tests/integration_tests/test_subtensor_integration.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ def netuid():
1717
yield 23
1818

1919

20-
async def prepare_test(mocker, seed):
20+
async def prepare_test(mocker, seed, **subtensor_args):
2121
"""
2222
Helper function: sets up the test environment.
2323
"""
2424
mocker.patch(
2525
"async_substrate_interface.sync_substrate.connect",
2626
mocker.Mock(return_value=FakeWebsocket(seed=seed)),
2727
)
28-
subtensor = Subtensor("unknown", _mock=True)
28+
subtensor = Subtensor("unknown", _mock=True, **subtensor_args)
2929
return subtensor
3030

3131

@@ -151,3 +151,13 @@ def test_mock_subtensor_force_register_neuron():
151151
assert neuron1.coldkey == "cc1"
152152
assert neuron2.hotkey == "hk2"
153153
assert neuron2.coldkey == "cc2"
154+
155+
156+
@pytest.mark.asyncio
157+
async def test_archive_node_retry(mocker):
158+
subtensor = await prepare_test(
159+
mocker, "retry_archive", archive_endpoints=["ws://fake-endpoi.nt"]
160+
)
161+
current_block = subtensor.substrate.get_block_number()
162+
old_block = current_block - 1000
163+
assert isinstance((subtensor.substrate.get_block(block_number=old_block)), dict)

0 commit comments

Comments
 (0)