Example #1
0
 def __getitem__(self, hash_and_pc):
     res = self.txos.get_by_hash(_hash(hash_and_pc))
     if not res:
         raise KeyError(hash_and_pc)
     utxo = IOput()
     utxo.deserialize(res)
     return utxo
Example #2
0
 def remove(self, n):
     self.commitments.remove(n)
     ser_removed_outputs = self.txos.remove(n)
     removed_outputs = []
     for _ser in ser_removed_outputs:
         utxo = IOput()
         utxo.deserialize(_ser)
         removed_outputs.append(utxo)
     return removed_outputs
Example #3
0
 def remove(self, n, wtx):
     self.commitments.remove(n, wtx=wtx)
     ser_removed_outputs = self.txos.remove(n, wtx=wtx)
     removed_outputs = []
     for _ser in ser_removed_outputs:
         utxo = IOput()
         utxo.deserialize_with_context(_ser)
         removed_outputs.append(utxo)
     return removed_outputs
Example #4
0
 def find(self, hash_and_pc):
     '''
     In contrast with __getitem__ find will try to find even spent
     outputs for other (syncing) nodes.
   '''
     res = self.txos.find_by_hash(_hash(hash_and_pc))
     if not res:
         raise KeyError(hash_and_pc)
     utxo = IOput()
     utxo.deserialize(res)
     return utxo
Example #5
0
 def generate(self, change_address=None):
     if self.coinbase:
         raise Exception(
             "generate() can be used only for common transaction, to create block transaction as miner use compose_block_transaction"
         )
     if not len(self.inputs):
         raise Exception("Tx should have at least one input")
     if not len(self._destinations):
         raise Exception("Tx should have at least one destination")
     for ioput in self.inputs:
         if not self.key_manager:
             raise Exception(
                 "Trying to generate tx which spends unknown input (KeyManager is None)"
             )
         if not ioput.detect_value(self.key_manager):
             raise Exception(
                 "Trying to generate tx which spends unknown input")
     in_value = sum([ioput.value for ioput in self.inputs])
     out_value = sum([destination[1] for destination in self._destinations])
     relay_fee = self.calc_relay_fee()
     # +1 for destination is for change address
     self.fee = relay_fee + self.calc_new_outputs_fee(
         len(self.inputs),
         len(self._destinations) + 1)
     remainder = in_value - out_value - self.fee
     if remainder < 0:
         raise Exception("Not enough money in inputs to cover outputs")
     # TODO We need logic here to cover too low remainders (less than new output fee)
     change_address = change_address if change_address else self.key_manager.new_address(
     )  # TODO Check: for first glance, we cannot get here if key_manager is None.
     self._destinations.append((change_address, remainder))
     privkey_sum = 0
     out_blinding_key_sum = None
     for out_index in range(len(self._destinations) - 1):
         address, value = self._destinations[out_index]
         output = IOput()
         output.fill(address, value, generator=default_generator_ser)
         self.outputs.append(output)
         out_blinding_key_sum = out_blinding_key_sum + output.blinding_key if out_blinding_key_sum else output.blinding_key
     # privkey for the last one output isn't arbitrary
     address, value = self._destinations[-1]
     in_blinding_key_sum = None
     for _input in self.inputs:
         in_blinding_key_sum = in_blinding_key_sum + _input.blinding_key if in_blinding_key_sum else _input.blinding_key
         in_blinding_key_sum += self.key_manager.priv_by_pub(
             _input.address.pubkey
         )  # we can't get here if key_manager is None
     output = IOput()
     output.fill(
         address,
         value,
         blinding_key=in_blinding_key_sum - out_blinding_key_sum,
         relay_fee=relay_fee,
         generator=default_generator_ser
     )  #TODO relay fee should be distributed uniformly, privacy leak
     self.outputs.append(output)
     [output.generate() for output in self.outputs]
     self.sort_ioputs()
     self.verify()
