Skip to content

Commit

Permalink
add serve_axon certificate sending
Browse files Browse the repository at this point in the history
  • Loading branch information
andreea-popescu-reef committed Apr 3, 2024
1 parent de0bd31 commit ecf52d3
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 7 deletions.
8 changes: 6 additions & 2 deletions bittensor/axon.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from starlette.requests import Request
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from typing import List, Optional, Tuple, Callable, Any, Dict
from .utils import Certificate

from bittensor.errors import (
InvalidRequestNameError,
Expand Down Expand Up @@ -822,7 +823,10 @@ def stop(self) -> "bittensor.axon":
return self

def serve(
self, netuid: int, subtensor: Optional[bittensor.subtensor] = None
self,
netuid: int,
subtensor: Optional[bittensor.subtensor] = None,
certificate: Optional[Certificate] = None,
) -> "bittensor.axon":
"""
Serves the Axon on the specified subtensor connection using the configured wallet. This method
Expand All @@ -848,7 +852,7 @@ def serve(
to start receiving and processing requests from other neurons.
"""
if subtensor is not None and hasattr(subtensor, "serve_axon"):
subtensor.serve_axon(netuid=netuid, axon=self)
subtensor.serve_axon(netuid=netuid, axon=self, certificate=certificate)
return self

async def default_verify(self, synapse: bittensor.Synapse):
Expand Down
63 changes: 63 additions & 0 deletions bittensor/chain_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

from .utils import networking as net, U16_MAX, U16_NORMALIZED_FLOAT
from .utils.balance import Balance
from .utils import Certificate

custom_rpc_type_registry = {
"types": {
Expand Down Expand Up @@ -67,6 +68,12 @@
["total_daily_return", "Compact<u64>"],
],
},
"NeuronCertificate": {
"type": "struct",
"type_mapping": [
["certificate", "Vec<u8>"],
],
},
"NeuronInfo": {
"type": "struct",
"type_mapping": [
Expand Down Expand Up @@ -286,6 +293,7 @@ class ChainDataType(Enum):
StakeInfo = 6
IPInfo = 7
SubnetHyperparameters = 8
NeuronCertificate = 9


# Constants
Expand Down Expand Up @@ -514,6 +522,61 @@ def _neuron_dict_to_namespace(neuron_dict) -> "NeuronInfo":
return neuron


# Dataclasses for chain data.
@dataclass
class NeuronCertificate:
r"""
Dataclass for neuron certificate.
"""

certificate: str

# @classmethod
# def fix_decoded_values(cls, neuron_certificate_decoded: Any) -> "NeuronCertificate":
# r"""Fixes the values of the NeuronCertificate object."""
# neuron_certificate_decoded["certificate"] = U16_NORMALIZED_FLOAT(
# neuron_certificate_decoded["certificate"]
# )
# return cls(**neuron_certificate_decoded)

@classmethod
def from_vec_u8(cls, vec_u8: List[int]) -> "NeuronCertificate":
r"""Returns a NeuronCertificate object from a ``vec_u8``."""
if len(vec_u8) == 0:
return NeuronCertificate._null_neuron()

decoded = from_scale_encoding(vec_u8, ChainDataType.NeuronCertificate)
if decoded is None:
return NeuronCertificate._null_neuron()

# decoded = NeuronCertificate.fix_decoded_values(decoded)

return decoded

@classmethod
def list_from_vec_u8(cls, vec_u8: List[int]) -> List["NeuronCertificate"]:
r"""Returns a list of NeuronCertificate objects from a ``vec_u8``."""

decoded_list = from_scale_encoding(
vec_u8, ChainDataType.NeuronCertificate, is_vec=True
)
if decoded_list is None:
return []

# decoded_list = [
# NeuronCertificate.fix_decoded_values(decoded) for decoded in decoded_list
# ]

return decoded_list

@staticmethod
def _null_neuron() -> "NeuronCertificate":
neuron_certificate = NeuronCertificate(
certificate=None,
)
return neuron_certificate


@dataclass
class NeuronInfoLite:
r"""
Expand Down
11 changes: 10 additions & 1 deletion bittensor/extrinsics/serving.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import bittensor.utils.networking as net
from rich.prompt import Confirm
from ..errors import MetadataError
from typing import Optional
from ..utils import Certificate


def serve_extrinsic(
Expand All @@ -34,6 +36,7 @@ def serve_extrinsic(
wait_for_inclusion: bool = False,
wait_for_finalization=True,
prompt: bool = False,
certificate: Optional[Certificate] = None,
) -> bool:
r"""Subscribes a Bittensor endpoint to the subtensor chain.
Expand All @@ -44,6 +47,8 @@ def serve_extrinsic(
Endpoint host port i.e., ``192.122.31.4``.
port (int):
Endpoint port number i.e., ``9221``.
certificate (str):
public key
protocol (int):
An ``int`` representation of the protocol.
netuid (int):
Expand All @@ -62,6 +67,7 @@ def serve_extrinsic(
success (bool):
Flag is ``true`` if extrinsic was finalized or uncluded in the block. If we did not wait for finalization / inclusion, the response is ``true``.
"""
print(f"serve_extrinsic {certificate}")
# Decrypt hotkey
wallet.hotkey
params: "bittensor.AxonServeCallParams" = {
Expand All @@ -75,6 +81,7 @@ def serve_extrinsic(
"protocol": protocol,
"placeholder1": placeholder1,
"placeholder2": placeholder2,
"certificate": certificate,
}
bittensor.logging.debug("Checking axon ...")
neuron = subtensor.get_neuron_for_pubkey_and_subnet(
Expand Down Expand Up @@ -144,6 +151,7 @@ def serve_axon_extrinsic(
wait_for_inclusion: bool = False,
wait_for_finalization: bool = True,
prompt: bool = False,
certificate: Optional[Certificate] = None,
) -> bool:
r"""Serves the axon to the network.
Expand All @@ -166,6 +174,7 @@ def serve_axon_extrinsic(
axon.wallet.coldkeypub
external_port = axon.external_port

print(f"serve_axon_extrinsic {certificate}")
# ---- Get external ip ----
if axon.external_ip == None:
try:
Expand Down Expand Up @@ -197,6 +206,7 @@ def serve_axon_extrinsic(
wait_for_inclusion=wait_for_inclusion,
wait_for_finalization=wait_for_finalization,
prompt=prompt,
certificate=certificate,
)
return serve_success

Expand Down Expand Up @@ -264,7 +274,6 @@ def publish_metadata(


from retry import retry
from typing import Optional


def get_metadata(self, netuid: int, hotkey: str, block: Optional[int] = None) -> str:
Expand Down
54 changes: 51 additions & 3 deletions bittensor/subtensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
# Local imports.
from .btlogging.defines import BITTENSOR_LOGGER_NAME
from .chain_data import (
NeuronCertificate,
NeuronInfo,
DelegateInfo,
PrometheusInfo,
Expand Down Expand Up @@ -82,7 +83,12 @@
)
from .extrinsics.root import root_register_extrinsic, set_root_weights_extrinsic
from .types import AxonServeCallParams, PrometheusServeCallParams
from .utils import U16_NORMALIZED_FLOAT, ss58_to_vec_u8, U64_NORMALIZED_FLOAT
from .utils import (
U16_NORMALIZED_FLOAT,
ss58_to_vec_u8,
U64_NORMALIZED_FLOAT,
Certificate,
)
from .utils.balance import Balance
from .utils.registration import POWSolution

Expand Down Expand Up @@ -1328,6 +1334,7 @@ def serve(
wait_for_inclusion: bool = False,
wait_for_finalization=True,
prompt: bool = False,
certificate: Optional[Certificate] = None,
) -> bool:
"""
Registers a neuron's serving endpoint on the Bittensor network. This function announces the
Expand All @@ -1351,6 +1358,7 @@ def serve(
This function is essential for establishing the neuron's presence in the network, enabling
it to participate in the decentralized machine learning processes of Bittensor.
"""
print(f"serve {certificate}")
return serve_extrinsic(
self,
wallet,
Expand All @@ -1362,6 +1370,7 @@ def serve(
placeholder2,
wait_for_inclusion,
wait_for_finalization,
certificate=certificate,
)

def serve_axon(
Expand All @@ -1371,6 +1380,7 @@ def serve_axon(
wait_for_inclusion: bool = False,
wait_for_finalization: bool = True,
prompt: bool = False,
certificate: Optional[Certificate] = None,
) -> bool:
"""
Registers an Axon serving endpoint on the Bittensor network for a specific neuron. This function
Expand All @@ -1391,7 +1401,12 @@ def serve_axon(
computing infrastructure, contributing to the collective intelligence of Bittensor.
"""
return serve_axon_extrinsic(
self, netuid, axon, wait_for_inclusion, wait_for_finalization
self,
netuid,
axon,
wait_for_inclusion,
wait_for_finalization,
certificate=certificate,
)

def _do_serve_axon(
Expand All @@ -1418,12 +1433,19 @@ def _do_serve_axon(
enhancing the decentralized computation capabilities of Bittensor.
"""

certificate = call_params["certificate"]
if certificate is None:
del call_params["certificate"]
call_function = "serve_axon"
else:
call_function = "serve_axon_tls"

@retry(delay=2, tries=3, backoff=2, max_delay=4)
def make_substrate_call_with_retry():
with self.substrate as substrate:
call = substrate.compose_call(
call_module="SubtensorModule",
call_function="serve_axon",
call_function=call_function,
call_params=call_params,
)
extrinsic = substrate.create_signed_extrinsic(
Expand Down Expand Up @@ -3952,6 +3974,32 @@ def make_substrate_call_with_retry():

return NeuronInfo.from_vec_u8(result)

def get_neuron_certificate(
self, uid: Optional[int], netuid: int, block: Optional[int] = None
) -> Certificate:
if uid is None:
return NeuronCertificate._null_neuron()

@retry(delay=2, tries=3, backoff=2, max_delay=4)
def make_substrate_call_with_retry():
with self.substrate as substrate:
block_hash = None if block == None else substrate.get_block_hash(block)
params = [netuid, uid]
if block_hash:
params = params + [block_hash]
return substrate.rpc_request(
method="neuronInfo_getNeuronCertificate",
params=params, # custom rpc method
)

json_body = make_substrate_call_with_retry()
result = json_body["result"]

if result in (None, []):
return NeuronCertificate._null_neuron()

return NeuronCertificate.from_vec_u8(result)

def neurons(self, netuid: int, block: Optional[int] = None) -> List[NeuronInfo]:
"""
Retrieves a list of all neurons within a specified subnet of the Bittensor network. This function
Expand Down
4 changes: 3 additions & 1 deletion bittensor/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.

from typing import TypedDict
from typing import TypedDict, Optional
from .utils import Certificate


class AxonServeCallParams(TypedDict):
Expand All @@ -28,6 +29,7 @@ class AxonServeCallParams(TypedDict):
port: int
ip_type: int
netuid: int
certificate: Optional[Certificate]


class PrometheusServeCallParams(TypedDict):
Expand Down
2 changes: 2 additions & 0 deletions bittensor/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
U16_MAX = 65535
U64_MAX = 18446744073709551615

Certificate = str


def ss58_to_vec_u8(ss58_address: str) -> List[int]:
ss58_bytes: bytes = bittensor.utils.ss58_address_to_bytes(ss58_address)
Expand Down

0 comments on commit ecf52d3

Please sign in to comment.