44import time
55import uuid
66import warnings
7+ from concurrent .futures import ProcessPoolExecutor
8+ from functools import partial
79from typing import Any , AsyncGenerator , Optional , Union , Type
810
911import aiohttp
@@ -39,6 +41,19 @@ def event_loop_is_running():
3941 return False
4042
4143
44+ def sign_message_worker (private_key_hex : str , message : str ) -> str :
45+ from bittensor_wallet import Keypair
46+
47+ # Re-instantiate the keypair from the private key
48+ # ss58_address is required but can be dummy if only signing?
49+ # Actually bittensor_wallet Keypair usually takes ss58_address.
50+ # If private_key is provided, it might derive it.
51+ # Let's try passing None or empty string if allowed, or check Keypair usage.
52+ # Safe bet: pass private key. Keypair usually derives public from private.
53+ kp = Keypair (private_key = private_key_hex )
54+ return f"0x{ kp .sign (message ).hex ()} "
55+
56+
4257class DendriteMixin :
4358 """
4459 The Dendrite class represents the abstracted implementation of a network client module.
@@ -121,6 +136,7 @@ def __init__(self, wallet: Optional[Union["Wallet", "Keypair"]] = None):
121136 self .synapse_history : list = []
122137
123138 self ._session : Optional [aiohttp .ClientSession ] = None
139+ self ._executor = ProcessPoolExecutor (max_workers = 1 )
124140
125141 @property
126142 async def session (self ) -> aiohttp .ClientSession :
@@ -192,6 +208,10 @@ def close_session(self, using_new_loop: bool = False):
192208 if using_new_loop :
193209 loop .close ()
194210 self ._session = None
211+
212+ if self ._executor :
213+ self ._executor .shutdown (wait = True )
214+ self ._executor = None
195215
196216 async def aclose_session (self ):
197217 """
@@ -217,6 +237,10 @@ async def aclose_session(self):
217237 if self ._session :
218238 await self ._session .close ()
219239 self ._session = None
240+
241+ if self ._executor :
242+ self ._executor .shutdown (wait = True )
243+ self ._executor = None
220244
221245 def _get_endpoint_url (self , target_axon , request_name ):
222246 """
@@ -568,7 +592,8 @@ async def call(
568592 url = self ._get_endpoint_url (target_axon , request_name = request_name )
569593
570594 # Preprocess synapse for making a request
571- synapse = self .preprocess_synapse_for_request (target_axon , synapse , timeout )
595+ synapse = await self .preprocess_synapse_for_request (target_axon , synapse , timeout )
596+
572597
573598 try :
574599 # Log outgoing request
@@ -643,7 +668,8 @@ async def call_stream(
643668 url = f"http://{ endpoint } /{ request_name } "
644669
645670 # Preprocess synapse for making a request
646- synapse = self .preprocess_synapse_for_request (target_axon , synapse , timeout ) # type: ignore
671+ synapse = await self .preprocess_synapse_for_request (target_axon , synapse , timeout ) # type: ignore
672+
647673
648674 try :
649675 # Log outgoing request
@@ -682,7 +708,7 @@ async def call_stream(
682708 else :
683709 yield synapse
684710
685- def preprocess_synapse_for_request (
711+ async def preprocess_synapse_for_request (
686712 self ,
687713 target_axon_info : "AxonInfo" ,
688714 synapse : "Synapse" ,
@@ -719,7 +745,12 @@ def preprocess_synapse_for_request(
719745
720746 # Sign the request using the dendrite, axon info, and the synapse body hash
721747 message = f"{ synapse .dendrite .nonce } .{ synapse .dendrite .hotkey } .{ synapse .axon .hotkey } .{ synapse .dendrite .uuid } .{ synapse .body_hash } "
722- synapse .dendrite .signature = f"0x{ self .keypair .sign (message ).hex ()} "
748+
749+ loop = asyncio .get_running_loop ()
750+ synapse .dendrite .signature = await loop .run_in_executor (
751+ self ._executor ,
752+ partial (sign_message_worker , self .keypair .private_key , message )
753+ )
723754
724755 return synapse
725756
0 commit comments