示例#1
0
    def test_regular_tx(self):
        # this should succeed
        parents = [tx.hash for tx in self.genesis_txs]
        genesis_block = self.genesis_blocks[0]

        value = genesis_block.outputs[0].value
        address = get_address_from_public_key(self.genesis_public_key)
        script = P2PKH.create_output_script(address)
        output = TxOutput(value, script)

        _input = TxInput(genesis_block.hash, 0, b'')
        tx = Transaction(weight=1,
                         inputs=[_input],
                         outputs=[output],
                         parents=parents,
                         storage=self.tx_storage,
                         timestamp=self.last_block.timestamp + 1)

        data_to_sign = tx.get_sighash_all()
        public_bytes, signature = self.wallet.get_input_aux_data(
            data_to_sign, self.genesis_private_key)
        _input.data = P2PKH.create_input_data(public_bytes, signature)

        tx.resolve()
        tx.verify()
示例#2
0
    def test_token_transfer(self):
        wallet = self.manager.wallet
        tx = create_tokens(self.manager, self.address_b58)
        token_uid = tx.tokens[0]
        utxo = tx.outputs[0]

        parents = self.manager.get_new_tx_parents()
        _input1 = TxInput(tx.hash, 0, b'')
        script = P2PKH.create_output_script(self.address)

        # regular transfer
        token_output = TxOutput(utxo.value, script, 1)
        tx2 = Transaction(weight=1, inputs=[_input1], outputs=[token_output], parents=parents, tokens=[token_uid],
                          storage=self.manager.tx_storage, timestamp=int(self.clock.seconds()))
        data_to_sign = tx2.get_sighash_all(clear_input_data=True)
        public_bytes, signature = wallet.get_input_aux_data(data_to_sign, wallet.get_private_key(self.address_b58))
        tx2.inputs[0].data = P2PKH.create_input_data(public_bytes, signature)
        tx2.resolve()
        tx2.verify()

        # missing tokens
        token_output = TxOutput(utxo.value - 1, script, 1)
        tx3 = Transaction(weight=1, inputs=[_input1], outputs=[token_output], parents=parents, tokens=[token_uid],
                          storage=self.manager.tx_storage, timestamp=int(self.clock.seconds()))
        data_to_sign = tx3.get_sighash_all(clear_input_data=True)
        public_bytes, signature = wallet.get_input_aux_data(data_to_sign, wallet.get_private_key(self.address_b58))
        tx3.inputs[0].data = P2PKH.create_input_data(public_bytes, signature)
        tx3.resolve()
        with self.assertRaises(InputOutputMismatch):
            tx3.verify()
示例#3
0
    def test_weight_inf(self):
        # this should succeed
        parents = [tx.hash for tx in self.genesis_txs]
        genesis_block = self.genesis_blocks[0]

        value = genesis_block.outputs[0].value
        address = get_address_from_public_key(self.genesis_public_key)
        script = P2PKH.create_output_script(address)
        output = TxOutput(value, script)

        _input = TxInput(genesis_block.hash, 0, b'')
        tx = Transaction(inputs=[_input],
                         outputs=[output],
                         parents=parents,
                         storage=self.tx_storage)
        tx.weight = float('inf')

        data_to_sign = tx.get_sighash_all()
        public_bytes, signature = self.wallet.get_input_aux_data(
            data_to_sign, self.genesis_private_key)
        _input.data = P2PKH.create_input_data(public_bytes, signature)

        tx.update_hash()
        self.assertTrue(isinf(tx.weight))
        with self.assertRaises(WeightError):
            tx.verify()
示例#4
0
    def test_unknown_authority(self):
        wallet = self.manager.wallet
        tx = create_tokens(self.manager, self.address_b58, mint_amount=500)
        token_uid = tx.tokens[0]
        parents = self.manager.get_new_tx_parents()
        script = P2PKH.create_output_script(self.address)

        # try an unknown authority
        input1 = TxInput(tx.hash, 1, b'')
        input2 = TxInput(tx.hash, 2, b'')
        output = TxOutput((TxOutput.ALL_AUTHORITIES << 1), script, 0b10000001)
        tx2 = Transaction(weight=1,
                          inputs=[input1, input2],
                          outputs=[output],
                          parents=parents,
                          tokens=[token_uid],
                          storage=self.manager.tx_storage,
                          timestamp=int(self.clock.seconds()))
        data_to_sign = tx2.get_sighash_all()
        public_bytes, signature = wallet.get_input_aux_data(
            data_to_sign, wallet.get_private_key(self.address_b58))
        data = P2PKH.create_input_data(public_bytes, signature)
        tx2.inputs[0].data = data
        tx2.inputs[1].data = data
        tx2.resolve()
        with self.assertRaises(InvalidToken):
            tx2.verify()