Example #6
0
 def rollback(self, pruned_inputs, num_of_added_outputs, prev_state):
     for r_i in pruned_inputs:
         if self.storage_space.utxo_index:
             #r_i[0][2] is serialized txo (0 is txo, 2 is serialized object)
             utxo = IOput()
             utxo.deserialize(r_i[0][2])
             self.storage_space.utxo_index.add_utxo(utxo)
         self.confirmed.unspend(r_i)
     outputs_for_mempool = self.confirmed.remove(num_of_added_outputs)
     for _o in outputs_for_mempool:
         self.mempool[_o.serialized_index] = _o
         self.storage_space.utxo_index.remove_utxo(_o)
     self.confirmed.set_state(prev_state)
Example #7
0
def process_new_txos(message):
    try:
        serialized_utxos = bytes(message["txos"])
        txos_hashes = bytes(message["txos_hashes"])
        num = message["num"]
        #txos_hashes = [txos_hashes[i*65:(i+1)*65)] for i in range(0,num)]
        txos_lengths = message["txos_lengths"]
        #TODO we should use txos_hashes and txos_lengths to proccess only unknown txos
        for i in range(num):
            utxo = IOput()
            serialized_utxos = utxo.deserialize_raw(serialized_utxos)
            storage_space.txos_storage.mempool[utxo.serialized_index] = utxo
        storage_space.blockchain.update(reason="downloaded new txos")
    except Exception as e:
        raise e  #XXX "DoS messages should be returned"
Example #8
0
 def give_block_template(self):
     if not self.key_manager:
         raise Exception("Key manager is not set")
     transaction_fees = self.give_tx().relay_fee if self.give_tx() else 0
     value = next_reward(
         self.storage_space.blockchain.current_tip,
         self.storage_space.headers_storage) + transaction_fees
     coinbase = IOput()
     coinbase.fill(
         self.key_manager.new_address(),
         value,
         relay_fee=0,
         coinbase=True,
         lock_height=self.storage_space.blockchain.current_height + 1 +
         coinbase_maturity)
     coinbase.generate()
     self.storage_space.txos_storage.mempool[
         coinbase.serialized_index] = coinbase
     tx = Transaction(txos_storage=self.storage_space.txos_storage,
                      key_manager=self.key_manager)
     tx.add_coinbase(coinbase)
     tx.compose_block_transaction()
     block = generate_block_template(tx, self.storage_space)
     self.add_block_template(block)
     return block
Example #9
0
def test_ioput_indexes():
    _input1 = IOput()
    _input1.fill(adr1, 100)
    _input1.generate(exp=2, concealed_bits=3)
    assert _input1.index_len == 32 + 33
    assert len(_input1.serialized_index) == 32 + 33
    assert len(_input1.commitment_index) == 32 + 33
    print("ioput_indexes len OK")
Example #10
0
 def get(self, hash_and_pc, rtx):
     res = self.txos.get_by_hash(sha256(hash_and_pc), rtx=rtx)
     if not res:
         raise KeyError(hash_and_pc)
     utxo = IOput()
     utxo.deserialize_with_context(res)
     utxo.set_verified_and_correct()  #Trust saved outputs
     return utxo
Example #11
0
def process_new_txos(message, wtx, core):
    try:
        serialized_utxos = bytes(message["txos"])
        txos_hashes = bytes(message["txos_hashes"])
        num = message["num"]
        txos_lengths = message["txos_lengths"]
        txos_hashes = [txos_hashes[i * 65:(i + 1) * 65] for i in range(0, num)]
        txos_lengths = [
            int.from_bytes(txos_lengths[i * 2:(i + 1) * 2], "big")
            for i in range(0, num)
        ]
        for i in range(num):
            txo_len, txo_hash = txos_lengths[i], txos_hashes[i]
            if txo_hash in core.storage_space.txos_storage.mempool:
                serialized_utxos = serialized_utxos[txo_len:]
                continue
            utxo = IOput()
            serialized_utxos = utxo.deserialize_raw(serialized_utxos)
            core.storage_space.txos_storage.mempool[
                utxo.serialized_index] = utxo
        core.storage_space.blockchain.update(wtx=wtx,
                                             reason="downloaded new txos")
    except Exception as e:
        raise DOSException()  #TODO add info
