Beispiel #1
0
    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
Beispiel #2
0
        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')
Beispiel #3
0
    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]
Beispiel #4
0
    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'])
Beispiel #5
0
    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
Beispiel #6
0
    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
Beispiel #7
0
 def test_exceptions(self):
     with self.assertRaises(ValueError):
         HDWallet(word_count=3)
Beispiel #8
0
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)
Beispiel #9
0
    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)