示例#5
0
    def test_tx_duplicated_parents(self):
        # the new tx will confirm the same tx twice
        parents = [self.genesis_txs[0].hash, self.genesis_txs[0].hash]
        genesis_block = self.genesis_blocks[0]

        value = genesis_block.outputs[0].value
        address = get_address_from_public_key(self.genesis_public_key)
        script = P2PKH.create_output_script(address)
        output = TxOutput(value, script)

        _input = TxInput(genesis_block.hash, 0, b'')
        tx = Transaction(weight=1,
                         inputs=[_input],
                         outputs=[output],
                         parents=parents,
                         storage=self.tx_storage,
                         timestamp=self.last_block.timestamp + 1)

        data_to_sign = tx.get_sighash_all()
        public_bytes, signature = self.wallet.get_input_aux_data(
            data_to_sign, self.genesis_private_key)
        _input.data = P2PKH.create_input_data(public_bytes, signature)

        tx.resolve()
        with self.assertRaises(DuplicatedParents):
            tx.verify()
示例#6
0
    def test_tx_inputs_conflict(self):
        # the new tx inputs will try to spend the same output
        parents = [tx.hash for tx in self.genesis_txs]
        genesis_block = self.genesis_blocks[0]

        value = genesis_block.outputs[0].value
        address = get_address_from_public_key(self.genesis_public_key)
        script = P2PKH.create_output_script(address)
        # We can't only duplicate the value because genesis is using the max value possible
        outputs = [TxOutput(value, script), TxOutput(value, script)]

        _input = TxInput(genesis_block.hash, 0, b'')
        tx = Transaction(weight=1,
                         inputs=[_input, _input],
                         outputs=outputs,
                         parents=parents,
                         storage=self.tx_storage,
                         timestamp=self.last_block.timestamp + 1)

        data_to_sign = tx.get_sighash_all()
        public_bytes, signature = self.wallet.get_input_aux_data(
            data_to_sign, self.genesis_private_key)
        _input.data = P2PKH.create_input_data(public_bytes, signature)

        tx.resolve()
        with self.assertRaises(ConflictingInputs):
            tx.verify()
示例#7
0
    def test_token_transfer_authority(self):
        wallet = self.manager.wallet
        tx = create_tokens(self.manager, self.address_b58)
        token_uid = tx.tokens[0]
        parents = self.manager.get_new_tx_parents()
        script = P2PKH.create_output_script(self.address)

        # input with mint and output with melt
        _input1 = TxInput(tx.hash, 1, b'')
        token_output = TxOutput(TxOutput.TOKEN_MELT_MASK, script, 0b10000001)
        tx2 = Transaction(weight=1, inputs=[_input1], outputs=[token_output], parents=parents, tokens=[token_uid],
                          storage=self.manager.tx_storage, timestamp=int(self.clock.seconds()))
        data_to_sign = tx2.get_sighash_all(clear_input_data=True)
        public_bytes, signature = wallet.get_input_aux_data(data_to_sign, wallet.get_private_key(self.address_b58))
        tx2.inputs[0].data = P2PKH.create_input_data(public_bytes, signature)
        tx2.resolve()
        with self.assertRaises(InvalidToken):
            tx2.verify()

        # input with melt and output with mint
        _input1 = TxInput(tx.hash, 2, b'')
        token_output = TxOutput(TxOutput.TOKEN_MINT_MASK, script, 0b10000001)
        tx3 = Transaction(weight=1, inputs=[_input1], outputs=[token_output], parents=parents, tokens=[token_uid],
                          storage=self.manager.tx_storage, timestamp=int(self.clock.seconds()))
        data_to_sign = tx3.get_sighash_all(clear_input_data=True)
        public_bytes, signature = wallet.get_input_aux_data(data_to_sign, wallet.get_private_key(self.address_b58))
        tx3.inputs[0].data = P2PKH.create_input_data(public_bytes, signature)
        tx3.resolve()
        with self.assertRaises(InvalidToken):
            tx3.verify()
