Exemple #1
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
Exemple #2
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()
Exemple #3
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")
Exemple #4
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")
Exemple #5
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")
Exemple #6
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
Exemple #7
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()