Skip to content

Commit

Permalink
progress on fix mock subtensor
Browse files Browse the repository at this point in the history
rename test files for discovery

catch nonce errors

skip long tests

test durations

group cli tests to same runner

try group again

try to group tests using arg

patch start server

dont use groups and wait longer to teardown

dont kill

loadgroup

.

update durations

update durations

delay reruns

progress on new mock

more progress

add back mock init

create axons and prometheus

fix imports

add reset state

fix mock calls

fix setup

move some extr send to subtensor impl

move stake ext call

move unstake ext

add extr outline to mock sub

add ext bodies

fix type ann

return empty map on None

fix global state
  • Loading branch information
camfairchild committed Jun 8, 2023
1 parent ec06a70 commit 6418f63
Show file tree
Hide file tree
Showing 19 changed files with 2,268 additions and 1,585 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
command: |
. env/bin/activate
export PYTHONUNBUFFERED=1
pytest -n2 --reruns 3 --durations=0 --verbose --junitxml=test-results/integration_tests.xml \
pytest -n2 --reruns 3 --reruns-delay 15 --durations=0 --verbose --junitxml=test-results/integration_tests.xml \
--cov=. --cov-append --cov-config .coveragerc \
--splits $CIRCLE_NODE_TOTAL --group $((CIRCLE_NODE_INDEX + 1)) \
--splitting-algorithm duration_based_chunks --store-durations --durations-path .test_durations \
Expand Down
147 changes: 97 additions & 50 deletions .test_durations

Large diffs are not rendered by default.

10 changes: 3 additions & 7 deletions bittensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ def turn_console_off():

__rao_symbol__: str = chr(0x03C1)

# Mock Testing Constant
__GLOBAL_MOCK_STATE__ = {}

# Block Explorers map network to explorer url
## Must all be polkadotjs explorer urls
__network_explorer_map__ = {
Expand All @@ -97,13 +100,6 @@ def turn_console_off():
'finney': "https://explorer.finney.opentensor.ai/#/explorer"
}

# Avoid collisions with other processes
from .utils.test_utils import get_random_unused_port
mock_subtensor_port = get_random_unused_port()
__mock_entrypoint__ = f"localhost:{mock_subtensor_port}"

__mock_chain_db__ = './tmp/mock_chain_db'

# --- Type Registry ---
__type_registry__ = {
'types': {
Expand Down
2 changes: 1 addition & 1 deletion bittensor/_subtensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def __new__(
config.subtensor._mock = _mock if _mock != None else config.subtensor._mock
if config.subtensor._mock == True or network == 'mock' or config.subtensor.get('network', bittensor.defaults.subtensor.network) == 'mock':
config.subtensor._mock = True
return subtensor_mock.mock_subtensor.mock()
return subtensor_mock.MockSubtensor()

# Determine config.subtensor.chain_endpoint and config.subtensor.network config.
# If chain_endpoint is set, we override the network flag, otherwise, the chain_endpoint is assigned by the network.
Expand Down
5 changes: 5 additions & 0 deletions bittensor/_subtensor/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ class UnstakeError(ChainTransactionError):
"""
pass

class NominationError(ChainTransactionError):
r""" Error raised when a nomination transaction fails.
"""
pass


class TransferError(ChainTransactionError):
r""" Error raised when a transfer transaction fails.
Expand Down
101 changes: 17 additions & 84 deletions bittensor/_subtensor/extrinsics/delegation.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,95 +53,28 @@ def nominate_extrinsic(

with bittensor.__console__.status(":satellite: Sending nominate call on [white]{}[/white] ...".format(subtensor.network)):
try:
with subtensor.substrate as substrate:
call = substrate.compose_call(
call_module='SubtensorModule',
call_function='become_delegate',
call_params = {
'hotkey': wallet.hotkey.ss58_address
}
)
extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey ) # sign with coldkey
response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
# We only wait here if we expect finalization.
if not wait_for_finalization and not wait_for_inclusion:
bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
return True

response.process_events()
if response.is_success:
bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
bittensor.logging.success( prefix = 'Become Delegate', sufix = '<green>Finalized: </green>' + str(response.is_success) )
else:
bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(response.error_message))
bittensor.logging.warning( prefix = 'Set weights', sufix = '<red>Failed: </red>' + str(response.error_message) )
success = subtensor.do_nominate(
wallet = wallet,
wait_for_inclusion = wait_for_inclusion,
wait_for_finalization = wait_for_finalization
)

if success:
bittensor.__console__.print(":white_heavy_check_mark: [green]Finalized[/green]")
bittensor.logging.success( prefix = 'Become Delegate', sufix = '<green>Finalized: </green>' + str(success) )

# Raises NominationError if False
return success

except Exception as e:
bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(e))
bittensor.logging.warning( prefix = 'Set weights', sufix = '<red>Failed: </red>' + str(e) )
return False

if response.is_success:
return True
except NominationError as e:
bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(e))
bittensor.logging.warning( prefix = 'Set weights', sufix = '<red>Failed: </red>' + str(e) )