示例#8
0
    def test_output_value(self):
        from hathor.transaction.base_transaction import bytes_to_output_value
        # first test using a small output value with 8 bytes. It should fail
        parents = [tx.hash for tx in self.genesis_txs]
        outputs = [TxOutput(1, b'')]
        tx = Transaction(outputs=outputs, parents=parents)
        original_struct = tx.get_struct()
        struct_bytes = tx.get_funds_struct()

        # we'll get the struct without the last output bytes and add it ourselves
        struct_bytes = struct_bytes[:-7]
        # add small value using 8 bytes and expect failure when trying to deserialize
        struct_bytes += (-1).to_bytes(8, byteorder='big', signed=True)
        struct_bytes += int_to_bytes(0, 1)
        struct_bytes += int_to_bytes(0, 2)
        struct_bytes += tx.get_graph_struct()
        struct_bytes += int_to_bytes(tx.nonce, tx.SERIALIZATION_NONCE_SIZE)

        len_difference = len(struct_bytes) - len(original_struct)
        assert len_difference == 4, 'new struct is incorrect, len difference={}'.format(len_difference)

        with self.assertRaises(ValueError):
            Transaction.create_from_struct(struct_bytes)

        # now use 8 bytes and make sure it's working
        outputs = [TxOutput(MAX_OUTPUT_VALUE, b'')]
        tx = Transaction(outputs=outputs, parents=parents)
        tx.update_hash()
        original_struct = tx.get_struct()
        tx2 = Transaction.create_from_struct(original_struct)
        tx2.update_hash()
        assert tx == tx2

        # Validating that all output values must be positive
        value = 1
        address = decode_address('WUDtnw3GYjvUnZmiHAmus6hhs9GoSUSJMG')
        script = P2PKH.create_output_script(address)
        output = TxOutput(value, script)
        output.value = -1
        tx = Transaction(inputs=[], outputs=[output], parents=parents, storage=self.tx_storage)
        with self.assertRaises(InvalidOutputValue):
            tx.resolve()

        # 'Manually resolving', to validate verify method
        tx.hash = bytes.fromhex('012cba011be3c29f1c406f9015e42698b97169dbc6652d1f5e4d5c5e83138858')
        with self.assertRaises(InvalidOutputValue):
            tx.verify()

        # Invalid output value
        invalid_output = bytes.fromhex('ffffffff')
        with self.assertRaises(InvalidOutputValue):
            bytes_to_output_value(invalid_output)

        # Can't instantiate an output with negative value
        with self.assertRaises(AssertionError):
            TxOutput(-1, script)
示例#9
0
 def _render_POST_thread(self, tx: Transaction, request: Request) -> Transaction:
     """ Method called in a thread to solve tx pow without stratum
     """
     # TODO Tx should be resolved in the frontend
     def _should_stop():
         return request.should_stop_mining_thread
     tx.start_mining(sleep_seconds=self.sleep_seconds, should_stop=_should_stop)
     if request.should_stop_mining_thread:
         raise CancelledError()
     tx.update_hash()
     tx.verify()
     return tx
示例#10
0
    def test_sigops_output_single_above_limit(self) -> None:
        genesis_block = self.genesis_blocks[0]
        value = genesis_block.outputs[0].value - 1
        _input = TxInput(genesis_block.hash, 0, b'')

        hscript = create_script_with_sigops(settings.MAX_TX_SIGOPS_OUTPUT + 1)
        output1 = TxOutput(value, hscript)
        tx = Transaction(inputs=[_input],
                         outputs=[output1],
                         storage=self.tx_storage)
        tx.update_hash()
        # This calls verify to ensure that verify_sigops_output is being called on verify
        with self.assertRaises(TooManySigOps):
            tx.verify()