Example #12
0
 def find(self, hash_and_pc, rtx):
     '''
     In contrast with __getitem__ find will try to find even spent
     outputs for other (syncing) nodes.
   '''
     res = self.txos.find_by_hash(sha256(hash_and_pc), rtx=rtx)
     if not res:
         raise KeyError(hash_and_pc)
     utxo = IOput()
     utxo.deserialize_with_context(res)
     utxo.set_verified_and_correct()  #Trust saved outputs
     return utxo
Example #13
0
def ioput_encrypted_messsage():
    _input1 = IOput()
    _input1.fill(adr1, 100)
    _input1.generate(exp=2, concealed_bits=3)

    _input2 = IOput(binary_object=_input1.serialize())
    _input2.verify()
    _input2.detect_value({'priv_by_pub': {adr1.serialized_pubkey: keys[0]}})

    assert _input1.value == _input2.value
    assert _input1.blinding_key.serialize() == _input2.blinding_key.serialize()
    print("ioput_encrypted_message OK")
Example #14
0
    def deserialize(self, serialized_tx, rtx, skip_verification=False):
        self.serialized = None
        if len(serialized_tx) < 2:
            raise Exception(
                "Serialized transaction doesn't contain enough bytes for inputs array length"
            )
        inputs_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[2:]
        (inputs_len, ) = struct.unpack("> H", inputs_len_buffer)
        for _input_index in range(inputs_len):
            if len(serialized_tx) < 2:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for input %s length"
                    % _input_index)
            input_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[
                2:]
            (input_len, ) = struct.unpack("> H", input_len_buffer)
            if len(serialized_tx) < input_len:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for input %s"
                    % _input_index)
            input_index_buffer, serialized_tx = serialized_tx[:
                                                              input_len], serialized_tx[
                                                                  input_len:]

            if not skip_verification:
                if (not self.txos_storage.confirmed.has(input_index_buffer,
                                                        rtx=rtx)):
                    raise Exception("Unknown input index")
                self.inputs.append(
                    self.txos_storage.confirmed.get(input_index_buffer,
                                                    rtx=rtx))
            else:
                self.inputs.append(input_index_buffer)

        if len(serialized_tx) < 2:
            raise Exception(
                "Serialized transaction doesn't contain enough bytes for outputs array length"
            )
        outputs_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[
            2:]
        (outputs_len, ) = struct.unpack("> H", outputs_len_buffer)
        for _output_index in range(outputs_len):
            if len(serialized_tx) < 2:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for output %s length"
                    % _output_index)
            output_len_buffer, serialized_tx = serialized_tx[:
                                                             2], serialized_tx[
                                                                 2:]
            (output_len, ) = struct.unpack("> H", output_len_buffer)
            if len(serialized_tx) < output_len:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for output %s"
                    % _output_index)
            output_buffer, serialized_tx = serialized_tx[:
                                                         output_len], serialized_tx[
                                                             output_len:]
            self.outputs.append(IOput(binary_object=output_buffer))

        if len(serialized_tx) < 2:
            raise Exception(
                "Serialized transaction doesn't contain enough bytes for additional excesses array length"
            )
        aes_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[2:]
        (aes_len, ) = struct.unpack("> H", aes_len_buffer)
        for _ae in range(aes_len):
            if len(serialized_tx) < 2:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for additional excess %s length"
                    % _ae)
            ae_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[2:]
            (ae_len, ) = struct.unpack("> H", ae_len_buffer)
            if len(serialized_tx) < ae_len:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for additional excess %s"
                    % _ae)
            ae_buffer, serialized_tx = serialized_tx[:ae_len], serialized_tx[
                ae_len:]
            e = Excess.from_serialized(ae_buffer)
            self.additional_excesses.append(e)

        for _ue in range(inputs_len):
            if len(serialized_tx) < 2:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for updated excess %s length"
                    % _ue)
            ue_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[2:]
            (ue_len, ) = struct.unpack("> H", ue_len_buffer)
            if len(serialized_tx) < ue_len:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for updated excess %s"
                    % _ue)
            ue_buffer, serialized_tx = serialized_tx[:ue_len], serialized_tx[
                ue_len:]
            e = Excess.from_serialized(ue_buffer)
            #Depending on skif_verification self.inputs either contains inputs or serialized_indexes only
            if isinstance(self.inputs[_ue], bytes):
                self.updated_excesses[self.inputs[_ue]] = e
            elif isinstance(self.inputs[_ue], IOput):
                self.updated_excesses[self.inputs[_ue].serialized_index] = e
        if len(serialized_tx) < 32:
            raise Exception(
                "Serialized transaction doesn't contain enough bytes for mixer_offset"
            )
        self.mixer_offset, serialized_tx = int.from_bytes(
            serialized_tx[:32], "big"), serialized_tx[32:]
        if not skip_verification:
            self.verify(rtx=rtx)