return False

def do_delegation(
subtensor: 'bittensor.Subtensor',
wallet: 'bittensor.wallet',
delegate_ss58: str,
amount: 'bittensor.Balance',
wait_for_inclusion: bool = True,
wait_for_finalization: bool = False,
) -> bool:
with subtensor.substrate as substrate:
call = substrate.compose_call(
call_module='SubtensorModule',
call_function='add_stake',
call_params={
'hotkey': delegate_ss58,
'amount_staked': amount.rao
}
)
extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
# We only wait here if we expect finalization.
if not wait_for_finalization and not wait_for_inclusion:
return True
response.process_events()
if response.is_success:
return True
else:
raise StakeError(response.error_message)

def do_undelegation(
subtensor: 'bittensor.Subtensor',
wallet: 'bittensor.wallet',
delegate_ss58: str,
amount: 'bittensor.Balance',
wait_for_inclusion: bool = True,
wait_for_finalization: bool = False,
) -> bool:
with subtensor.substrate as substrate:
call = substrate.compose_call(
call_module='SubtensorModule',
call_function='remove_stake',
call_params={
'hotkey': delegate_ss58,
'amount_unstaked': amount.rao
}
)
extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
# We only wait here if we expect finalization.
if not wait_for_finalization and not wait_for_inclusion:
return True
response.process_events()
if response.is_success:
return True
else:
raise StakeError(response.error_message)


