forked from Datura-ai/subnet-template
-
Notifications
You must be signed in to change notification settings - Fork 1
/
miner.py
163 lines (142 loc) · 5.57 KB
/
miner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import os
import time
import argparse
import traceback
import bittensor as bt
from typing import Tuple
from protocol import Dummy
class Miner:
def __init__(self):
self.config = self.get_config()
self.setup_logging()
self.setup_bittensor_objects()
def get_config(self):
# Set up the configuration parser
parser = argparse.ArgumentParser()
# TODO: Add your custom miner arguments to the parser.
parser.add_argument(
"--custom",
default="my_custom_value",
help="Adds a custom value to the parser.",
)
# Adds override arguments for network and netuid.
parser.add_argument(
"--netuid", type=int, default=1, help="The chain subnet uid."
)
# Adds subtensor specific arguments.
bt.subtensor.add_args(parser)
# Adds logging specific arguments.
bt.logging.add_args(parser)
# Adds wallet specific arguments.
bt.wallet.add_args(parser)
# Adds axon specific arguments.
bt.axon.add_args(parser)
# Parse the arguments.
config = bt.config(parser)
# Set up logging directory
config.full_path = os.path.expanduser(
"{}/{}/{}/netuid{}/{}".format(
config.logging.logging_dir,
config.wallet.name,
config.wallet.hotkey_str,
config.netuid,
"miner",
)
)
# Ensure the directory for logging exists.
os.makedirs(config.full_path, exist_ok=True)
return config
def setup_logging(self):
# Activate Bittensor's logging with the set configurations.
bt.logging(config=self.config, logging_dir=self.config.full_path)
bt.logging.info(
f"Running miner for subnet: {self.config.netuid} on network: {self.config.subtensor.network} with config:"
)
bt.logging.info(self.config)
def setup_bittensor_objects(self):
# Initialize Bittensor miner objects
bt.logging.info("Setting up Bittensor objects.")
# Initialize wallet.
self.wallet = bt.wallet(config=self.config)
bt.logging.info(f"Wallet: {self.wallet}")
# Initialize subtensor.
self.subtensor = bt.subtensor(config=self.config)
bt.logging.info(f"Subtensor: {self.subtensor}")
# Initialize metagraph.
self.metagraph = self.subtensor.metagraph(self.config.netuid)
bt.logging.info(f"Metagraph: {self.metagraph}")
if self.wallet.hotkey.ss58_address not in self.metagraph.hotkeys:
bt.logging.error(
f"\nYour miner: {self.wallet} is not registered to chain connection: {self.subtensor} \nRun 'btcli register' and try again."
)
exit()
else:
# Each miner gets a unique identity (UID) in the network.
self.my_subnet_uid = self.metagraph.hotkeys.index(
self.wallet.hotkey.ss58_address
)
bt.logging.info(f"Running miner on uid: {self.my_subnet_uid}")
def blacklist_fn(self, synapse: Dummy) -> Tuple[bool, str]:
# Ignore requests from unrecognized entities.
if synapse.dendrite.hotkey not in self.metagraph.hotkeys:
bt.logging.trace(
f"Blacklisting unrecognized hotkey {synapse.dendrite.hotkey}"
)
return True, None
bt.logging.trace(
f"Not blacklisting recognized hotkey {synapse.dendrite.hotkey}"
)
return False, None
def dummy(self, synapse: Dummy) -> Dummy:
# Simple logic: return the input value multiplied by 2.
synapse.dummy_output = synapse.dummy_input * 2
bt.logging.info(
f"Received input: {synapse.dummy_input}, sending output: {synapse.dummy_output}"
)
return synapse
def setup_axon(self):
# Build and link miner functions to the axon.
self.axon = bt.axon(wallet=self.wallet, config=self.config)
# Attach functions to the axon.
bt.logging.info("Attaching forward function to axon.")
self.axon.attach(
forward_fn=self.dummy,
blacklist_fn=self.blacklist_fn,
)
# Serve the axon.
bt.logging.info(
f"Serving axon on network: {self.config.subtensor.network} with netuid: {self.config.netuid}"
)
self.axon.serve(netuid=self.config.netuid, subtensor=self.subtensor)
bt.logging.info(f"Axon: {self.axon}")
# Start the axon server.
bt.logging.info(f"Starting axon server on port: {self.config.axon.port}")
self.axon.start()
def run(self):
self.setup_axon()
# Keep the miner alive.
bt.logging.info(f"Starting main loop")
step = 0
while True:
try:
# Periodically update our knowledge of the network graph.
if step % 60 == 0:
self.metagraph.sync()
log = (
f"Block: {self.metagraph.block.item()} | "
f"Incentive: {self.metagraph.I[self.my_subnet_uid]} | "
)
bt.logging.info(log)
step += 1
time.sleep(1)
except KeyboardInterrupt:
self.axon.stop()
bt.logging.success("Miner killed by keyboard interrupt.")
break
except Exception as e:
bt.logging.error(traceback.format_exc())
continue
# Run the miner.
if __name__ == "__main__":
miner = Miner()
miner.run()