def setUp(self): super().setUp() self.wallet = HDWallet(gap_limit=2) self.wallet._manually_initialize() self.manager = self.create_peer('testnet', wallet=self.wallet, unlock_wallet=False) self.tx_storage = self.manager.tx_storage self.wallet.unlock(tx_storage=self.tx_storage) self.BLOCK_TOKENS = self.manager.get_tokens_issued_per_block(1) self.TOKENS = self.BLOCK_TOKENS
def create_wallet(): if args.wallet == 'hd': print('Using HDWallet') kwargs = { 'words': args.words, } if args.passphrase: wallet_passphrase = getpass.getpass( prompt='HD Wallet passphrase:') kwargs['passphrase'] = wallet_passphrase.encode() if args.data: kwargs['directory'] = args.data return HDWallet(**kwargs) elif args.wallet == 'keypair': print('Using KeyPairWallet') if args.data: wallet = Wallet(directory=args.data) else: wallet = Wallet() wallet.flush_to_disk_interval = 5 # seconds if args.unlock_wallet: wallet_passwd = getpass.getpass(prompt='Wallet password:'******'Invalid type for wallet')
def get_address(self, index: int) -> Optional[str]: """ Generate a fixed HD Wallet and return an address """ from hathor.wallet import HDWallet words = ( 'bind daring above film health blush during tiny neck slight clown salmon ' 'wine brown good setup later omit jaguar tourist rescue flip pet salute' ) hd = HDWallet(words=words) hd._manually_initialize() if index >= hd.gap_limit: return None return list(hd.keys.keys())[index]
def test_unlocking_hd_wallet(self): self.manager.wallet = HDWallet() self.manager.wallet._manually_initialize() self.manager.wallet.unlock(tx_storage=self.manager.tx_storage) # Wallet is not locked response = yield self.web_state.get("wallet/state") data = response.json_value() self.assertFalse(data['is_locked']) # Lock the wallet response_lock = yield self.web_lock.post("wallet/lock") data_lock = response_lock.json_value() self.assertTrue(data_lock['success']) # Wallet is locked response_locked = yield self.web_state.get("wallet/state") data_locked = response_locked.json_value() self.assertTrue(data_locked['is_locked']) # Unlock wallet invalid words response_invalid = yield self.web.post("wallet/unlock", { 'words': 'abc def', 'passphrase': '' }) data_invalid = response_invalid.json_value() self.assertFalse(data_invalid['success']) # Unlock wallet response_success = yield self.web.post("wallet/unlock", {'passphrase': ''}) data_success = response_success.json_value() self.assertTrue(data_success['success']) # Wallet is unlocked response_unlocked = yield self.web_state.get("wallet/state") data_unlocked = response_unlocked.json_value() self.assertFalse(data_unlocked['is_locked']) # Lock the wallet and unlock with same words self.manager.wallet.lock() response_words = yield self.web.post("wallet/unlock", { 'words': data_success['words'], 'passphrase': '' }) data_words = response_words.json_value() self.assertTrue(data_words['success'])
def create_peer(self, network, unlock_wallet=True): wallet = HDWallet(gap_limit=2) wallet._manually_initialize() manager = super().create_peer(network, wallet=wallet) manager.test_mode = TestMode.TEST_ALL_WEIGHT manager.avg_time_between_blocks = 64 # Don't use it anywhere else. It is unsafe to generate mnemonic words like this. # It should be used only for testing purposes. m = Mnemonic('english') words = m.to_mnemonic(bytes(random.randint(0, 255) for _ in range(32))) wallet.unlock(words=words, tx_storage=manager.tx_storage) return manager
def create_peer(self, network: Optional[str] = None, peer_id: Optional[PeerId] = None, enable_sync_v1: bool = True, enable_sync_v2: bool = True, soft_voided_tx_ids: Optional[Set[bytes]] = None) -> HathorManager: assert self._started if network is None: network = self._network wallet = HDWallet(gap_limit=2) wallet._manually_initialize() assert peer_id is not None # XXX: temporary, for checking that tests are using the peer_id if peer_id is None: peer_id = PeerId() tx_storage = TransactionMemoryStorage() manager = HathorManager( self._clock, peer_id=peer_id, network=network, wallet=wallet, enable_sync_v1=enable_sync_v1, enable_sync_v2=enable_sync_v2, tx_storage=tx_storage, rng=Random(self.rng.getrandbits(64)), soft_voided_tx_ids=soft_voided_tx_ids, ) manager.reactor = self._clock manager._full_verification = True manager.start() self.run_to_completion() # Don't use it anywhere else. It is unsafe to generate mnemonic words like this. # It should be used only for testing purposes. m = Mnemonic('english') words = m.to_mnemonic(self.rng.randbytes(32)) self.log.debug('randomized step: generate wallet', words=words) wallet.unlock(words=words, tx_storage=manager.tx_storage) return manager
def test_exceptions(self): with self.assertRaises(ValueError): HDWallet(word_count=3)
class BaseWalletHDTest(unittest.TestCase): __test__ = False def setUp(self): super().setUp() self.wallet = HDWallet(gap_limit=2) self.wallet._manually_initialize() self.manager = self.create_peer('testnet', wallet=self.wallet, unlock_wallet=False) self.tx_storage = self.manager.tx_storage self.wallet.unlock(tx_storage=self.tx_storage) self.BLOCK_TOKENS = self.manager.get_tokens_issued_per_block(1) self.TOKENS = self.BLOCK_TOKENS def test_transaction_and_balance(self): # generate a new block and check if we increase balance new_address = self.wallet.get_unused_address() out = WalletOutputInfo(decode_address(new_address), self.TOKENS, timelock=None) block = add_new_block(self.manager) block.verify() utxo = self.wallet.unspent_txs[settings.HATHOR_TOKEN_UID].get( (block.hash, 0)) self.assertIsNotNone(utxo) self.assertEqual(self.wallet.balance[settings.HATHOR_TOKEN_UID], WalletBalance(0, self.BLOCK_TOKENS)) # create transaction spending this value, but sending to same wallet add_blocks_unlock_reward(self.manager) new_address2 = self.wallet.get_unused_address() out = WalletOutputInfo(decode_address(new_address2), self.TOKENS, timelock=None) tx1 = self.wallet.prepare_transaction_compute_inputs( Transaction, [out], self.tx_storage) tx1.update_hash() tx1.verify_script(tx1.inputs[0], block) tx1.storage = self.tx_storage self.wallet.on_new_tx(tx1) self.tx_storage.save_transaction(tx1) self.assertEqual(len(self.wallet.spent_txs), 1) utxo = self.wallet.unspent_txs[settings.HATHOR_TOKEN_UID].get( (tx1.hash, 0)) self.assertIsNotNone(utxo) self.assertEqual(self.wallet.balance[settings.HATHOR_TOKEN_UID], WalletBalance(0, self.TOKENS)) # pass inputs and outputs to prepare_transaction, but not the input keys # spend output last transaction input_info = WalletInputInfo(tx1.hash, 0, None) new_address3 = self.wallet.get_unused_address() out = WalletOutputInfo(decode_address(new_address3), self.TOKENS, timelock=None) tx2 = self.wallet.prepare_transaction_incomplete_inputs( Transaction, inputs=[input_info], outputs=[out], tx_storage=self.tx_storage) tx2.storage = self.tx_storage tx2.update_hash() tx2.storage = self.tx_storage tx2.verify_script(tx2.inputs[0], tx1) self.tx_storage.save_transaction(tx2) self.wallet.on_new_tx(tx2) self.assertEqual(len(self.wallet.spent_txs), 2) self.assertEqual(self.wallet.balance[settings.HATHOR_TOKEN_UID], WalletBalance(0, self.TOKENS)) # Test getting more unused addresses than the gap limit for i in range(3): kwargs = {'mark_as_used': True} if i == 2: # Last one we dont mark as used kwargs['mark_as_used'] = False self.wallet.get_unused_address(**kwargs) def test_insuficient_funds(self): add_blocks_unlock_reward(self.manager) # create transaction spending some value new_address = self.wallet.get_unused_address() out = WalletOutputInfo(decode_address(new_address), self.TOKENS, timelock=None) with self.assertRaises(InsufficientFunds): self.wallet.prepare_transaction_compute_inputs( Transaction, [out], self.tx_storage) def test_lock(self): # Test locking and unlocking wallet # Initially is unlocked self.assertFalse(self.wallet.is_locked()) words = self.wallet.words address = self.wallet.get_unused_address() # We lock self.wallet.lock() # Now it's locked self.assertTrue(self.wallet.is_locked()) # We unlock self.wallet.unlock(tx_storage=self.tx_storage, words=words) self.assertFalse(self.wallet.is_locked()) self.assertEqual(address, self.wallet.get_unused_address()) def test_exceptions(self): with self.assertRaises(ValueError): HDWallet(word_count=3)
def test_checkmultisig(self): with self.assertRaises(MissingStackItems): op_checkmultisig([], log=[], extras=None) block = self.genesis_blocks[0] from hathor.transaction import Transaction, TxInput, TxOutput txin = TxInput(tx_id=block.hash, index=0, data=b'') txout = TxOutput(value=block.outputs[0].value, script=b'') tx = Transaction(inputs=[txin], outputs=[txout]) data_to_sign = tx.get_sighash_all() extras = ScriptExtras(tx=tx, txin=None, spent_tx=None) wallet = HDWallet() wallet._manually_initialize() wallet.words = wallet.mnemonic.generate() wallet._manually_initialize() keys_count = 3 keys = [] for i in range(keys_count): privkey = list(wallet.keys.values())[i] keys.append({ 'privkey': privkey, 'pubkey': privkey.sec(), 'signature': wallet.get_input_aux_data(data_to_sign, privkey)[1] }) wrong_privkey = list(wallet.keys.values())[3] wrong_key = { 'privkey': wrong_privkey, 'pubkey': wrong_privkey.sec(), 'signature': wallet.get_input_aux_data(data_to_sign, wrong_privkey)[1] } # All signatures match stack = [ keys[0]['signature'], keys[2]['signature'], 2, keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], 3 ] op_checkmultisig(stack, log=[], extras=extras) self.assertEqual(1, stack.pop()) # New set of valid signatures stack = [ keys[0]['signature'], keys[1]['signature'], 2, keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], 3 ] op_checkmultisig(stack, log=[], extras=extras) self.assertEqual(1, stack.pop()) # Changing the signatures but they match stack = [ keys[1]['signature'], keys[2]['signature'], 2, keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], 3 ] op_checkmultisig(stack, log=[], extras=extras) self.assertEqual(1, stack.pop()) # Signatures are valid but in wrong order stack = [ keys[1]['signature'], keys[0]['signature'], 2, keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], 3 ] op_checkmultisig(stack, log=[], extras=extras) self.assertEqual(0, stack.pop()) # Adding wrong signature, so we get error stack = [ keys[0]['signature'], wrong_key['signature'], 2, keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], 3 ] op_checkmultisig(stack, log=[], extras=extras) self.assertEqual(0, stack.pop()) # Adding same signature twice, so we get error stack = [ keys[0]['signature'], keys[0]['signature'], 2, keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], 3 ] op_checkmultisig(stack, log=[], extras=extras) self.assertEqual(0, stack.pop()) # Adding less signatures than required, so we get error stack = [ keys[0]['signature'], 2, keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], 3 ] with self.assertRaises(MissingStackItems): op_checkmultisig(stack, log=[], extras=extras) # Quantity of signatures is more than it should stack = [ keys[0]['signature'], keys[1]['signature'], 3, keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], 3 ] with self.assertRaises(MissingStackItems): op_checkmultisig(stack, log=[], extras=extras) # Quantity of pubkeys is more than it should stack = [ keys[0]['signature'], keys[1]['signature'], 2, keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], 4 ] with self.assertRaises(InvalidStackData): op_checkmultisig(stack, log=[], extras=extras) # Exception pubkey_count should be integer stack = [ keys[0]['signature'], keys[1]['signature'], 2, keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], '3' ] with self.assertRaises(InvalidStackData): op_checkmultisig(stack, log=[], extras=extras) # Exception not enough pub keys stack = [keys[0]['pubkey'], keys[1]['pubkey'], 3] with self.assertRaises(MissingStackItems): op_checkmultisig(stack, log=[], extras=extras) # Exception stack empty after pubkeys stack = [keys[0]['pubkey'], keys[1]['pubkey'], keys[2]['pubkey'], 3] with self.assertRaises(MissingStackItems): op_checkmultisig(stack, log=[], extras=extras)