def delegate_extrinsic(
subtensor: 'bittensor.Subtensor',
Expand Down Expand Up @@ -217,7 +150,7 @@ def delegate_extrinsic(

try:
with bittensor.__console__.status(":satellite: Staking to: [bold white]{}[/bold white] ...".format(subtensor.network)):
staking_response: bool = do_delegation(
staking_response: bool = subtensor.do_delegation(
subtensor = subtensor,
wallet = wallet,
delegate_ss58 = delegate_ss58,
Expand Down Expand Up @@ -326,7 +259,7 @@ def undelegate_extrinsic(

try:
with bittensor.__console__.status(":satellite: Unstaking from: [bold white]{}[/bold white] ...".format(subtensor.network)):
staking_response: bool = do_undelegation(
staking_response: bool = subtensor.do_undelegation(
subtensor = subtensor,
wallet = wallet,
delegate_ss58 = delegate_ss58,
Expand Down
126 changes: 49 additions & 77 deletions bittensor/_subtensor/extrinsics/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import torch
import time
from rich.prompt import Confirm
from typing import List, Dict, Union, Optional
from typing import List, Dict, Union, Optional, Tuple
import bittensor.utils.networking as net
from bittensor.utils.registration import POWSolution, create_pow
from ..errors import *
Expand Down Expand Up @@ -122,50 +122,35 @@ def register_extrinsic (
with bittensor.__console__.status(":satellite: Submitting POW..."):
# check if pow result is still valid
while not pow_result.is_stale(subtensor=subtensor):
with subtensor.substrate as substrate:
# create extrinsic call
call = substrate.compose_call(
call_module='SubtensorModule',
call_function='register',
call_params={
'netuid': netuid,
'block_number': pow_result.block_number,
'nonce': pow_result.nonce,
'work': [int(byte_) for byte_ in pow_result.seal],
'hotkey': wallet.hotkey.ss58_address,
'coldkey': wallet.coldkeypub.ss58_address,
}
)
extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.hotkey )
response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization )

# We only wait here if we expect finalization.
if not wait_for_finalization and not wait_for_inclusion:
bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
result: Tuple[bool, Optional[str]] = subtensor.do_pow_register(
netuid = netuid,
wallet = wallet,
pow_result = pow_result,
wait_for_inclusion = wait_for_inclusion,
wait_for_finalization = wait_for_finalization,
)
success, err_msg = result

if not success:
if 'key is already registered' in err_msg:
# Error meant that the key is already registered.
bittensor.__console__.print(f":white_heavy_check_mark: [green]Already Registered on [bold]subnet:{netuid}[/bold][/green]")
return True

# process if registration successful, try again if pow is still valid
response.process_events()
if not response.is_success:
if 'key is already registered' in response.error_message:
# Error meant that the key is already registered.
bittensor.__console__.print(f":white_heavy_check_mark: [green]Already Registered on [bold]subnet:{netuid}[/bold][/green]")
return True

bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(response.error_message))
time.sleep(0.5)
bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(err_msg))
time.sleep(0.5)

# Successful registration, final check for neuron and pubkey
# Successful registration, final check for neuron and pubkey
else:
bittensor.__console__.print(":satellite: Checking Balance...")
is_registered = wallet.is_registered( subtensor = subtensor, netuid = netuid )
if is_registered:
bittensor.__console__.print(":white_heavy_check_mark: [green]Registered[/green]")
return True
else:
bittensor.__console__.print(":satellite: Checking Balance...")
is_registered = wallet.is_registered( subtensor = subtensor, netuid = netuid )
if is_registered:
bittensor.__console__.print(":white_heavy_check_mark: [green]Registered[/green]")
return True
else:
# neuron not found, try again
bittensor.__console__.print(":cross_mark: [red]Unknown error. Neuron not found.[/red]")
continue
# neuron not found, try again
bittensor.__console__.print(":cross_mark: [red]Unknown error. Neuron not found.[/red]")
continue
else:
# Exited loop because pow is no longer valid.
bittensor.__console__.print( "[red]POW is stale.[/red]" )
Expand Down Expand Up @@ -236,41 +221,28 @@ def burned_register_extrinsic (
return False

with bittensor.__console__.status(":satellite: Recycling TAO for Registration..."):
with subtensor.substrate as substrate:
# create extrinsic call
call = substrate.compose_call(
call_module='SubtensorModule',
call_function='burned_register',
call_params={
'netuid': netuid,
'hotkey': wallet.hotkey.ss58_address
}
)
extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion=wait_for_inclusion, wait_for_finalization=wait_for_finalization )

# We only wait here if we expect finalization.
if not wait_for_finalization and not wait_for_inclusion:
bittensor.__console__.print(":white_heavy_check_mark: [green]Sent[/green]")
success, err_msg = subtensor.do_burned_register(
netuid = netuid,
wallet = wallet,
wait_for_inclusion = wait_for_inclusion,
wait_for_finalization = wait_for_finalization,
)

if not success:
bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(err_msg))
time.sleep(0.5)

# Successful registration, final check for neuron and pubkey
else:
bittensor.__console__.print(":satellite: Checking Balance...")
block = subtensor.get_current_block()
new_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address, block = block )

bittensor.__console__.print("Balance:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( old_balance, new_balance ))
is_registered = wallet.is_registered( subtensor = subtensor, netuid = netuid )
if is_registered:
bittensor.__console__.print(":white_heavy_check_mark: [green]Registered[/green]")
return True

# process if registration successful, try again if pow is still valid
response.process_events()
if not response.is_success:
bittensor.__console__.print(":cross_mark: [red]Failed[/red]: error:{}".format(response.error_message))
time.sleep(0.5)

# Successful registration, final check for neuron and pubkey
else:
bittensor.__console__.print(":satellite: Checking Balance...")
block = subtensor.get_current_block()
new_balance = subtensor.get_balance( wallet.coldkeypub.ss58_address, block = block )

bittensor.__console__.print("Balance:\n [blue]{}[/blue] :arrow_right: [green]{}[/green]".format( old_balance, new_balance ))
is_registered = wallet.is_registered( subtensor = subtensor, netuid = netuid )
if is_registered:
bittensor.__console__.print(":white_heavy_check_mark: [green]Registered[/green]")
return True
else:
# neuron not found, try again
bittensor.__console__.print(":cross_mark: [red]Unknown error. Neuron not found.[/red]")
# neuron not found, try again
bittensor.__console__.print(":cross_mark: [red]Unknown error. Neuron not found.[/red]")
30 changes: 10 additions & 20 deletions bittensor/_subtensor/extrinsics/staking.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,23 +374,13 @@ def __do_add_stake_single(
if not subtensor.is_hotkey_delegate( hotkey_ss58 = hotkey_ss58 ):
raise NotDelegateError("Hotkey: {} is not a delegate.".format(hotkey_ss58))

with subtensor.substrate as substrate:
call = substrate.compose_call(
call_module='SubtensorModule',
call_function='add_stake',
call_params={
'hotkey': hotkey_ss58,
'amount_staked': amount.rao
}
)
extrinsic = substrate.create_signed_extrinsic( call = call, keypair = wallet.coldkey )
response = substrate.submit_extrinsic( extrinsic, wait_for_inclusion = wait_for_inclusion, wait_for_finalization = wait_for_finalization )
# We only wait here if we expect finalization.
if not wait_for_finalization and not wait_for_inclusion:
return True

response.process_events()
if response.is_success:
return True
else:
raise StakeError(response.error_message)
success = subtensor.do_stake(
wallet = wallet,
hotkey_ss58 = hotkey_ss58,
amount = amount,
wait_for_inclusion = wait_for_inclusion,
wait_for_finalization = wait_for_finalization,
)

return success

Loading

0 comments on commit 6418f63

Please sign in to comment.