Example #15
0
 def blindly_generate(self, change_address, input_data, relay_fee_per_kb=0):
     self.serialized = None
     if self.coinbase:
         raise Exception(
             "generate() can be used only for common transaction, to create block transaction as miner use compose_block_transaction"
         )
     if not len(input_data):
         raise Exception("Tx should have at least one input")
     if not len(self._destinations):
         raise Exception("Tx should have at least one destination")
     in_value = sum([ioput[1] for ioput in input_data])
     out_value = sum([destination[1] for destination in self._destinations])
     relay_fee = self.calc_relay_fee(relay_fee_per_kb=relay_fee_per_kb)
     # +1 for destination is for change address
     self.fee = relay_fee + self.calc_new_outputs_fee(
         len(input_data),
         len(self._destinations) + 1)
     remainder = in_value - out_value - self.fee
     if remainder < 0:
         raise Exception("Not enough money in inputs to cover outputs")
     # TODO We need logic here to cover too low remainders (less than new output fee)
     self._destinations.append((change_address, remainder, True))
     privkey_sum = 0
     out_blinding_key_sum = None
     need_proofs = []
     excesses_key_sum = None
     for out_index in range(len(self._destinations) - 1):
         address, value, need_proof = self._destinations[out_index]
         output = IOput()
         output.fill(address, value, generator=default_generator_ser)
         self.outputs.append(output)
         out_blinding_key_sum = (
             out_blinding_key_sum + output.blinding_key
         ) if out_blinding_key_sum else output.blinding_key
         if need_proof:
             need_proofs.append(
                 (output, PrivateKey()
                  ))  #excesses will be generated after output generation
     offset_pk = PrivateKey()
     self.mixer_offset = int.from_bytes(offset_pk.private_key, "big")
     # privkey for the last one output isn't arbitrary
     address, value, need_proof = self._destinations[-1]
     if need_proof:
         need_proofs.append(
             (output, PrivateKey()
              ))  #excesses will be generated after output generation
     in_blinding_key_sum = None
     burdens_to_be_covered = []
     for i, v, priv_key, blinding_key, ser_apc in input_data:
         in_blinding_key_sum = (
             in_blinding_key_sum +
             blinding_key) if in_blinding_key_sum else blinding_key
         in_blinding_key_sum += priv_key
         self.updated_excesses[i] = excess_from_private_key(
             priv_key, b"\x01\x00" + ser_apc)
         self.inputs.append(pseudoinput(
             i, ser_apc))  #For tx serialization and sorts
     if len(need_proofs):
         excesses_key_sum = need_proofs[0][1]
         for i in need_proofs[1:]:
             excesses_key_sum += i[1]
     output = IOput()
     last_blinding_key = in_blinding_key_sum - out_blinding_key_sum - offset_pk
     if excesses_key_sum:
         last_blinding_key += excesses_key_sum
     output.fill(
         address,
         value,
         blinding_key=last_blinding_key,
         relay_fee=relay_fee,
         generator=default_generator_ser
     )  #TODO relay fee should be distributed uniformly, privacy leak
     self.outputs.append(output)
     [output.generate() for output in self.outputs]
     for ae in need_proofs:
         script = generate_proof_script(ae[0])
         e = excess_from_private_key(ae[1], script)
         self.additional_excesses.append(e)
     self.sort_lists()
