Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Template release #24

Merged
merged 15 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions cybertensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
nest_asyncio.apply()

# Cybertensor code and protocol version.
__version__ = "0.1.6"
__version__ = "0.2.0"
version_split = __version__.split(".")
__version_as_int__ = (
(100 * int(version_split[0]))
Expand Down Expand Up @@ -65,15 +65,6 @@ def turn_console_on():
turn_console_on()


# Logging helpers.
def trace(on: bool = True):
logging.set_trace(on)


def debug(on: bool = True):
logging.set_debug(on)


class NetworkConfigCwTensor(NetworkConfig):
def __init__(
self,
Expand Down Expand Up @@ -196,7 +187,6 @@ def __init__(
from cybertensor.dendrite import dendrite
from cybertensor.config import Config
from cybertensor.mock import MockCwtensor, MockWallet
# from .subnets import SubnetsAPI

configs = [
axon.config(),
Expand Down
44 changes: 21 additions & 23 deletions cybertensor/axon.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from starlette.responses import Response

import cybertensor
import cybertensor.utils.networking as net
from cybertensor.config import Config
from cybertensor.errors import *
from cybertensor.keypair import Keypair
Expand Down Expand Up @@ -184,7 +185,7 @@ class MySynapse( cybertensor.Synapse ):
output: int = None

# Define a custom request forwarding function
def forward( synapse: MySynapse ) -> MySynapse:
def forward_my_synapse( synapse: MySynapse ) -> MySynapse:
# Apply custom logic to synapse and return it
synapse.output = 2
return synapse
Expand All @@ -194,13 +195,13 @@ def verify_my_synapse( synapse: MySynapse ):
# Apply custom verification logic to synapse
# Optionally raise Exception

# Define a custom request blacklist fucntion
# Define a custom request blacklist function
def blacklist_my_synapse( synapse: MySynapse ) -> bool:
# Apply custom blacklist
# return False ( if non blacklisted ) or True ( if blacklisted )

# Define a custom request priority fucntion
def prioritize_my_synape( synapse: MySynapse ) -> float:
# Define a custom request priority function
def prioritize_my_synapse( synapse: MySynapse ) -> float:
# Apply custom priority
return 1.0

Expand All @@ -212,12 +213,12 @@ def prioritize_my_synape( synapse: MySynapse ) -> float:
forward_fn = forward_my_synapse,
verify_fn = verify_my_synapse,
blacklist_fn = blacklist_my_synapse,
priority_fn = prioritize_my_synape
priority_fn = prioritize_my_synapse
).attach(
forward_fn = forward_my_synapse_2,
verify_fn = verify_my_synapse_2,
blacklist_fn = blacklist_my_synapse_2,
priority_fn = prioritize_my_synape_2
priority_fn = prioritize_my_synapse_2
).serve(
netuid = ...
cwtensor = ...
Expand Down Expand Up @@ -309,16 +310,8 @@ def __init__(
self.uuid = str(uuid.uuid1())
self.ip = self.config.axon.ip
self.port = self.config.axon.port
self.external_ip = (
self.config.axon.external_ip
if self.config.axon.external_ip is not None
else cybertensor.utils.networking.get_external_ip()
)
self.external_port = (
self.config.axon.external_port
if self.config.axon.external_port is not None
else self.config.axon.port
)
self.external_ip = self.config.axon.external_ip or net.get_external_ip()
self.external_port = self.config.axon.external_port or self.config.axon.port
self.full_address = str(self.config.axon.ip) + ":" + str(self.config.axon.port)
self.started = False

Expand Down Expand Up @@ -687,12 +680,12 @@ def check_config(cls, config: "Config"):
Raises:
AssertionError: If the axon or external ports are not in range [1024, 65535]
"""
assert (
config.axon.port > 1024 and config.axon.port < 65535
assert config.axon.port is None or (
1024 < config.axon.port < 65535
), "Axon port must be in range [1024, 65535]"

assert config.axon.external_port is None or (
config.axon.external_port > 1024 and config.axon.external_port < 65535
1024 < config.axon.external_port < 65535
), "External port must be in range [1024, 65535]"

def to_string(self):
Expand Down Expand Up @@ -847,7 +840,10 @@ async def default_verify(self, synapse: cybertensor.Synapse):
"""
# Build the keypair from the dendrite_hotkey
if synapse.dendrite is not None:
keypair = Keypair(address=synapse.dendrite.hotkey) # type: ignore
cybertensor.logging.info(f"dendrite: {synapse.dendrite}")
# NOTE added public key to the synapese for correct keypair initialization
# keypair = Keypair(address=synapse.dendrite.hotkey)
keypair = Keypair(address=synapse.dendrite.hotkey, public_key=synapse.dendrite.pubkey)
# Build the signature messages.
message = (f"{synapse.dendrite.nonce}.{synapse.dendrite.hotkey}.{self.wallet.hotkey.address}."
f"{synapse.dendrite.uuid}.{synapse.computed_body_hash}")
Expand All @@ -864,7 +860,7 @@ async def default_verify(self, synapse: cybertensor.Synapse):
):
raise Exception("Nonce is too small")

if not keypair.verify(message, synapse.dendrite.signature): # type: ignore
if not keypair.verify(message, synapse.dendrite.signature):
raise Exception(
f"Signature mismatch with {message} and {synapse.dendrite.signature}"
)
Expand Down Expand Up @@ -981,11 +977,13 @@ async def dispatch(
# Logs the start of the request processing
if synapse.dendrite is not None:
cybertensor.logging.trace(
f"axon | <-- | {request.headers.get('content-length', -1)} B | {synapse.name} | {synapse.dendrite.hotkey} | {synapse.dendrite.ip}:{synapse.dendrite.port} | 200 | Success "
f"axon | <-- | {request.headers.get('content-length', -1)} B | {synapse.name} | "
f"{synapse.dendrite.hotkey} | {synapse.dendrite.ip}:{synapse.dendrite.port} | 200 | Success "
)
else:
cybertensor.logging.trace(
f"axon | <-- | {request.headers.get('content-length', -1)} B | {synapse.name} | None | None | 200 | Success "
f"axon | <-- | {request.headers.get('content-length', -1)} B | {synapse.name} | "
f"None | None | 200 | Success "
)

# Call the blacklist function
Expand Down
16 changes: 9 additions & 7 deletions cybertensor/contract/schema/execute.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,7 @@
],
"properties": {
"ip": {
"type": "integer",
"format": "uint128",
"minimum": 0.0
"$ref": "#/definitions/Uint128"
},
"ip_type": {
"type": "integer",
Expand Down Expand Up @@ -239,9 +237,7 @@
],
"properties": {
"ip": {
"type": "integer",
"format": "uint128",
"minimum": 0.0
"$ref": "#/definitions/Uint128"
},
"ip_type": {
"type": "integer",
Expand Down Expand Up @@ -1449,5 +1445,11 @@
},
"additionalProperties": false
}
]
],
"definitions": {
"Uint128": {
"description": "A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
}
}
}
23 changes: 23 additions & 0 deletions cybertensor/contract/schema/query.json
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,29 @@
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"get_subnetwork_n"
],
"properties": {
"get_subnetwork_n": {
"type": "object",
"required": [
"netuid"
],
"properties": {
"netuid": {
"type": "integer",
"format": "uint16",
"minimum": 0.0
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
Expand Down
37 changes: 24 additions & 13 deletions cybertensor/cwtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,11 +345,15 @@ def make_call_with_retry(self, wait_for_finalization: bool,
self.contract.execute(msg, signer_wallet, gas, funds=funds)
return True
else:
tx = self.contract.execute(msg, signer_wallet, gas, funds=funds)
try:
# NOTE will raise exception if tx simulation is not successful, need to catch it
tx = self.contract.execute(msg, signer_wallet, gas, funds=funds)
except Exception as e:
raise error(e.__str__())
try:
tx.wait_to_complete()
if tx.response.is_successful():
print(f'Gas used: {tx.response.gas_used}')
cybertensor.logging.trace(f'Gas used: {tx.response.gas_used}')
return True
else:
raise error(tx.response.logs)
Expand All @@ -371,6 +375,7 @@ def _execute_contract(self, wait_for_finalization: bool,
signer_wallet = LocalWallet(
PrivateKey(_private_key), self.address_prefix
)
cybertensor.logging.trace(f'tx msg {msg}\tsigner_wallet {signer_wallet}')
res = self.make_call_with_retry(
wait_for_finalization=wait_for_finalization,
msg=msg,
Expand Down Expand Up @@ -402,11 +407,17 @@ def _execute_contract(self, wait_for_finalization: bool,
def make_call_with_retry_2(self, wait_for_finalization: bool,
msg: dict, signer_wallet: LocalWallet, gas: Optional[int] = cybertensor.__default_gas__,
funds: Optional[str] = None) -> [bool, Optional[str]]:
cybertensor.logging.trace(f'tx msg {msg}\tsigner_wallet {signer_wallet}')
if not wait_for_finalization:
self.contract.execute(msg, signer_wallet, gas, funds=funds)
return True, None
else:
tx = self.contract.execute(msg, signer_wallet, gas, funds=funds)
try:
# NOTE will raise exception if tx simulation is not successful, need to catch it
tx = self.contract.execute(msg, signer_wallet, gas, funds=funds)
except Exception as e:
return False, e.__str__()

try:
tx.wait_to_complete()
if tx.response.is_successful():
Expand All @@ -417,9 +428,9 @@ def make_call_with_retry_2(self, wait_for_finalization: bool,
except Exception as e:
return False, e.__str__()

####################
#### Websocket Interface related
####################
#####################################
#### Websocket Interface related ####
#####################################
def connect_websocket(self):
"""
(Re)creates the websocket connection, if the URL contains a 'ws' or 'wss' scheme
Expand Down Expand Up @@ -1457,9 +1468,9 @@ def root_set_weights(
prompt=prompt,
)

#####################################
#### Hyper parameter calls. ####
#####################################
###############################
#### Hyper parameter calls ####
###############################

def difficulty(self, netuid: int, block: Optional[int] = None) -> Optional[int]:
"""
Expand Down Expand Up @@ -1749,9 +1760,9 @@ def tx_rate_limit(self, block: Optional[int] = None) -> Optional[int]:
"""
return self.contract.query({"get_tx_rate_limit": {}})

#####################################
############################
#### Network Parameters ####
#####################################
############################

def get_subnet_burn_cost(self, block: Optional[int] = None) -> Optional[int]:
lock_cost = self.contract.query({"get_network_registration_cost": {}})
Expand Down Expand Up @@ -2092,9 +2103,9 @@ def get_stake_info_for_coldkeys(

return StakeInfo.list_of_tuple_from_list_any(result)

########################################
#######################################
#### Neuron information per subnet ####
########################################
#######################################

def is_hotkey_registered_any(
self, hotkey: str, block: Optional[int] = None
Expand Down
2 changes: 2 additions & 0 deletions cybertensor/dendrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,13 +620,15 @@ def preprocess_synapse_for_request(
nonce=time.monotonic_ns(),
uuid=self.uuid,
hotkey=self.keypair.address,
pubkey=self.keypair.public_key
)

# Build the Axon headers using the target axon's details
synapse.axon = cybertensor.TerminalInfo(
ip=target_axon_info.ip,
port=target_axon_info.port,
hotkey=target_axon_info.hotkey,
pubkey=None
)

# Sign the request using the dendrite, axon info, and the synapse body hash
Expand Down
8 changes: 7 additions & 1 deletion cybertensor/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,19 @@ class KeyFileError(Exception):
pass


class ConfigurationError(Exception):
r"""Error raised when a private key is not found."""
pass


class MetadataError(ChainTransactionError):
r"""Error raised when metadata commitment transaction fails."""

pass


class InvalidRequestNameError(Exception):
r"""This exception is raised when the request name is invalid. Ususally indicates a broken URL."""
r"""This exception is raised when the request name is invalid. Usually indicates a broken URL."""

pass

Expand Down Expand Up @@ -146,6 +151,7 @@ class PriorityException(Exception):

pass


class PostProcessException(Exception):
r"""This exception is raised when the response headers cannot be updated."""

Expand Down
Loading
Loading