Exemple #1
0
    def deserialize_token_info(cls, buf: bytes, *, verbose: VerboseCallback = None) -> Tuple[str, str, bytes]:
        """ Gets the token name and symbol from serialized format
        """
        (token_info_version,), buf = unpack('!B', buf)
        if verbose:
            verbose('token_info_version', token_info_version)
        if token_info_version != TOKEN_INFO_VERSION:
            raise ValueError('unknown token info version: {}'.format(token_info_version))

        (name_len,), buf = unpack('!B', buf)
        if verbose:
            verbose('token_name_len', name_len)
        name, buf = unpack_len(name_len, buf)
        if verbose:
            verbose('token_name', name)
        (symbol_len,), buf = unpack('!B', buf)
        if verbose:
            verbose('token_symbol_len', symbol_len)
        symbol, buf = unpack_len(symbol_len, buf)
        if verbose:
            verbose('token_symbol', symbol)

        # Token name and symbol can be only utf-8 valid strings for now
        decoded_name = decode_string_utf8(name, 'Token name')
        decoded_symbol = decode_string_utf8(symbol, 'Token symbol')

        return decoded_name, decoded_symbol, buf
Exemple #2
0
    def get_funds_fields_from_struct(self, buf: bytes) -> bytes:
        """ Gets all funds fields for a transaction from a buffer.

        :param buf: Bytes of a serialized transaction
        :type buf: bytes

        :return: A buffer containing the remaining struct bytes
        :rtype: bytes

        :raises ValueError: when the sequence of bytes is incorect
        """
        (self.version, tokens_len, inputs_len,
         outputs_len), buf = unpack(_FUNDS_FORMAT_STRING, buf)

        for _ in range(tokens_len):
            token_uid, buf = unpack_len(TX_HASH_SIZE, buf)
            self.tokens.append(token_uid)

        for _ in range(inputs_len):
            txin, buf = TxInput.create_from_bytes(buf)
            self.inputs.append(txin)

        for _ in range(outputs_len):
            txout, buf = TxOutput.create_from_bytes(buf)
            self.outputs.append(txout)

        return buf
Exemple #3
0
    def get_funds_fields_from_struct(self, buf: bytes, *, verbose: VerboseCallback = None) -> bytes:
        """ Gets all funds fields for a transaction from a buffer.

        :param buf: Bytes of a serialized transaction
        :type buf: bytes

        :return: A buffer containing the remaining struct bytes
        :rtype: bytes

        :raises ValueError: when the sequence of bytes is incorect
        """
        (self.version, inputs_len, outputs_len), buf = unpack(_FUNDS_FORMAT_STRING, buf)
        if verbose:
            verbose('version', self.version)
            verbose('inputs_len', inputs_len)
            verbose('outputs_len', outputs_len)

        for _ in range(inputs_len):
            txin, buf = TxInput.create_from_bytes(buf, verbose=verbose)
            self.inputs.append(txin)

        for _ in range(outputs_len):
            txout, buf = TxOutput.create_from_bytes(buf, verbose=verbose)
            self.outputs.append(txout)

        # token name and symbol
        self.token_name, self.token_symbol, buf = TokenCreationTransaction.deserialize_token_info(buf, verbose=verbose)

        return buf
Exemple #4
0
def bytes_to_output_value(buf: bytes) -> Tuple[int, bytes]:
    (value_high_byte, ), _ = unpack('!b', buf)
    if value_high_byte < 0:
        output_struct = '!q'
        value_sign = -1
    else:
        output_struct = '!i'
        value_sign = 1
    try:
        (signed_value, ), buf = unpack(output_struct, buf)
    except StructError as e:
        raise InvalidOutputValue('Invalid byte struct for output') from e
    value = signed_value * value_sign
    assert value >= 0
    if value < _MAX_OUTPUT_VALUE_32 and value_high_byte < 0:
        raise ValueError('Value fits in 4 bytes but is using 8 bytes')
    return value, buf