Example #16
0
    def deserialize_raw(self, serialized, storage_space=None):
        if len(serialized) < 1:
            raise Exception("Not enough bytes for tx skeleton version marker")
        serialized, ser_version = serialized[1:], serialized[0]
        rich_format = ser_version & 1
        self.version = ser_version >> 1
        if not self.version in [0]:
            raise Exception("Unknown tx_sceleton version")
        if len(serialized) < 2:
            raise Exception("Not enough bytes for tx skeleton inputs len")
        serialized, _len_i = serialized[2:], int.from_bytes(
            serialized[:2], "big")
        if len(serialized) < 2:
            raise Exception("Not enough bytes for tx skeleton outputs len")
        serialized, _len_o = serialized[2:], int.from_bytes(
            serialized[:2], "big")

        if len(serialized) < 2:
            raise Exception(
                "Not enough bytes for tx skeleton additional excesses len")
        serialized, _len_ae = serialized[2:], int.from_bytes(
            serialized[:2], "big")

        serialized_index_len = IOput().index_len
        for i in range(_len_i):
            if len(serialized) < serialized_index_len:
                raise Exception(
                    "Not enough bytes for tx skeleton' input index %d len" % i)
            _input_index, serialized = serialized[:
                                                  serialized_index_len], serialized[
                                                      serialized_index_len:]
            self.input_indexes.append(_input_index)
        for i in range(_len_o):
            if len(serialized) < serialized_index_len:
                raise Exception(
                    "Not enough bytes for tx skeleton' output index %d len" %
                    i)
            _output_index, serialized = serialized[:
                                                   serialized_index_len], serialized[
                                                       serialized_index_len:]
            self.output_indexes.append(_output_index)

        for i in range(_len_o):
            if len(serialized) < 4:
                raise Exception(
                    "Not enough bytes for tx skeleton' output relay fee %d len"
                    % i)
            ser_relay_fee, serialized = serialized[:4], serialized[4:]
            self.output_relay_fees.append(int.from_bytes(ser_relay_fee, "big"))

        for i in range(_len_ae):
            e = Excess()
            serialized = e.deserialize_raw(serialized)
            self.additional_excesses.append(e)
        for i in range(_len_i):
            e = Excess()
            serialized = e.deserialize_raw(serialized)
            self.updated_excesses[self.input_indexes[i]] = e
        if len(serialized) < 32:
            raise Exception("Not enough bytes for mixer offset")
        self.mixer_offset, serialized = int.from_bytes(serialized[:32],
                                                       "big"), serialized[32:]

        if not self.verify():
            #TODO consider renmaing verify to validate_excesses or make exception text more general
            raise Exception("Additional excesses are not signed properly")

        if rich_format and storage_space:
            txouts_num_serialized, serialized = serialized[:2], serialized[2:]
            txouts_num = int.from_bytes(txouts_num_serialized, "big")
            for _ in range(txouts_num):
                output = IOput()
                serialized = output.deserialize_raw(serialized)
                if not (output.serialized_index in self.output_indexes):
                    raise Exception("Unknown output in rich txskel data")
                storage_space.txos_storage.mempool[
                    output.serialized_index] = output

        return serialized
