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

[feature] add --seed option to regen_hotkey #916

Merged
merged 6 commits into from
Sep 15, 2022
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
15 changes: 12 additions & 3 deletions bittensor/_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,12 @@ def config(args: List[str]) -> 'bittensor.config':
nargs="+",
help='Mnemonic used to regen your key i.e. horse cart dog ...'
)
regen_hotkey_parser.add_argument(
"--seed",
required=False,
default=None,
help='Seed hex string used to regen your key i.e. 0x1234...'
)
regen_hotkey_parser.add_argument(
'--use_password',
dest='use_password',
Expand Down Expand Up @@ -891,16 +897,19 @@ def check_regen_hotkey_config( config: 'bittensor.Config' ):
hotkey = Prompt.ask("Enter hotkey name", default = bittensor.defaults.wallet.hotkey)
config.wallet.hotkey = str(hotkey)

if config.mnemonic == None:
config.mnemonic = Prompt.ask("Enter mnemonic")
if config.mnemonic == None and config.seed == None:
prompt_answer = Prompt.ask("Enter mnemonic or seed")
if prompt_answer.startswith("0x"):
config.seed = prompt_answer
else:
config.mnemonic = prompt_answer

def check_regen_coldkey_config( config: 'bittensor.Config' ):
if config.wallet.get('name') == bittensor.defaults.wallet.name and not config.no_prompt:
wallet_name = Prompt.ask("Enter wallet name", default = bittensor.defaults.wallet.name)
config.wallet.name = str(wallet_name)
if config.mnemonic == None and config.seed == None:
prompt_answer = Prompt.ask("Enter mnemonic or seed")
print(prompt_answer)
if prompt_answer.startswith("0x"):
config.seed = prompt_answer
else:
Expand Down
2 changes: 1 addition & 1 deletion bittensor/_cli/cli_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def regen_hotkey ( self ):
r""" Creates a new coldkey under this wallet.
"""
wallet = bittensor.wallet(config = self.config)
wallet.regenerate_hotkey( mnemonic = self.config.mnemonic, use_password = self.config.use_password, overwrite = self.config.overwrite_hotkey)
wallet.regenerate_hotkey( mnemonic = self.config.mnemonic, seed=self.config.seed, use_password = self.config.use_password, overwrite = self.config.overwrite_hotkey)

def query ( self ):
r""" Query an endpoint and get query time.
Expand Down
29 changes: 20 additions & 9 deletions bittensor/_wallet/wallet_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ def regenerate_coldkeypub( self, ss58_address: Optional[str] = None, public_key:
# Short name for regenerate_coldkeypub
regen_coldkeypub = regenerate_coldkeypub

def regenerate_coldkey( self, mnemonic: Optional[Union[list, str]]=None, seed: Optional[str]=None, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
def regenerate_coldkey( self, mnemonic: Optional[Union[list, str]] = None, seed: Optional[str] = None, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
""" Regenerates the coldkey from passed mnemonic, encrypts it with the user's password and save the file
Args:
mnemonic: (Union[list, str], optional):
Expand Down Expand Up @@ -700,11 +700,13 @@ def regenerate_coldkey( self, mnemonic: Optional[Union[list, str]]=None, seed: O
self.set_coldkeypub( keypair, overwrite = overwrite)
return self

def regen_hotkey( self, mnemonic: Union[list, str], use_password: bool = True, overwrite:bool = False) -> 'Wallet':
def regen_hotkey( self, mnemonic: Optional[Union[list, str]], seed: Optional[str] = None, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
""" Regenerates the hotkey from passed mnemonic, encrypts it with the user's password and save the file
Args:
mnemonic: (Union[list, str], optional):
Key mnemonic as list of words or string space separated words.
seed: (str, optional):
Seed as hex string.
use_password (bool, optional):
Is the created key password protected.
overwrite (bool, optional):
Expand All @@ -713,13 +715,15 @@ def regen_hotkey( self, mnemonic: Union[list, str], use_password: bool = True, o
wallet (bittensor.Wallet):
this object with newly created hotkey.
"""
self.regenerate_hotkey(mnemonic, use_password, overwrite)
self.regenerate_hotkey(mnemonic, seed, use_password, overwrite)

def regenerate_hotkey( self, mnemonic: Union[list, str], use_password: bool = True, overwrite:bool = False) -> 'Wallet':
def regenerate_hotkey( self, mnemonic: Optional[Union[list, str]] = None, seed: Optional[str] = None, use_password: bool = True, overwrite:bool = False) -> 'Wallet':
""" Regenerates the hotkey from passed mnemonic, encrypts it with the user's password and save the file
Args:
mnemonic: (Union[list, str], optional):
Key mnemonic as list of words or string space separated words.
seed: (str, optional):
Seed as hex string.
use_password (bool, optional):
Is the created key password protected.
overwrite (bool, optional):
Expand All @@ -728,10 +732,17 @@ def regenerate_hotkey( self, mnemonic: Union[list, str], use_password: bool = Tr
wallet (bittensor.Wallet):
this object with newly created hotkey.
"""
if isinstance( mnemonic, str): mnemonic = mnemonic.split()
if len(mnemonic) not in [12,15,18,21,24]:
raise ValueError("Mnemonic has invalid size. This should be 12,15,18,21 or 24 words")
keypair = Keypair.create_from_mnemonic(" ".join(mnemonic))
display_mnemonic_msg( keypair, "hotkey" )
if mnemonic is None and seed is None:
raise ValueError("Must pass either mnemonic or seed")
if mnemonic is not None:
if isinstance( mnemonic, str): mnemonic = mnemonic.split()
if len(mnemonic) not in [12,15,18,21,24]:
raise ValueError("Mnemonic has invalid size. This should be 12,15,18,21 or 24 words")
keypair = Keypair.create_from_mnemonic(" ".join(mnemonic))
display_mnemonic_msg( keypair, "hotkey" )
else:
# seed is not None
keypair = Keypair.create_from_seed(seed)

self.set_hotkey( keypair, encrypt=use_password, overwrite = overwrite)
return self
1 change: 1 addition & 0 deletions tests/integration_tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@ def test_regen_hotkey( self ):
config.subtensor._mock = True
config.model = "core_server"
config.mnemonic = "faculty decade seven jelly gospel axis next radio grain radio remain gentle"
config.seed = None
config.n_words = 12
config.use_password = False
config.no_prompt = True
Expand Down
30 changes: 30 additions & 0 deletions tests/unit_tests/bittensor_tests/test_wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,33 @@ def test_regen_coldkeypub_no_pubkey(self):
with pytest.raises(ValueError):
# Must provide either public_key or ss58_address
self.mock_wallet.regenerate_coldkeypub(ss58_address=None, public_key=None)

def test_regen_coldkey_from_hex_seed_str(self):
ss58_addr = "5D5cwd8DX6ij7nouVcoxDuWtJfiR1BnzCkiBVTt7DU8ft5Ta"
seed_str = "0x659c024d5be809000d0d93fe378cfde020846150b01c49a201fc2a02041f7636"
with patch.object(self.mock_wallet, 'set_coldkey') as mock_set_coldkey:
self.mock_wallet.regenerate_coldkey(seed=seed_str)

mock_set_coldkey.assert_called_once()
keypair: bittensor.Keypair = mock_set_coldkey.call_args_list[0][0][0]
self.assertEqual(keypair.seed_hex, seed_str)
self.assertEqual(keypair.ss58_address, ss58_addr) # Check that the ss58 address is correct

seed_str_bad = "0x659c024d5be809000d0d93fe378cfde020846150b01c49a201fc2a02041f763" # 1 character short
with pytest.raises(ValueError):
self.mock_wallet.regenerate_coldkey(seed=seed_str_bad)

def test_regen_hotkey_from_hex_seed_str(self):
ss58_addr = "5D5cwd8DX6ij7nouVcoxDuWtJfiR1BnzCkiBVTt7DU8ft5Ta"
seed_str = "0x659c024d5be809000d0d93fe378cfde020846150b01c49a201fc2a02041f7636"
with patch.object(self.mock_wallet, 'set_hotkey') as mock_set_hotkey:
self.mock_wallet.regenerate_hotkey(seed=seed_str)

mock_set_hotkey.assert_called_once()
keypair: bittensor.Keypair = mock_set_hotkey.call_args_list[0][0][0]
self.assertEqual(keypair.seed_hex, seed_str)
self.assertEqual(keypair.ss58_address, ss58_addr) # Check that the ss58 address is correct

seed_str_bad = "0x659c024d5be809000d0d93fe378cfde020846150b01c49a201fc2a02041f763" # 1 character short
with pytest.raises(ValueError):
self.mock_wallet.regenerate_hotkey(seed=seed_str_bad)