def wallet_rm(ctx, wallet_idx, skip_confirmation): """ Removes an address from the wallet using the given address index. Warning! Use with caution. Removing an address from the wallet will result in loss of access to the address and is not reversible unless you have address recovery information. Use the wallet_secret command for obtaining the recovery Mnemonic/Hexseed and the wallet_recover command for restoring an address. """ wallet = Wallet(wallet_path=ctx.obj.wallet_path) address_item = get_item_from_wallet(wallet, wallet_idx) if address_item: if not skip_confirmation: click.echo( 'You are about to remove address [{0}]: {1} from the wallet.'.format(wallet_idx, address_item.qaddress)) click.echo( 'Warning! By continuing, you risk complete loss of access to this address if you do not have a ' 'recovery Mnemonic/Hexseed.') click.confirm('Do you want to continue?', abort=True) wallet.remove(address_item.qaddress) _print_addresses(ctx, wallet.address_items, config.user.wallet_dir)
def test_create(self): with set_xrd_dir("no_data"): wallet = Wallet() self.assertEqual(0, len(wallet.address_items)) xmss1 = wallet.add_new_address(4) self.assertEqual(1, len(wallet.address_items)) xmss2 = wallet.get_xmss_by_index(0) self.assertEqual(xmss1.address, xmss2.address) self.assertEqual(xmss1.mnemonic, xmss2.mnemonic)
def wallet_secret(ctx, wallet_idx): """ Provides the mnemonic/hexseed of the given address index """ wallet = Wallet(wallet_path=ctx.obj.wallet_path) if wallet.encrypted: secret = click.prompt('The wallet is encrypted. Enter password', hide_input=True) wallet.decrypt(secret) address_item = get_item_from_wallet(wallet, wallet_idx) if address_item: click.echo('Wallet Address : {}'.format(address_item.qaddress)) click.echo('Mnemonic : {}'.format(address_item.mnemonic)) click.echo('Hexseed : {}'.format(address_item.hexseed))
def wallet_add(ctx, height, hash_function): """ Adds an address or generates a new wallet (working directory) """ secret = None wallet = Wallet(wallet_path=ctx.obj.wallet_path) wallet_was_encrypted = wallet.encrypted if wallet.encrypted: secret = click.prompt('The wallet is encrypted. Enter password', hide_input=True) wallet.decrypt(secret) wallet.add_new_address(height, hash_function) _print_addresses(ctx, wallet.address_items, config.user.wallet_dir) if wallet_was_encrypted: wallet.encrypt(secret) wallet.save()
def _select_wallet(ctx, address_or_index): try: wallet = Wallet(wallet_path=ctx.obj.wallet_path) if not wallet.addresses: click.echo('This command requires a local wallet') return if wallet.encrypted: secret = click.prompt('The wallet is encrypted. Enter password', hide_input=True) wallet.decrypt(secret) if address_or_index.isdigit(): address_or_index = int(address_or_index) addr_item = get_item_from_wallet(wallet, address_or_index) if addr_item: # FIXME: This should only return pk and index xmss = wallet.get_xmss_by_index(address_or_index) return wallet.addresses[address_or_index], xmss elif address_or_index.startswith('Q'): for i, addr_item in enumerate(wallet.address_items): if address_or_index == addr_item.qaddress: xmss = wallet.get_xmss_by_address(wallet.addresses[i]) return wallet.addresses[i], xmss click.echo('Source address not found in your wallet', color='yellow') quit(1) return parse_qaddress(address_or_index), None except Exception as e: click.echo("Error selecting wallet") click.echo(str(e)) quit(1)
def test_decrypt_wallet(self): with set_xrd_dir("no_data"): wallet = Wallet() wallet.add_new_address(height=4) wallet.add_new_address(height=4) addresses = wallet.addresses TEST_KEY = 'mytestkey' wallet.encrypt(TEST_KEY) self.assertTrue(wallet.encrypted) wallet.decrypt(TEST_KEY) self.assertEqual(addresses, wallet.addresses) self.assertFalse(wallet.encrypted_partially)
def wallet_encrypt(ctx): wallet = Wallet(wallet_path=ctx.obj.wallet_path) click.echo('Encrypting wallet at {}'.format(wallet.wallet_path)) secret = click.prompt('Enter password', hide_input=True, confirmation_prompt=True) wallet.encrypt(secret) wallet.save()
def test_read_ver0(self): with set_xrd_dir("wallet_ver0"): wallet = Wallet() self.assertEqual(1, len(wallet.address_items)) self.assertEqual(wallet.version, 0) addr_item = wallet.address_items[0] self.assertFalse(addr_item.encrypted) self.assertEqual( 'Q010400d9f1efe5b272e042dcc8ef690f0e90ca8b0b6edba0d26f81e7aff12a6754b21788169f7f', addr_item.qaddress) xmss0 = wallet.get_xmss_by_index(0) self.assertEqual( '010400d9f1efe5b272e042dcc8ef690f0e90ca8b0b6edba0d26f81e7aff12a6754b21788169f7f', bin2hstr(xmss0.address)) xmss0b = wallet.get_xmss_by_address(xmss0.address) self.assertEqual( '010400d9f1efe5b272e042dcc8ef690f0e90ca8b0b6edba0d26f81e7aff12a6754b21788169f7f', bin2hstr(xmss0b.address))
def test_create_load(self): with set_xrd_dir("no_data"): wallet = Wallet() wallet.add_new_address(height=4) wallet.save() wallet_b = Wallet() self.assertEqual(1, len(wallet_b.address_items)) self.assertEqual(wallet.address_items[0], wallet_b.address_items[0])
def test_read_wallet_ver0_saves_wallet_ver1(self): with set_xrd_dir("wallet_ver0"): wallet = Wallet() self.assertEqual(wallet.version, 0) wallet.version = 1 wallet.save() wallet_reloaded = Wallet() self.assertEqual(wallet_reloaded.version, 1)
def wallet_gen(ctx, height, hash_function, encrypt): """ Generates a new wallet with one address """ wallet = Wallet(wallet_path=ctx.obj.wallet_path) if len(wallet.address_items) > 0: click.echo("Wallet already exists") return wallet.add_new_address(height, hash_function) _print_addresses(ctx, wallet.address_items, ctx.obj.wallet_path) if encrypt: secret = click.prompt('Enter password to encrypt wallet with', hide_input=True, confirmation_prompt=True) wallet.encrypt(secret) wallet.save()
def test_create_custom_hash_function_load(self): with set_xrd_dir("no_data"): wallet = Wallet() xmss = wallet.add_new_address(height=4, hash_function="sha2_256") wallet.save() self.assertEqual("sha2_256", xmss.hash_function) wallet_reloaded = Wallet() self.assertEqual("sha2_256", wallet_reloaded.address_items[0].hashFunction)
def test_encrypt_wallet(self): # 2 unencrypted addresses. This should work. with set_xrd_dir("no_data"): TEST_KEY = 'mytestkey' wallet = Wallet() wallet.add_new_address(height=4) wallet.add_new_address(height=4) wallet.encrypt(TEST_KEY) self.assertTrue(wallet.encrypted) self.assertFalse(wallet.encrypted_partially)
def wallet_decrypt(ctx): wallet = Wallet(wallet_path=ctx.obj.wallet_path) click.echo('Decrypting wallet at {}'.format(wallet.wallet_path)) secret = click.prompt('Enter password', hide_input=True) try: wallet.decrypt(secret) except WalletDecryptionError as e: click.echo(str(e)) quit(1) except Exception as e: click.echo(str(e)) quit(1) try: wallet.save() except Exception as e: click.echo(str(e)) quit(1)
def wallet_recover(ctx, seed_type): """ Recovers a wallet from a hexseed or mnemonic (32 words) """ seed = click.prompt('Please enter your %s' % (seed_type,)) seed = seed.lower().strip() if seed_type == 'mnemonic': words = seed.split() if len(words) != 34: print('You have entered %s words' % (len(words),)) print('Mnemonic seed must contain only 34 words') return bin_seed = mnemonic2bin(seed) else: if len(seed) != 102: print('You have entered hexseed of %s characters' % (len(seed),)) print('Hexseed must be of only 102 characters.') return bin_seed = hstr2bin(seed) wallet = Wallet(wallet_path=ctx.obj.wallet_path) recovered_xmss = XMSS.from_extended_seed(bin_seed) print('Recovered Wallet Address : %s' % (Wallet._get_Qaddress(recovered_xmss.address),)) for addr in wallet.address_items: if recovered_xmss.qaddress == addr.qaddress: print('Wallet Address is already in the wallet list') return if click.confirm('Do you want to save the recovered wallet?'): click.echo('Saving...') wallet.append_xmss(recovered_xmss) wallet.save() click.echo('Done') _print_addresses(ctx, wallet.address_items, config.user.wallet_dir)
def test_read_secure(self): with set_xrd_dir("wallet_secure_ver1"): wallet = Wallet() self.assertEqual(1, len(wallet.address_items)) self.assertEqual(wallet.version, 1) self.assertTrue(wallet.encrypted) addr_item = wallet.address_items[0] self.assertEqual( 'Q010400d9f1efe5b272e042dcc8ef690f0e90ca8b0b6edba0d26f81e7aff12a6754b21788169f7f', addr_item.qaddress) wallet.decrypt_item(0, 'test1234') xmss0 = wallet.get_xmss_by_index(0) self.assertEqual( '010400d9f1efe5b272e042dcc8ef690f0e90ca8b0b6edba0d26f81e7aff12a6754b21788169f7f', bin2hstr(xmss0.address)) xmss0b = wallet.get_xmss_by_address(xmss0.address) self.assertEqual( '010400d9f1efe5b272e042dcc8ef690f0e90ca8b0b6edba0d26f81e7aff12a6754b21788169f7f', bin2hstr(xmss0b.address))
def test_encrypt_save_reload(self): with set_xrd_dir("no_data"): wallet = Wallet() wallet.add_new_address(height=4) wallet.save() wallet_b = Wallet() self.assertEqual(1, len(wallet_b.address_items)) self.assertEqual(wallet.address_items[0], wallet_b.address_items[0]) TEST_KEY = 'mytestkey' wallet_b.encrypt(TEST_KEY) wallet_b.save() self.assertEqual(1, len(wallet_b.address_items)) self.assertNotEqual(wallet.address_items[0], wallet_b.address_items[0]) wallet_c = Wallet() self.assertEqual(1, len(wallet_c.address_items)) self.assertTrue(wallet_c.address_items[0].encrypted) wallet_c.decrypt(TEST_KEY) self.assertFalse(wallet_c.address_items[0].encrypted) self.assertEqual(wallet.address_items[0], wallet_c.address_items[0])
def test_integrity_behaviour(self): with set_xrd_dir("no_data"): TEST_KEY = 'mytestkey' wallet = Wallet() wallet.add_new_address(4) wallet.add_new_address(4) wallet.encrypt(TEST_KEY) # An encrypted wallet is not editable. with self.assertRaises(WalletEncryptionError): wallet.add_new_address(4) # You may not re-encrypt it. with self.assertRaises(WalletEncryptionError): wallet.encrypt(TEST_KEY) # You can save it. wallet.save() wallet.decrypt_item(1, TEST_KEY) # A partially encrypted wallet is not editable. with self.assertRaises(WalletEncryptionError): wallet.add_new_address(4) # You may not re-encrypt it. with self.assertRaises(WalletEncryptionError): wallet.encrypt(TEST_KEY) # You may not re-decrypt it. with self.assertRaises(WalletEncryptionError): wallet.decrypt(TEST_KEY) # You can't even save it. with self.assertRaises(WalletEncryptionError): wallet.save() wallet.decrypt_item(0, TEST_KEY) # A fully decrypted wallet is editable. wallet.add_new_address(4) # You may not re-decrypt it. with self.assertRaises(WalletEncryptionError): wallet.decrypt(TEST_KEY) # You can save it. wallet.save()
def test_create_custom_hash_function(self): with set_xrd_dir("no_data"): wallet = Wallet() xmss = wallet.add_new_address(height=4, hash_function="sha2_256") self.assertEqual("sha2_256", xmss.hash_function)
def wallet_ls(ctx): """ Lists available wallets """ wallet = Wallet(wallet_path=ctx.obj.wallet_path) _print_addresses(ctx, wallet.address_items, ctx.obj.wallet_dir)
def test_read_wallet_secure_ver0_saves_wallet_ver1_encrypted(self): with set_xrd_dir("wallet_secure_ver0"): wallet = Wallet() self.assertEqual(wallet.version, 0) # Wallet will not let you save an encrypted ver0 wallet as ver1. You have to decrypt it first. # This is because Qaddress is unencrypted in the ver1 wallet. with self.assertRaises(WalletVersionError): wallet.save() wallet.decrypt('test1234') wallet.encrypt('test1234') wallet.version = 1 wallet.save() wallet_reloaded = Wallet() self.assertEqual(wallet_reloaded.version, 1) self.assertEqual( wallet_reloaded.address_items[0].qaddress, 'Q010400d9f1efe5b272e042dcc8ef690f0e90ca8b0b6edba0d26f81e7aff12a6754b21788169f7f' ) wallet_reloaded.decrypt('test1234') addr_item = wallet_reloaded.address_items[0] self.assertEqual( 'Q010400d9f1efe5b272e042dcc8ef690f0e90ca8b0b6edba0d26f81e7aff12a6754b21788169f7f', addr_item.qaddress) xmss0 = wallet_reloaded.get_xmss_by_index(0) self.assertEqual( '010400d9f1efe5b272e042dcc8ef690f0e90ca8b0b6edba0d26f81e7aff12a6754b21788169f7f', bin2hstr(xmss0.address)) xmss0b = wallet_reloaded.get_xmss_by_address(xmss0.address) self.assertEqual( '010400d9f1efe5b272e042dcc8ef690f0e90ca8b0b6edba0d26f81e7aff12a6754b21788169f7f', bin2hstr(xmss0b.address))
def test_init(self): with set_xrd_dir("wallet_ver0"): wallet = Wallet() self.assertIsNotNone(wallet)