Example #17
0
def ioput_serialize_deserialize():
    options = {
        'address': [adr1],
        'value': [1, 100, int(705e6 * 1e8)],
        'relay_fee': [0, 100, int(1e8)],
        'generator': [
            None
        ],  #b'\x0b\xf8x*\xe9\xdc\xb1\xfd\xe9k\x8eZ\xf9\x8250\xdcrLU`p\xbaD\xf1\xfdh\x93\xd7\x85\xb9\x9e\x07'], #TODO arbitraty value gen
        'burden_hash': [None, b"\x44" * 32],
        'coinbase': [True, False],
        'lock_height': [0, 10, 10000]
    }
    all_possible_options = [{}]
    for opt in options:
        c = all_possible_options
        all_possible_options = []
        for i in options[opt]:
            for prev in c:
                n = prev.copy()
                if i != None:
                    n[opt] = i
                all_possible_options.append(n)

    for var in all_possible_options:
        _input1 = IOput()
        _input1.fill(**var)
        _input1.generate()

        _input2 = IOput(binary_object=_input1.serialize())
        _input2.verify()

        assert _input1.version == _input2.version
        assert _input1.block_version == _input2.block_version
        assert _input1.lock_height == _input2.lock_height
        assert _input1.authorized_pedersen_commitment.serialize(
        ) == _input2.authorized_pedersen_commitment.serialize()
        assert _input1.address.serialize() == _input2.address.serialize()
        assert _input1.rangeproof.proof == _input2.rangeproof.proof
        assert _input1.encrypted_message == _input2.encrypted_message
        assert _input1.generator == _input2.generator
        assert _input1.relay_fee == _input2.relay_fee
        assert _input1.authorized_burden == _input2.authorized_burden

    print("ioput_serialize_deserialize OK")
Example #18
0
    def deserialize_raw(self, serialized, storage_space=None):
        if len(serialized) < 1:
            raise Exception(
                "Not enough bytes for tx skeleton rich format marker")
        serialized, rich_format = serialized[1:], bool(serialized[0])
        if len(serialized) < 2:
            raise Exception("Not enough bytes for tx skeleton inputs len")
        serialized, _len_i = serialized[2:], int.from_bytes(
            serialized[:2], "big")
        if len(serialized) < 2:
            raise Exception("Not enough bytes for tx skeleton outputs len")
        serialized, _len_o = serialized[2:], int.from_bytes(
            serialized[:2], "big")

        if len(serialized) < 2:
            raise Exception(
                "Not enough bytes for tx skeleton additional excesses len")
        serialized, _len_ae = serialized[2:], int.from_bytes(
            serialized[:2], "big")

        serialized_index_len = IOput().index_len
        for i in range(_len_i):
            if len(serialized) < serialized_index_len:
                raise Exception(
                    "Not enough bytes for tx skeleton' input index %d len" % i)
            _input_index, serialized = serialized[:
                                                  serialized_index_len], serialized[
                                                      serialized_index_len:]
            self.input_indexes.append(_input_index)
        for i in range(_len_o):
            if len(serialized) < serialized_index_len:
                raise Exception(
                    "Not enough bytes for tx skeleton' output index %d len" %
                    i)
            _output_index, serialized = serialized[:
                                                   serialized_index_len], serialized[
                                                       serialized_index_len:]
            self.output_indexes.append(_output_index)

        for i in range(_len_ae):
            e = Excess()
            serialized = e.deserialize_raw(serialized)
            self.additional_excesses.append(e)

        if not self.verify():
            #TODO consider renmaing verify to validate_excesses or make exception text more general
            raise Exception("Additional excesses are not signed properly")

        if rich_format and storage_space:
            txouts_num_serialized, serialized = serialized[:2], serialized[2:]
            txouts_num = int.from_bytes(txouts_num_serialized, "big")
            for _ in range(txouts_num):
                output = IOput()
                serialized = output.deserialize_raw(serialized)
                if not (output.serialized_index in self.output_indexes):
                    raise Exception("Unknown output in rich txskel data")
                storage_space.txos_storage.mempool[
                    output.serialized_index] = output

        if not GLOBAL_TEST['skip combined excesses']:
            raise NotImplemented
        return serialized