示例#11
0
    def test_sigops_output_multi_above_limit(self) -> None:
        genesis_block = self.genesis_blocks[0]
        value = genesis_block.outputs[0].value - 1
        _input = TxInput(genesis_block.hash, 0, b'')
        num_outputs = 5

        hscript = create_script_with_sigops(
            (settings.MAX_TX_SIGOPS_OUTPUT + num_outputs) // num_outputs)
        output2 = TxOutput(value, hscript)
        tx = Transaction(inputs=[_input],
                         outputs=[output2] * num_outputs,
                         storage=self.tx_storage)
        tx.update_hash()
        with self.assertRaises(TooManySigOps):
            tx.verify()
示例#12
0
    def test_sigops_input_single_above_limit(self) -> None:
        genesis_block = self.genesis_blocks[0]
        value = genesis_block.outputs[0].value - 1
        address = get_address_from_public_key(self.genesis_public_key)
        script = P2PKH.create_output_script(address)
        _output = TxOutput(value, script)

        hscript = create_script_with_sigops(settings.MAX_TX_SIGOPS_INPUT + 1)
        input1 = TxInput(genesis_block.hash, 0, hscript)
        tx = Transaction(inputs=[input1],
                         outputs=[_output],
                         storage=self.tx_storage)
        tx.update_hash()
        with self.assertRaises(TooManySigOps):
            tx.verify()
    def test_tokens_balance(self):
        # create tokens and check balances

        # initial tokens
        address_b58 = self.manager.wallet.get_unused_address()
        address = decode_address(address_b58)
        tx = create_tokens(self.manager, address_b58)
        token_id = tx.tokens[0]
        amount = tx.outputs[0].value

        # initial token balance
        self.assertEqual(self.manager.wallet.balance[token_id],
                         WalletBalance(0, amount))
        # initial hathor balance
        # we don't consider HTR balance 0 because we transfer genesis tokens to this
        # wallet during token creation
        hathor_balance = self.manager.wallet.balance[settings.HATHOR_TOKEN_UID]

        # transfer token to another wallet and check balance again
        parents = self.manager.get_new_tx_parents()
        _input1 = TxInput(tx.hash, 0, b'')
        script = P2PKH.create_output_script(address)
        token_output1 = TxOutput(30, b'', 0b00000001)
        token_output2 = TxOutput(amount - 30, script, 0b00000001)
        tx2 = Transaction(weight=1,
                          inputs=[_input1],
                          outputs=[token_output1, token_output2],
                          parents=parents,
                          tokens=[token_id],
                          storage=self.manager.tx_storage,
                          timestamp=int(self.manager.reactor.seconds()))
        data_to_sign = tx2.get_sighash_all(clear_input_data=True)
        public_bytes, signature = self.manager.wallet.get_input_aux_data(
            data_to_sign, self.manager.wallet.get_private_key(address_b58))
        tx2.inputs[0].data = P2PKH.create_input_data(public_bytes, signature)
        tx2.resolve()
        tx2.verify()
        self.manager.propagate_tx(tx2)
        self.run_to_completion()
        # verify balance
        self.assertEqual(self.manager.wallet.balance[token_id],
                         WalletBalance(0, amount - 30))
        # hathor balance remains the same
        self.assertEqual(
            self.manager.wallet.balance[settings.HATHOR_TOKEN_UID],
            hathor_balance)
示例#14
0
    def test_tx_token_outputs(self):
        genesis_block = self.genesis_blocks[0]

        _input = TxInput(genesis_block.hash, 0, b'')

        value = genesis_block.outputs[0].value
        script = P2PKH.create_output_script(self.address)
        output = TxOutput(value, script, 1)

        parents = [tx.hash for tx in self.genesis_txs]
        tx = Transaction(weight=1,
                         inputs=[_input],
                         outputs=[output],
                         parents=parents,
                         storage=self.manager.tx_storage)

        # no token uids in list
        data_to_sign = tx.get_sighash_all()
        public_bytes, signature = self.manager.wallet.get_input_aux_data(
            data_to_sign, self.genesis_private_key)
        tx.inputs[0].data = P2PKH.create_input_data(public_bytes, signature)
        tx.resolve()
        with self.assertRaises(InvalidToken):
            tx.verify()

        # with 1 token uid in list
        tx.tokens = [
            bytes.fromhex(
                '0023be91834c973d6a6ddd1a0ae411807b7c8ef2a015afb5177ee64b666ce602'
            )
        ]
        output.token_data = 2
        data_to_sign = tx.get_sighash_all()
        public_bytes, signature = self.manager.wallet.get_input_aux_data(
            data_to_sign, self.genesis_private_key)
        tx.inputs[0].data = P2PKH.create_input_data(public_bytes, signature)
        tx.resolve()
        with self.assertRaises(InvalidToken):
            tx.verify()

        # try hathor authority UTXO
        output = TxOutput(value, script, 0b10000000)
        tx.outputs = [output]
        data_to_sign = tx.get_sighash_all()
        public_bytes, signature = self.manager.wallet.get_input_aux_data(
            data_to_sign, self.genesis_private_key)
        tx.inputs[0].data = P2PKH.create_input_data(public_bytes, signature)
        tx.resolve()
        with self.assertRaises(InvalidToken):
            tx.verify()
示例#15
0
    def test_tx_inputs_out_of_range(self):
        # we'll try to spend output 3 from genesis transaction, which does not exist
        parents = [tx.hash for tx in self.genesis_txs]
        genesis_block = self.genesis_blocks[0]

        value = genesis_block.outputs[0].value
        address = get_address_from_public_key(self.genesis_public_key)
        script = P2PKH.create_output_script(address)
        output = TxOutput(value, script)

        _input = TxInput(genesis_block.hash,
                         len(genesis_block.outputs) + 1, b'')
        tx = Transaction(weight=1,
                         inputs=[_input],
                         outputs=[output],
                         parents=parents,
                         storage=self.tx_storage)

        data_to_sign = tx.get_sighash_all()
        public_bytes, signature = self.wallet.get_input_aux_data(
            data_to_sign, self.genesis_private_key)
        data = P2PKH.create_input_data(public_bytes, signature)
        tx.inputs[0].data = data

        # test with an inexistent index
        tx.resolve()
        with self.assertRaises(InexistentInput):
            tx.verify()

        # now with index equals of len of outputs
        _input = [
            TxInput(genesis_block.hash, len(genesis_block.outputs), data)
        ]
        tx.inputs = _input
        # test with an inexistent index
        tx.resolve()
        with self.assertRaises(InexistentInput):
            tx.verify()

        # now with inexistent tx hash
        random_bytes = bytes.fromhex(
            '0000184e64683b966b4268f387c269915cc61f6af5329823a93e3696cb0fe902')
        _input = [TxInput(random_bytes, 3, data)]
        tx.inputs = _input
        tx.resolve()
        with self.assertRaises(InexistentInput):
            tx.verify()
示例#16
0
    def test_tx_number_parents(self):
        genesis_block = self.genesis_blocks[0]

        _input = TxInput(genesis_block.hash, 0, b'')

        value = genesis_block.outputs[0].value
        address = get_address_from_public_key(self.genesis_public_key)
        script = P2PKH.create_output_script(address)
        output = TxOutput(value, script)

        parents = [self.genesis_txs[0].hash]
        tx = Transaction(weight=1,
                         inputs=[_input],
                         outputs=[output],
                         parents=parents,
                         storage=self.tx_storage,
                         timestamp=self.last_block.timestamp + 1)

        data_to_sign = tx.get_sighash_all()
        public_bytes, signature = self.wallet.get_input_aux_data(
            data_to_sign, self.genesis_private_key)
        tx.inputs[0].data = P2PKH.create_input_data(public_bytes, signature)

        # in first test, only with 1 parent
        tx.resolve()
        with self.assertRaises(IncorrectParents):
            tx.verify()

        # test with 3 parents
        parents = [tx.hash for tx in self.genesis]
        tx.parents = parents
        tx.resolve()
        with self.assertRaises(IncorrectParents):
            tx.verify()

        # 2 parents, 1 tx and 1 block
        parents = [self.genesis_txs[0].hash, self.genesis_blocks[0].hash]
        tx.parents = parents
        tx.resolve()
        with self.assertRaises(IncorrectParents):
            tx.verify()
示例#17
0
    def test_token_mint(self):
        wallet = self.manager.wallet
        tx = create_tokens(self.manager, self.address_b58, mint_amount=500)
        token_uid = tx.tokens[0]
        parents = self.manager.get_new_tx_parents()
        script = P2PKH.create_output_script(self.address)

        # mint tokens and transfer mint authority
        mint_amount = 10000000
        deposit_amount = get_deposit_amount(mint_amount)
        _input1 = TxInput(tx.hash, 1, b'')
        _input2 = TxInput(tx.hash, 3, b'')
        token_output1 = TxOutput(mint_amount, script, 1)
        token_output2 = TxOutput(TxOutput.TOKEN_MINT_MASK, script, 0b10000001)
        deposit_output = TxOutput(tx.outputs[3].value - deposit_amount, script,
                                  0)
        tx2 = Transaction(
            weight=1,
            inputs=[_input1, _input2],
            outputs=[token_output1, token_output2, deposit_output],
            parents=parents,
            tokens=[token_uid],
            storage=self.manager.tx_storage,
            timestamp=int(self.clock.seconds()))
        data_to_sign = tx2.get_sighash_all()
        public_bytes, signature = wallet.get_input_aux_data(
            data_to_sign, wallet.get_private_key(self.address_b58))
        data = P2PKH.create_input_data(public_bytes, signature)
        tx2.inputs[0].data = data
        tx2.inputs[1].data = data
        tx2.resolve()
        tx2.verify()
        self.manager.propagate_tx(tx2)
        self.run_to_completion()

        # check tokens index
        tokens_index = self.manager.tx_storage.tokens_index.tokens[token_uid]
        self.assertIn((tx2.hash, 1), tokens_index.mint)
        self.assertIn((tx.hash, 2), tokens_index.melt)
        # there should only be one element on the indexes for the token
        self.assertEqual(1, len(tokens_index.mint))
        self.assertEqual(1, len(tokens_index.melt))
        # check total amount of tokens
        self.assertEqual(500 + mint_amount, tokens_index.total)

        # try to mint 1 token unit without deposit
        mint_amount = 1
        _input1 = TxInput(tx.hash, 1, b'')
        token_output1 = TxOutput(mint_amount, script, 1)
        token_output2 = TxOutput(TxOutput.TOKEN_MINT_MASK, script, 0b10000001)
        tx3 = Transaction(weight=1,
                          inputs=[_input1],
                          outputs=[token_output1, token_output2],
                          parents=parents,
                          tokens=[token_uid],
                          storage=self.manager.tx_storage,
                          timestamp=int(self.clock.seconds()))
        data_to_sign = tx3.get_sighash_all()
        public_bytes, signature = wallet.get_input_aux_data(
            data_to_sign, wallet.get_private_key(self.address_b58))
        data = P2PKH.create_input_data(public_bytes, signature)
        tx3.inputs[0].data = data
        tx3.resolve()
        with self.assertRaises(InputOutputMismatch):
            tx3.verify()

        # try to mint and deposit less tokens than necessary
        mint_amount = 10000000
        deposit_amount = get_deposit_amount(mint_amount) - 1
        _input1 = TxInput(tx.hash, 1, b'')
        _input2 = TxInput(tx.hash, 3, b'')
        token_output1 = TxOutput(mint_amount, script, 1)
        token_output2 = TxOutput(TxOutput.TOKEN_MINT_MASK, script, 0b10000001)
        deposit_output = TxOutput(tx.outputs[3].value - deposit_amount, script,
                                  0)
        tx4 = Transaction(
            weight=1,
            inputs=[_input1, _input2],
            outputs=[token_output1, token_output2, deposit_output],
            parents=parents,
            tokens=[token_uid],
            storage=self.manager.tx_storage,
            timestamp=int(self.clock.seconds()))
        data_to_sign = tx4.get_sighash_all()
        public_bytes, signature = wallet.get_input_aux_data(
            data_to_sign, wallet.get_private_key(self.address_b58))
        data = P2PKH.create_input_data(public_bytes, signature)
        tx4.inputs[0].data = data
        tx4.inputs[1].data = data
        tx4.resolve()
        with self.assertRaises(InputOutputMismatch):
            tx4.verify()

        # try to mint using melt authority UTXO
        _input1 = TxInput(tx.hash, 2, b'')
        token_output = TxOutput(10000000, script, 1)
        tx5 = Transaction(weight=1,
                          inputs=[_input1],
                          outputs=[token_output],
                          parents=parents,
                          tokens=[token_uid],
                          storage=self.manager.tx_storage,
                          timestamp=int(self.clock.seconds()))
        data_to_sign = tx5.get_sighash_all()
        public_bytes, signature = wallet.get_input_aux_data(
            data_to_sign, wallet.get_private_key(self.address_b58))
        tx5.inputs[0].data = P2PKH.create_input_data(public_bytes, signature)
        tx5.resolve()
        with self.assertRaises(InputOutputMismatch):
            tx5.verify()
示例#18
0
 def _stratum_thread_verify(self, tx: Transaction) -> Transaction:
     """ Method to verify the transaction that runs in a separated thread
     """
     tx.verify()
     return tx
示例#19
0
    def test_token_melt(self):
        wallet = self.manager.wallet
        tx = create_tokens(self.manager, self.address_b58)
        token_uid = tx.tokens[0]
        parents = self.manager.get_new_tx_parents()
        script = P2PKH.create_output_script(self.address)

        # melt tokens and transfer melt authority
        melt_amount = 100
        new_amount = tx.outputs[0].value - melt_amount
        withdraw_amount = get_withdraw_amount(melt_amount)
        _input1 = TxInput(tx.hash, 0, b'')
        _input2 = TxInput(tx.hash, 2, b'')
        token_output1 = TxOutput(new_amount, script, 1)
        token_output2 = TxOutput(TxOutput.TOKEN_MELT_MASK, script, 0b10000001)
        withdraw_output = TxOutput(withdraw_amount, script, 0)
        tx2 = Transaction(
            weight=1,
            inputs=[_input1, _input2],
            outputs=[token_output1, token_output2, withdraw_output],
            parents=parents,
            tokens=[token_uid],
            storage=self.manager.tx_storage,
            timestamp=int(self.clock.seconds()))
        data_to_sign = tx2.get_sighash_all()
        public_bytes, signature = wallet.get_input_aux_data(
            data_to_sign, wallet.get_private_key(self.address_b58))
        data = P2PKH.create_input_data(public_bytes, signature)
        tx2.inputs[0].data = data
        tx2.inputs[1].data = data
        tx2.resolve()
        tx2.verify()
        self.manager.propagate_tx(tx2)
        self.run_to_completion()

        # check tokens index
        tokens_index = self.manager.tx_storage.indexes.tokens.get_token_info(
            token_uid)
        mint = list(tokens_index.iter_mint_utxos())
        melt = list(tokens_index.iter_melt_utxos())
        self.assertIn(TokenUtxoInfo(tx.hash, 1), mint)
        self.assertIn(TokenUtxoInfo(tx2.hash, 1), melt)
        # there should only be one element on the indexes for the token
        self.assertEqual(1, len(mint))
        self.assertEqual(1, len(melt))
        # check total amount of tokens
        self.assertEqual(new_amount, tokens_index.get_total())

        # melt tokens and withdraw more than what's allowed
        melt_amount = 100
        withdraw_amount = get_withdraw_amount(melt_amount)
        _input1 = TxInput(tx.hash, 0, b'')
        _input2 = TxInput(tx.hash, 2, b'')
        token_output1 = TxOutput(tx.outputs[0].value - melt_amount, script, 1)
        token_output2 = TxOutput(TxOutput.TOKEN_MELT_MASK, script, 0b10000001)
        withdraw_output = TxOutput(withdraw_amount + 1, script, 0)
        tx3 = Transaction(
            weight=1,
            inputs=[_input1, _input2],
            outputs=[token_output1, token_output2, withdraw_output],
            parents=parents,
            tokens=[token_uid],
            storage=self.manager.tx_storage,
            timestamp=int(self.clock.seconds()))
        data_to_sign = tx3.get_sighash_all()
        public_bytes, signature = wallet.get_input_aux_data(
            data_to_sign, wallet.get_private_key(self.address_b58))
        data = P2PKH.create_input_data(public_bytes, signature)
        tx3.inputs[0].data = data
        tx3.inputs[1].data = data
        tx3.resolve()
        with self.assertRaises(InputOutputMismatch):
            tx3.verify()

        # try to melt using mint authority UTXO
        _input1 = TxInput(tx.hash, 0, b'')
        _input2 = TxInput(tx.hash, 1, b'')
        token_output = TxOutput(tx.outputs[0].value - 1, script, 1)
        tx4 = Transaction(weight=1,
                          inputs=[_input1, _input2],
                          outputs=[token_output],
                          parents=parents,
                          tokens=[token_uid],
                          storage=self.manager.tx_storage,
                          timestamp=int(self.clock.seconds()))
        data_to_sign = tx4.get_sighash_all()
        public_bytes, signature = wallet.get_input_aux_data(
            data_to_sign, wallet.get_private_key(self.address_b58))
        data = P2PKH.create_input_data(public_bytes, signature)
        tx4.inputs[0].data = data
        tx4.inputs[1].data = data
        tx4.resolve()
        with self.assertRaises(InputOutputMismatch):
            tx4.verify()
示例#20
0
    def test_token_index_with_conflict(self, mint_amount=0):
        # create a new token and have a mint operation done. The tx that mints the
        # tokens has the following outputs:
        # 0. minted tokens
        # 1. mint authority;
        # 2. melt authority
        # 3. HTR deposit change
        tx = create_tokens(self.manager, self.address_b58, mint_amount=100)
        token_uid = tx.tokens[0]
        tokens_index = self.manager.tx_storage.indexes.tokens.get_token_info(
            tx.tokens[0])
        mint = list(tokens_index.iter_mint_utxos())
        melt = list(tokens_index.iter_melt_utxos())
        self.assertIn(TokenUtxoInfo(tx.hash, 1), mint)
        self.assertIn(TokenUtxoInfo(tx.hash, 2), melt)
        # there should only be one element on the indexes for the token
        self.assertEqual(1, len(mint))
        self.assertEqual(1, len(melt))
        # check total amount of tokens
        self.assertEqual(100, tokens_index.get_total())

        # new tx minting tokens
        mint_amount = 300
        deposit_amount = get_deposit_amount(mint_amount)
        script = P2PKH.create_output_script(self.address)
        # inputs
        mint_input = TxInput(tx.hash, 1, b'')
        melt_input = TxInput(tx.hash, 2, b'')
        deposit_input = TxInput(tx.hash, 3, b'')
        # outputs
        mint_output = TxOutput(mint_amount, script, 1)
        authority_output1 = TxOutput(TxOutput.TOKEN_MINT_MASK, script,
                                     0b10000001)
        authority_output2 = TxOutput(TxOutput.TOKEN_MELT_MASK, script,
                                     0b10000001)
        deposit_output = TxOutput(tx.outputs[3].value - deposit_amount, script,
                                  0)
        tx2 = Transaction(weight=1,
                          inputs=[mint_input, melt_input, deposit_input],
                          outputs=[
                              authority_output1, authority_output2,
                              mint_output, deposit_output
                          ],
                          parents=self.manager.get_new_tx_parents(),
                          tokens=[token_uid],
                          storage=self.manager.tx_storage,
                          timestamp=int(self.clock.seconds()))
        # sign inputs
        wallet = self.manager.wallet
        data_to_sign = tx2.get_sighash_all()
        public_bytes, signature = wallet.get_input_aux_data(
            data_to_sign, wallet.get_private_key(self.address_b58))
        data = P2PKH.create_input_data(public_bytes, signature)
        tx2.inputs[0].data = data
        tx2.inputs[1].data = data
        tx2.inputs[2].data = data
        tx2.resolve()
        tx2.verify()
        self.manager.propagate_tx(tx2)
        self.run_to_completion()

        # there should only be one element on the indexes for the token
        tokens_index = self.manager.tx_storage.indexes.tokens.get_token_info(
            tx.tokens[0])
        mint = list(tokens_index.iter_mint_utxos())
        melt = list(tokens_index.iter_melt_utxos())
        self.assertEqual(1, len(mint))
        self.assertEqual(1, len(melt))
        self.assertIn(TokenUtxoInfo(tx2.hash, 0), mint)
        self.assertIn(TokenUtxoInfo(tx2.hash, 1), melt)
        # check total amount of tokens has been updated
        self.assertEqual(400, tokens_index.get_total())

        # create conflicting tx by changing parents
        tx3 = Transaction.create_from_struct(tx2.get_struct())
        tx3.parents = [tx.parents[1], tx.parents[0]]
        tx3.weight = 3
        tx3.resolve()
        self.assertNotEqual(tx3.hash, tx2.hash)
        self.assertTrue(tx3.weight > tx2.weight)
        self.manager.propagate_tx(tx3)
        self.run_to_completion()

        # new tx should be on tokens index. Old tx should not be present
        tokens_index = self.manager.tx_storage.indexes.tokens.get_token_info(
            tx.tokens[0])
        mint = list(tokens_index.iter_mint_utxos())
        melt = list(tokens_index.iter_melt_utxos())
        self.assertIn(TokenUtxoInfo(tx3.hash, 0), mint)
        self.assertIn(TokenUtxoInfo(tx3.hash, 1), melt)
        # there should only be one element on the indexes for the token
        self.assertEqual(1, len(mint))
        self.assertEqual(1, len(melt))
        # should have same amount of tokens
        self.assertEqual(400, tokens_index.get_total())