Exemple #1
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)
Exemple #2
0
    def __bytes__(self) -> bytes:
        """Returns a byte representation of the input

        :rtype: bytes
        """
        ret = b''
        ret += self.tx_id
        ret += int_to_bytes(self.index, 1)
        ret += int_to_bytes(len(self.data), 2)  # data length
        ret += self.data
        return ret
Exemple #3
0
    def __bytes__(self) -> bytes:
        """Returns a byte representation of the output

        :rtype: bytes
        """
        ret = b''
        ret += output_value_to_bytes(self.value)
        ret += int_to_bytes(self.token_data, 1)
        ret += int_to_bytes(len(self.script), 2)  # script length
        ret += self.script
        return ret
    def get_sighash_bytes(self) -> bytes:
        """Return a serialization of the input for the sighash. It always clears the input data.

        :return: Serialization of the input
        :rtype: bytes
        """
        ret = bytearray()
        ret += self.tx_id
        ret += int_to_bytes(self.index, 1)
        ret += int_to_bytes(0, 2)
        return bytes(ret)
Exemple #5
0
    def serialize_token_info(self) -> bytes:
        """ Returns the serialization for token name and symbol
        """
        encoded_name = self.token_name.encode('utf-8')
        encoded_symbol = self.token_symbol.encode('utf-8')

        ret = b''
        ret += int_to_bytes(TOKEN_INFO_VERSION, 1)
        ret += int_to_bytes(len(encoded_name), 1)
        ret += encoded_name
        ret += int_to_bytes(len(encoded_symbol), 1)
        ret += encoded_symbol
        return ret
Exemple #6
0
    def get_sighash_bytes(self, clear_data: bool) -> bytes:
        """Return a serialization of the input for the sighash

        :return: Serialization of the input
        :rtype: bytes
        """
        if not clear_data:
            return bytes(self)
        else:
            ret = b''
            ret += self.tx_id
            ret += int_to_bytes(self.index, 1)
            ret += int_to_bytes(0, 2)
            return ret
Exemple #7
0
    def get_graph_struct(self) -> bytes:
        """Return the graph data serialization of the block, without including the nonce field

        :return: graph data serialization of the transaction
        :rtype: bytes
        """
        struct_bytes_without_data = super().get_graph_struct()
        data_bytes = int_to_bytes(len(self.data), 1)
        return struct_bytes_without_data + data_bytes + self.data
Exemple #8
0
    def get_struct_nonce(self) -> bytes:
        """Return a partial serialization of the transaction's proof-of-work, which is usually the nonce field

        :return: Partial serialization of the transaction's proof-of-work
        :rtype: bytes
        """
        assert self.SERIALIZATION_NONCE_SIZE is not None
        struct_bytes = int_to_bytes(self.nonce, self.SERIALIZATION_NONCE_SIZE)
        return struct_bytes
    def test_token_info_not_utf8(self):
        token_name = 'TestCoin'
        token_symbol = 'TST'

        # Token version 1; Name length; Name; Symbol length; Symbol
        bytes1 = (bytes([0x01]) + int_to_bytes(len(token_name), 1) +
                  token_name.encode('utf-8') +
                  int_to_bytes(len(token_symbol), 1) +
                  token_symbol.encode('utf-8'))

        name, symbol, _ = TokenCreationTransaction.deserialize_token_info(
            bytes1)

        self.assertEqual(name, token_name)
        self.assertEqual(symbol, token_symbol)

        encoded_name = token_name.encode('utf-16')
        bytes2 = (bytes([0x01]) + int_to_bytes(len(encoded_name), 1) +
                  encoded_name + int_to_bytes(len(token_symbol), 1) +
                  token_symbol.encode('utf-8'))

        with self.assertRaises(StructError):
            TokenCreationTransaction.deserialize_token_info(bytes2)

        encoded_symbol = token_symbol.encode('utf-16')
        bytes3 = (bytes([0x01]) + int_to_bytes(len(token_name), 1) +
                  token_name.encode('utf-8') +
                  int_to_bytes(len(encoded_symbol), 1) + encoded_symbol)

        with self.assertRaises(StructError):
            TokenCreationTransaction.deserialize_token_info(bytes3)
Exemple #10
0
 def to_proto(self,
              include_metadata: bool = True) -> protos.BaseTransaction:
     tx_proto = protos.Block(version=self.version,
                             weight=self.weight,
                             timestamp=self.timestamp,
                             parents=self.parents,
                             outputs=map(TxOutput.to_proto, self.outputs),
                             hash=self.hash,
                             data=self.data)
     tx_proto.nonce = int_to_bytes(self.nonce, 16)
     if include_metadata:
         tx_proto.metadata.CopyFrom(self.get_metadata().to_proto())
     return protos.BaseTransaction(block=tx_proto)