Example #19
0
def ioput_proofs_info():
    _input1 = IOput()
    _input1.fill(adr1, 100)
    _input1.version = 1  #To use RangeProof instead of BulletProofs
    _input1.generate(exp=2, concealed_bits=3)
    info = _input1.info()
    assert info['exp'] == 2
    assert info['min_value'] == 0
    assert info['max_value'] == 700
    _input1 = IOput()
    _input1.fill(adr1, 3)
    _input1.version = 1  #To use RangeProof instead of BulletProofs
    _input1.generate(exp=0, concealed_bits=3, min_value=1)
    info = _input1.info()
    assert info['exp'] == 0
    assert info['mantissa'] == 3
    assert info['min_value'] == 1
    assert info['max_value'] == 8
    _input1 = IOput()
    _input1.fill(adr1, 300)
    _input1.version = 1  #To use RangeProof instead of BulletProofs
    #coceanled bits cannot be less than bits in value
    _input1.generate(exp=0, concealed_bits=3)
    info = _input1.info()
    assert info['exp'] == 0
    assert info['mantissa'] == 9
    assert info['min_value'] == 0
    assert info['max_value'] == 511
    print("ioput_proofs_info OK")

    _input1 = IOput()
    _input1.fill(adr1, 300)
    _input1.generate()
    info = _input1.info()
    assert info['exp'] == 0
    assert info['mantissa'] == 0
    assert info['min_value'] == 0
    assert info['max_value'] == 2**64 - 1
Example #20
0
    def deserialize(self, serialized_tx):
        if len(serialized_tx) < 2:
            raise Exception(
                "Serialized transaction doesn't contain enough bytes for inputs array length"
            )
        inputs_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[2:]
        (inputs_len, ) = struct.unpack("> H", inputs_len_buffer)
        for _input_index in range(inputs_len):
            if len(serialized_tx) < 2:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for input %s length"
                    % _input_index)
            input_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[
                2:]
            (input_len, ) = struct.unpack("> H", input_len_buffer)
            if len(serialized_tx) < input_len:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for input %s"
                    % _input_index)
            input_index_buffer, serialized_tx = serialized_tx[:
                                                              input_len], serialized_tx[
                                                                  input_len:]

            if not GLOBAL_TEST['spend from mempool']:
                raise NotImplemented
            else:
                if not input_index_buffer in self.txos_storage.confirmed:
                    raise Exception("Unknown input index")
                self.inputs.append(
                    self.txos_storage.confirmed[input_index_buffer])

        if len(serialized_tx) < 2:
            raise Exception(
                "Serialized transaction doesn't contain enough bytes for outputs array length"
            )
        outputs_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[
            2:]
        (outputs_len, ) = struct.unpack("> H", outputs_len_buffer)
        for _output_index in range(outputs_len):
            if len(serialized_tx) < 2:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for output %s length"
                    % _output_index)
            output_len_buffer, serialized_tx = serialized_tx[:
                                                             2], serialized_tx[
                                                                 2:]
            (output_len, ) = struct.unpack("> H", output_len_buffer)
            if len(serialized_tx) < output_len:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for output %s"
                    % _output_index)
            output_buffer, serialized_tx = serialized_tx[:
                                                         output_len], serialized_tx[
                                                             output_len:]
            self.outputs.append(IOput(binary_object=output_buffer))

        if len(serialized_tx) < 2:
            raise Exception(
                "Serialized transaction doesn't contain enough bytes for additional excesses array length"
            )
        aes_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[2:]
        (aes_len, ) = struct.unpack("> H", aes_len_buffer)
        for _ae in range(aes_len):
            if len(serialized_tx) < 2:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for additional excess %s length"
                    % _ae)
            ae_len_buffer, serialized_tx = serialized_tx[:2], serialized_tx[2:]
            (ae_len, ) = struct.unpack("> H", ae_len_buffer)
            if len(serialized_tx) < ae_len:
                raise Exception(
                    "Serialized transaction doesn't contain enough bytes for additional excess %s"
                    % _ae)
            ae_buffer, serialized_tx = serialized_tx[:ae_len], serialized_tx[
                ae_len:]
            e = Excess()
            e.deserialize_raw(ae_buffer)
            self.additional_excesses.append(e)

        self.verify()
        if not GLOBAL_TEST['skip combined excesses']:
            raise NotImplemented