Exemple #5
0
 def create_from_bytes(cls, buf: bytes) -> Tuple['TxInput', bytes]:
     """ Creates a TxInput from a serialized input. Returns the input
     and remaining bytes
     """
     input_tx_id, buf = unpack_len(TX_HASH_SIZE, buf)
     (input_index, data_len), buf = unpack('!BH', buf)
     input_data, buf = unpack_len(data_len, buf)
     txin = cls(input_tx_id, input_index, input_data)
     return txin, buf
Exemple #6
0
 def create_from_bytes(cls, buf: bytes) -> Tuple['TxOutput', bytes]:
     """ Creates a TxOutput from a serialized output. Returns the output
     and remaining bytes
     """
     value, buf = bytes_to_output_value(buf)
     (token_data, script_len), buf = unpack('!BH', buf)
     script, buf = unpack_len(script_len, buf)
     txout = cls(value, script, token_data)
     return txout, buf
Exemple #7
0
    def get_graph_fields_from_struct(self, buf: bytes) -> bytes:
        """ Gets graph fields for a block from a buffer.

        :param buf: Bytes of a serialized transaction
        :type buf: bytes

        :return: A buffer containing the remaining struct bytes
        :rtype: bytes

        :raises ValueError: when the sequence of bytes is incorect
        """
        buf = super().get_graph_fields_from_struct(buf)
        (data_bytes, ), buf = unpack('!B', buf)
        self.data, buf = unpack_len(data_bytes, buf)
        return buf
Exemple #8
0
    def create_from_struct(
            cls,
            struct_bytes: bytes,
            storage: Optional['TransactionStorage'] = None) -> 'Transaction':
        tx = cls()
        buf = tx.get_fields_from_struct(struct_bytes)

        if len(buf) != cls.SERIALIZATION_NONCE_SIZE:
            raise ValueError('Invalid sequence of bytes')

        [
            tx.nonce,
        ], buf = unpack('!I', buf)

        tx.update_hash()
        tx.storage = storage

        return tx
Exemple #9
0
    def get_funds_fields_from_struct(self, buf: bytes) -> bytes:
        """ Gets all funds fields for a block from a buffer.

        :param buf: Bytes of a serialized block
        :type buf: bytes

        :return: A buffer containing the remaining struct bytes
        :rtype: bytes

        :raises ValueError: when the sequence of bytes is incorect
        """
        (self.version, outputs_len), buf = unpack(_FUNDS_FORMAT_STRING, buf)

        for _ in range(outputs_len):
            txout, buf = TxOutput.create_from_bytes(buf)
            self.outputs.append(txout)

        return buf
Exemple #10
0
    def get_graph_fields_from_struct(self, buf: bytes) -> bytes:
        """ Gets all common graph fields for a Transaction and a Block from a buffer.

        :param buf: Bytes of a serialized transaction
        :type buf: bytes

        :return: A buffer containing the remaining struct bytes
        :rtype: bytes

        :raises ValueError: when the sequence of bytes is incorect
        """
        (self.weight, self.timestamp,
         parents_len), buf = unpack(_GRAPH_FORMAT_STRING, buf)

        for _ in range(parents_len):
            parent, buf = unpack_len(TX_HASH_SIZE, buf)  # 256bits
            self.parents.append(parent)

        return buf
Exemple #11
0
    def get_graph_fields_from_struct(self,
                                     buf: bytes,
                                     *,
                                     verbose: VerboseCallback = None) -> bytes:
        """ Gets graph fields for a block from a buffer.

        :param buf: Bytes of a serialized transaction
        :type buf: bytes

        :return: A buffer containing the remaining struct bytes
        :rtype: bytes

        :raises ValueError: when the sequence of bytes is incorect
        """
        buf = super().get_graph_fields_from_struct(buf, verbose=verbose)
        (data_bytes, ), buf = unpack('!B', buf)
        if verbose:
            verbose('data_len', data_bytes)
        self.data, buf = unpack_len(data_bytes, buf)
        if verbose:
            verbose('data', self.data.hex())
        return buf