def test_multiple_fulfillment_validation_of_transfer_tx(user_ffill, user_cond,
                                                        user_priv, user2_pub,
                                                        user2_priv, user3_pub,
                                                        user3_priv):
    from copy import deepcopy
    from bigchaindb_common.transaction import (Transaction, TransactionLink,
                                               Fulfillment, Condition, Asset)
    from cryptoconditions import Ed25519Fulfillment

    tx = Transaction(Transaction.CREATE, Asset(),
                     [user_ffill, deepcopy(user_ffill)],
                     [user_cond, deepcopy(user_cond)])
    tx.sign([user_priv])

    fulfillments = [Fulfillment(cond.fulfillment, cond.owners_after,
                                TransactionLink(tx.id, index))
                    for index, cond in enumerate(tx.conditions)]
    conditions = [Condition(Ed25519Fulfillment(public_key=user3_pub),
                            [user3_pub]),
                  Condition(Ed25519Fulfillment(public_key=user3_pub),
                            [user3_pub])]
    transfer_tx = Transaction('TRANSFER', tx.asset, fulfillments, conditions)
    transfer_tx = transfer_tx.sign([user_priv])

    assert transfer_tx.fulfillments_valid(tx.conditions) is True
示例#2
0
def create_asset(vw_sk, vw_pk, vehicle_id, data, metadata):
    # Create asset VW -> [VW, TEL]
    # Custom crypto condition multisig 1-2
    threshold_fulfillment = ThresholdSha256Fulfillment(threshold=1)

    vw_fulfillment = Ed25519Fulfillment(public_key=vw_pk)
    tel_fulfillment = Ed25519Fulfillment(public_key=vehicle_id)

    threshold_fulfillment.add_subfulfillment(vw_fulfillment)
    threshold_fulfillment.add_subfulfillment(tel_fulfillment)

    output = {
        'amount': 1,
        'condition': {
            'details': threshold_fulfillment.to_dict(),
            'uri': threshold_fulfillment.condition.serialize_uri()
        },
        'public_keys': [vw_pk, vehicle_id]
    }

    # Create the transaction
    tx_create = Transaction.create([vw_pk], [([vw_pk, vehicle_id], 1)],
                                   asset=data,
                                   metadata=metadata)
    # Override the condition we our custom build one
    tx_create.outputs[0] = Output.from_dict(output)

    # Sign the transaction
    tx_create_signed = tx_create.sign([vw_sk])

    return tx_create_signed
示例#3
0
    def test_deserialize_unsigned_dict_to_fulfillment(self, vk_ilp):
        fulfillment = ThresholdSha256Fulfillment(threshold=1)
        fulfillment.add_subfulfillment(
            Ed25519Fulfillment(public_key=VerifyingKey(vk_ilp['b58'])))
        fulfillment.add_subfulfillment(
            Ed25519Fulfillment(public_key=VerifyingKey(vk_ilp['b58'])))
        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())

        assert parsed_fulfillment.condition.serialize_uri(
        ) == fulfillment.condition.serialize_uri()
        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
def persisted_transfer_dimi_car_to_ewy(dimi_keypair, ewy_pubkey,
                                       transactions_api_full_url,
                                       persisted_transfer_carol_car_to_dimi):
    output_txid = persisted_transfer_carol_car_to_dimi['id']
    ed25519_ewy = Ed25519Fulfillment(public_key=ewy_pubkey)
    transaction = {
        'asset': {
            'id': persisted_transfer_carol_car_to_dimi['asset']['id']
        },
        'metadata':
        None,
        'operation':
        'TRANSFER',
        'outputs': ({
            'amount': 1,
            'condition': {
                'details': ed25519_ewy.to_dict(),
                'uri': ed25519_ewy.condition_uri,
            },
            'public_keys': (ewy_pubkey, ),
        }, ),
        'inputs': ({
            'fulfillment': None,
            'fulfills': {
                'output': 0,
                'txid': output_txid,
            },
            'owners_before': (dimi_keypair.public_key, ),
        }, ),
        'version':
        '0.9',
    }
    serialized_transaction_without_id = json.dumps(
        transaction,
        sort_keys=True,
        separators=(',', ':'),
        ensure_ascii=False,
    ).encode()
    transaction['id'] = sha3_256(serialized_transaction_without_id).hexdigest()
    serialized_transaction_with_id = json.dumps(
        transaction,
        sort_keys=True,
        separators=(',', ':'),
        ensure_ascii=False,
    ).encode()
    ed25519_dimi = Ed25519Fulfillment(public_key=dimi_keypair.public_key)
    ed25519_dimi.sign(serialized_transaction_with_id,
                      Ed25519SigningKey(dimi_keypair.private_key))
    transaction['inputs'][0]['fulfillment'] = ed25519_dimi.serialize_uri()
    response = requests.post(transactions_api_full_url, json=transaction)
    return response.json()
def test_generate_conditions_flat_ownage(user_pub, user2_pub, user3_pub):
    from bigchaindb_common.transaction import Condition
    from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment

    expected_simple1 = Ed25519Fulfillment(public_key=user_pub)
    expected_simple2 = Ed25519Fulfillment(public_key=user2_pub)
    expected_simple3 = Ed25519Fulfillment(public_key=user3_pub)

    expected = ThresholdSha256Fulfillment(threshold=3)
    expected.add_subfulfillment(expected_simple1)
    expected.add_subfulfillment(expected_simple2)
    expected.add_subfulfillment(expected_simple3)

    cond = Condition.generate([user_pub, user2_pub, expected_simple3])
    assert cond.fulfillment.to_dict() == expected.to_dict()
def test_validate_fulfillments_of_transfer_tx_with_invalid_params(transfer_tx,
                                                                  cond_uri,
                                                                  utx,
                                                                  user2_pub,
                                                                  user_priv):
    from bigchaindb_common.transaction import Condition
    from cryptoconditions import Ed25519Fulfillment

    invalid_cond = Condition(Ed25519Fulfillment.from_uri('cf:0:'), ['invalid'])
    assert transfer_tx.fulfillments_valid([invalid_cond]) is False
    invalid_cond = utx.conditions[0]
    invalid_cond.owners_after = 'invalid'
    assert transfer_tx.fulfillments_valid([invalid_cond]) is True

    with raises(TypeError):
        assert transfer_tx.fulfillments_valid(None) is False
    with raises(AttributeError):
        transfer_tx.fulfillments_valid('not a list')
    with raises(ValueError):
        transfer_tx.fulfillments_valid([])
    with raises(TypeError):
        transfer_tx.operation = "Operation that doesn't exist"
        transfer_tx.fulfillments_valid([utx.conditions[0]])
    with raises(ValueError):
        tx = utx.sign([user_priv])
        tx.conditions = []
        tx.fulfillments_valid()
示例#7
0
    def test_deserialize_unsigned_dict_to_fulfillment(self, vk_ilp):
        fulfillment = Ed25519Fulfillment(public_key=vk_ilp['b58'])
        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())

        assert parsed_fulfillment.condition.serialize_uri(
        ) == fulfillment.condition.serialize_uri()
        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
示例#8
0
    def create_fulfillment_ed25519sha256(self, sk_ilp, vk_ilp):
        sk = SigningKey(sk_ilp['b58'])
        vk = VerifyingKey(vk_ilp['b58'])

        fulfillment = Ed25519Fulfillment(public_key=vk)
        fulfillment.sign(MESSAGE, sk)
        return fulfillment
def test_generate_conditions_single_owner_with_condition(user_pub):
    from bigchaindb_common.transaction import Condition
    from cryptoconditions import Ed25519Fulfillment

    expected = Ed25519Fulfillment(public_key=user_pub)
    cond = Condition.generate([expected])

    assert cond.fulfillment.to_dict() == expected.to_dict()
示例#10
0
def user_user2_threshold(user_pub, user2_pub):
    from cryptoconditions import (ThresholdSha256Fulfillment,
                                  Ed25519Fulfillment)
    user_pub_keys = [user_pub, user2_pub]
    threshold = ThresholdSha256Fulfillment(threshold=len(user_pub_keys))
    for user_pub in user_pub_keys:
        threshold.add_subfulfillment(Ed25519Fulfillment(public_key=user_pub))
    return threshold
def test_generate_conditions_split_half_single_owner(user_pub, user2_pub,
                                                     user3_pub):
    from bigchaindb_common.transaction import Condition
    from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment

    expected_simple1 = Ed25519Fulfillment(public_key=user_pub)
    expected_simple2 = Ed25519Fulfillment(public_key=user2_pub)
    expected_simple3 = Ed25519Fulfillment(public_key=user3_pub)

    expected = ThresholdSha256Fulfillment(threshold=2)
    expected_threshold = ThresholdSha256Fulfillment(threshold=2)
    expected_threshold.add_subfulfillment(expected_simple2)
    expected_threshold.add_subfulfillment(expected_simple3)
    expected.add_subfulfillment(expected_threshold)
    expected.add_subfulfillment(expected_simple1)

    cond = Condition.generate([[expected_simple2, user3_pub], user_pub])
    assert cond.fulfillment.to_dict() == expected.to_dict()
示例#12
0
def make_ed25519_condition(public_key, *, amount=1):
    ed25519 = Ed25519Fulfillment(public_key=public_key)
    return {
        'amount': amount,
        'condition': {
            'details': ed25519.to_dict(),
            'uri': ed25519.condition_uri,
        },
        'public_keys': (public_key, ),
    }
示例#13
0
    def test_serialize_unsigned_dict_to_fulfillment(self, vk_ilp):
        fulfillment = Ed25519Fulfillment(public_key=vk_ilp['b58'])

        assert fulfillment.to_dict() == \
            {'bitmask': 32,
             'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
             'signature': None,
             'type': 'fulfillment',
             'type_id': 4}
        assert fulfillment.validate(MESSAGE) == False
示例#14
0
def sign_transaction(transaction, *, public_key, private_key):
    ed25519 = Ed25519Fulfillment(public_key=public_key)
    message = json.dumps(
        transaction,
        sort_keys=True,
        separators=(',', ':'),
        ensure_ascii=False,
    )
    ed25519.sign(message.encode(), Ed25519SigningKey(private_key))
    return ed25519.serialize_uri()
示例#15
0
    def generate(cls, owners_after):
        """Generates a Condition from a specifically formed tuple or list.

            Note:
                If a ThresholdCondition has to be generated where the threshold
                is always the number of subconditions it is split between, a
                list of the following structure is sufficient:

                [(address|condition)*, [(address|condition)*, ...], ...]

                If however, the thresholds of individual threshold conditions
                to be created have to be set specifically, a tuple of the
                following structure is necessary:

                ([(address|condition)*,
                  ([(address|condition)*, ...], subthreshold),
                  ...], threshold)

            Args:
                owners_after (:obj:`list` of :obj:`str`|tuple): The users that
                    should be able to fulfill the Condition that is being
                    created.

            Returns:
                A Condition that can be used in a Transaction.

            Returns:
                TypeError: If `owners_after` is not an instance of `list`.
                TypeError: If `owners_after` is an empty list.
        """
        # TODO: We probably want to remove the tuple logic for weights here
        # again:
        # github.com/bigchaindb/bigchaindb/issues/730#issuecomment-255144756
        if isinstance(owners_after, tuple):
            owners_after, threshold = owners_after
        else:
            threshold = len(owners_after)

        if not isinstance(owners_after, list):
            raise TypeError('`owners_after` must be an instance of list')
        if len(owners_after) == 0:
            raise ValueError('`owners_after` needs to contain at least one'
                             'owner')
        elif len(owners_after) == 1 and not isinstance(owners_after[0], list):
            try:
                ffill = Ed25519Fulfillment(public_key=owners_after[0])
            except TypeError:
                ffill = owners_after[0]
            return cls(ffill, owners_after)
        else:
            initial_cond = ThresholdSha256Fulfillment(threshold=threshold)
            threshold_cond = reduce(cls._gen_condition, owners_after,
                                    initial_cond)
            return cls(threshold_cond, owners_after)
def test_generate_conditions_split_half_recursive_custom_threshold(user_pub,
                                                                   user2_pub,
                                                                   user3_pub):
    from bigchaindb_common.transaction import Condition
    from cryptoconditions import Ed25519Fulfillment, ThresholdSha256Fulfillment

    expected_simple1 = Ed25519Fulfillment(public_key=user_pub)
    expected_simple2 = Ed25519Fulfillment(public_key=user2_pub)
    expected_simple3 = Ed25519Fulfillment(public_key=user3_pub)

    expected = ThresholdSha256Fulfillment(threshold=1)
    expected.add_subfulfillment(expected_simple1)
    expected_threshold = ThresholdSha256Fulfillment(threshold=1)
    expected_threshold.add_subfulfillment(expected_simple2)
    expected_threshold.add_subfulfillment(expected_simple3)
    expected.add_subfulfillment(expected_threshold)

    cond = Condition.generate(([user_pub, ([user2_pub, expected_simple3], 1)],
                              1))
    assert cond.fulfillment.to_dict() == expected.to_dict()
def test_generate_threshold_condition_with_hashlock(user_pub, user2_pub,
                                                    user3_pub):
    from bigchaindb_common.transaction import Condition
    from cryptoconditions import (PreimageSha256Fulfillment,
                                  Ed25519Fulfillment,
                                  ThresholdSha256Fulfillment)

    secret = b'much secret, wow'
    hashlock = PreimageSha256Fulfillment(preimage=secret)

    expected_simple1 = Ed25519Fulfillment(public_key=user_pub)
    expected_simple3 = Ed25519Fulfillment(public_key=user3_pub)

    expected = ThresholdSha256Fulfillment(threshold=2)
    expected_sub = ThresholdSha256Fulfillment(threshold=2)
    expected_sub.add_subfulfillment(expected_simple1)
    expected_sub.add_subfulfillment(hashlock)
    expected.add_subfulfillment(expected_simple3)

    cond = Condition.generate([[user_pub, hashlock], expected_simple3])
    assert cond.fulfillment.to_dict() == expected.to_dict()
示例#18
0
def sign_ed25519(transaction, private_keys):
    from cryptoconditions import Ed25519Fulfillment
    from cryptoconditions.crypto import Ed25519VerifyingKey

    for index, _input in enumerate(transaction.inputs):
        receiver = _input.owners_before[0]
        transaction.inputs[index].fulfillment = Ed25519Fulfillment(
            public_key=Ed25519VerifyingKey(receiver))

    private_keys = [private_keys
                    ] if not isinstance(private_keys, list) else private_keys
    return transaction.sign(private_keys).to_dict()
示例#19
0
    def test_serialize_deserialize_condition(self, vk_ilp):
        vk = VerifyingKey(vk_ilp['b58'])

        fulfillment = Ed25519Fulfillment(public_key=vk)

        condition = fulfillment.condition
        deserialized_condition = Condition.from_uri(condition.serialize_uri())

        assert deserialized_condition.bitmask == condition.bitmask
        assert deserialized_condition.hash == condition.hash
        assert deserialized_condition.max_fulfillment_length == condition.max_fulfillment_length
        assert deserialized_condition.serialize_uri(
        ) == condition.serialize_uri()
 def test_fulfill(self, driver, alice_keypair, unsigned_transaction):
     signed_transaction = driver.transactions.fulfill(
         unsigned_transaction, private_keys=alice_keypair.sk)
     unsigned_transaction['inputs'][0]['fulfillment'] = None
     message = json.dumps(
         unsigned_transaction,
         sort_keys=True,
         separators=(',', ':'),
         ensure_ascii=False,
     ).encode()
     ed25519 = Ed25519Fulfillment(public_key=alice_keypair.vk)
     ed25519.sign(message, Ed25519SigningKey(alice_keypair.sk))
     fulfillment_uri = ed25519.serialize_uri()
     assert signed_transaction['inputs'][0]['fulfillment'] == fulfillment_uri   # noqa
示例#21
0
    def test_serialize_unsigned_dict_to_fulfillment(self, vk_ilp):
        fulfillment = ThresholdSha256Fulfillment(threshold=1)
        fulfillment.add_subfulfillment(
            Ed25519Fulfillment(public_key=VerifyingKey(vk_ilp['b58'])))
        fulfillment.add_subfulfillment(
            Ed25519Fulfillment(public_key=VerifyingKey(vk_ilp['b58'])))

        assert fulfillment.to_dict() == \
            {'bitmask': 41,
             'subfulfillments': [{'bitmask': 32,
                                  'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
                                  'signature': None,
                                  'type': 'fulfillment',
                                  'type_id': 4,
                                  'weight': 1},
                                 {'bitmask': 32,
                                  'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
                                  'signature': None,
                                  'type': 'fulfillment',
                                  'type_id': 4,
                                  'weight': 1}],
             'threshold': 1,
             'type': 'fulfillment',
             'type_id': 2}
示例#22
0
    def _gen_condition(cls, initial, current):
        """Generates ThresholdSha256 conditions from a list of new owners.

            Note:
                This method is intended only to be used with a reduce function.
                For a description on how to use this method, see
                `Condition.generate`.

            Args:
                initial (:class:`cryptoconditions.ThresholdSha256Fulfillment`):
                    A Condition representing the overall root.
                current (:obj:`list` of :obj:`str`|str): A list of new owners
                    or a single new owner.

            Returns:
                :class:`cryptoconditions.ThresholdSha256Fulfillment`:
        """
        if isinstance(current, tuple):
            owners_after, threshold = current
        else:
            owners_after = current
            try:
                threshold = len(owners_after)
            except TypeError:
                threshold = None

        if isinstance(owners_after, list) and len(owners_after) > 1:
            ffill = ThresholdSha256Fulfillment(threshold=threshold)
            reduce(cls._gen_condition, owners_after, ffill)
        elif isinstance(owners_after, list) and len(owners_after) <= 1:
            raise ValueError('Sublist cannot contain single owner')
        else:
            try:
                owners_after = owners_after.pop()
            except AttributeError:
                pass
            try:
                ffill = Ed25519Fulfillment(public_key=owners_after)
            except TypeError:
                # NOTE: Instead of submitting base58 encoded addresses, a user
                #       of this class can also submit fully instantiated
                #       Cryptoconditions. In the case of casting `owners_after`
                #       to a Ed25519Fulfillment with the result of a
                #       `TypeError`, we're assuming that `owners_after` is a
                #       Cryptocondition then.
                ffill = owners_after
        initial.add_subfulfillment(ffill)
        return initial
示例#23
0
def prepare_transfer_ed25519_simple(transaction, receiver, metadata=None):
    from cryptoconditions import Ed25519Fulfillment
    from cryptoconditions.crypto import Ed25519VerifyingKey

    return prepare_transfer(
        inputs=[{
            'tx': transaction,
            'output': 0
        }],
        outputs=[{
            'condition':
            Ed25519Fulfillment(public_key=Ed25519VerifyingKey(receiver)),
            'public_keys': [receiver],
            'amount':
            1
        }],
        metadata=metadata)
示例#24
0
    def generate(cls, owners_after, amount):
        """Generates a Condition from a specifically formed tuple or list.

            Note:
                If a ThresholdCondition has to be generated where the threshold
                is always the number of subconditions it is split between, a
                list of the following structure is sufficient:

                [(address|condition)*, [(address|condition)*, ...], ...]

            Args:
                owners_after (:obj:`list` of :obj:`str`): The public key of
                    the users that should be able to fulfill the Condition
                    that is being created.
                amount (:obj:`int`): The amount locked by the condition.

            Returns:
                A Condition that can be used in a Transaction.

            Raises:
                TypeError: If `owners_after` is not an instance of `list`.
                ValueError: If `owners_after` is an empty list.
        """
        threshold = len(owners_after)
        if not isinstance(amount, int):
            raise TypeError('`amount` must be a int')
        if amount < 1:
            raise AmountError('`amount` needs to be greater than zero')
        if not isinstance(owners_after, list):
            raise TypeError('`owners_after` must be an instance of list')
        if len(owners_after) == 0:
            raise ValueError('`owners_after` needs to contain at least one'
                             'owner')
        elif len(owners_after) == 1 and not isinstance(owners_after[0], list):
            try:
                ffill = Ed25519Fulfillment(public_key=owners_after[0])
            except TypeError:
                ffill = owners_after[0]
            return cls(ffill, owners_after, amount=amount)
        else:
            initial_cond = ThresholdSha256Fulfillment(threshold=threshold)
            threshold_cond = reduce(cls._gen_condition, owners_after,
                                    initial_cond)
            return cls(threshold_cond, owners_after, amount=amount)
示例#25
0
    def _gen_condition(cls, initial, new_public_keys):
        """Generates ThresholdSha256 conditions from a list of new owners.

            Note:
                This method is intended only to be used with a reduce function.
                For a description on how to use this method, see
                :meth:`~.Output.generate`.

            Args:
                initial (:class:`cryptoconditions.ThresholdSha256Fulfillment`):
                    A Condition representing the overall root.
                new_public_keys (:obj:`list` of :obj:`str`|str): A list of new
                    owners or a single new owner.

            Returns:
                :class:`cryptoconditions.ThresholdSha256Fulfillment`:
        """
        try:
            threshold = len(new_public_keys)
        except TypeError:
            threshold = None

        if isinstance(new_public_keys, list) and len(new_public_keys) > 1:
            ffill = ThresholdSha256Fulfillment(threshold=threshold)
            reduce(cls._gen_condition, new_public_keys, ffill)
        elif isinstance(new_public_keys, list) and len(new_public_keys) <= 1:
            raise ValueError('Sublist cannot contain single owner')
        else:
            try:
                new_public_keys = new_public_keys.pop()
            except AttributeError:
                pass
            try:
                ffill = Ed25519Fulfillment(public_key=new_public_keys)
            except TypeError:
                # NOTE: Instead of submitting base58 encoded addresses, a user
                #       of this class can also submit fully instantiated
                #       Cryptoconditions. In the case of casting
                #       `new_public_keys` to a Ed25519Fulfillment with the
                #       result of a `TypeError`, we're assuming that
                #       `new_public_keys` is a Cryptocondition then.
                ffill = new_public_keys
        initial.add_subfulfillment(ffill)
        return initial
示例#26
0
    def test_serialize_deserialize_fulfillment(self, sk_ilp, vk_ilp):
        sk = SigningKey(sk_ilp['b58'])
        vk = VerifyingKey(vk_ilp['b58'])

        fulfillment = Ed25519Fulfillment(public_key=vk)
        fulfillment.sign(MESSAGE, sk)

        assert fulfillment.validate(MESSAGE)

        deserialized_fulfillment = Fulfillment.from_uri(
            fulfillment.serialize_uri())
        assert isinstance(deserialized_fulfillment, Ed25519Fulfillment)
        assert deserialized_fulfillment.serialize_uri(
        ) == fulfillment.serialize_uri()
        assert deserialized_fulfillment.condition.serialize_uri(
        ) == fulfillment.condition.serialize_uri()
        assert deserialized_fulfillment.public_key.encode(encoding='bytes') == \
                fulfillment.public_key.encode(encoding='bytes')
        assert deserialized_fulfillment.validate(MESSAGE)
示例#27
0
    def test_serialize_condition_and_validate_fulfillment(
            self, sk_ilp, vk_ilp, fulfillment_ed25519):
        sk = SigningKey(sk_ilp['b58'])
        vk = VerifyingKey(vk_ilp['b58'])

        fulfillment = Ed25519Fulfillment(public_key=vk)

        assert fulfillment.condition.serialize_uri(
        ) == fulfillment_ed25519['condition_uri']
        assert binascii.hexlify(fulfillment.condition.hash
                                ) == fulfillment_ed25519['condition_hash']

        # ED25519-SHA256 condition not fulfilled
        assert fulfillment.validate() == False

        # Fulfill an ED25519-SHA256 condition
        fulfillment.sign(MESSAGE, sk)

        assert fulfillment.serialize_uri(
        ) == fulfillment_ed25519['fulfillment_uri']
        assert fulfillment.validate(MESSAGE)
示例#28
0
    def test_fulfillment_didnt_reach_threshold(self, vk_ilp,
                                               fulfillment_ed25519):
        ilp_fulfillment = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])
        threshold = 10

        # Create a threshold condition
        fulfillment = ThresholdSha256Fulfillment(threshold=threshold)

        for i in range(threshold - 1):
            fulfillment.add_subfulfillment(ilp_fulfillment)

        with pytest.raises(KeyError):
            fulfillment.serialize_uri()

        assert fulfillment.validate(MESSAGE) is False

        fulfillment.add_subfulfillment(ilp_fulfillment)

        fulfillment_uri = fulfillment.serialize_uri()
        assert fulfillment.validate(MESSAGE)

        deserialized_fulfillment = Fulfillment.from_uri(fulfillment_uri)

        assert isinstance(deserialized_fulfillment, ThresholdSha256Fulfillment)
        assert deserialized_fulfillment.threshold == threshold
        assert len([
            f for f in deserialized_fulfillment.subconditions
            if f['type'] == 'fulfillment'
        ]) == threshold
        assert len(deserialized_fulfillment.subconditions) == threshold
        assert deserialized_fulfillment.serialize_uri() == fulfillment_uri
        assert deserialized_fulfillment.validate(MESSAGE)

        fulfillment.add_subfulfillment(
            Ed25519Fulfillment(public_key=VerifyingKey(vk_ilp['b58'])))

        assert fulfillment.validate(MESSAGE) == True
示例#29
0
def create_transfer(prev_tx, vw_sk, vw_pk, vehicle_id, metadata, asset_id):
    prev_tx = Transaction.from_dict(prev_tx)
    # Create asset VW -> [VW, TEL]
    # Custom crypto condition multisig 1-2
    threshold_fulfillment = ThresholdSha256Fulfillment(threshold=1)

    vw_fulfillment = Ed25519Fulfillment(public_key=vw_pk)
    tel_fulfillment = Ed25519Fulfillment(public_key=vehicle_id)

    threshold_fulfillment.add_subfulfillment(vw_fulfillment)
    threshold_fulfillment.add_subfulfillment(tel_fulfillment)

    output = {
        'amount': 1,
        'condition': {
            'details': threshold_fulfillment.to_dict(),
            'uri': threshold_fulfillment.condition.serialize_uri()
        },
        'public_keys': [vw_pk, vehicle_id],
    }

    # The yet to be fulfilled input:
    input_ = {
        'fulfillment': None,
        'fulfills': {
            'txid': prev_tx.id,
            'output': 0,
        },
        'owners_before': [vw_pk, vehicle_id],
    }

    # Craft the payload:
    transfer_tx = {
        'operation': 'TRANSFER',
        'asset': {
            'id': asset_id
        },
        'metadata': metadata,
        'outputs': [output],
        'inputs': [input_],
        'version': '0.9',
    }

    # Generate the id, by hashing the encoded json formatted string
    # representation of the transaction:
    json_str_tx = json.dumps(
        transfer_tx,
        sort_keys=True,
        separators=(',', ':'),
        ensure_ascii=False,
    )

    txid = sha3.sha3_256(json_str_tx.encode()).hexdigest()

    transfer_tx['id'] = txid

    # Sign the transaction:
    message = json.dumps(
        transfer_tx,
        sort_keys=True,
        separators=(',', ':'),
        ensure_ascii=False,
    )

    threshold_fulfillment = ThresholdSha256Fulfillment(threshold=1)

    vw_fulfillment.sign(message.encode(), private_key=Ed25519SigningKey(vw_sk))
    threshold_fulfillment.add_subfulfillment(vw_fulfillment)
    threshold_fulfillment.add_subcondition(tel_fulfillment.condition)

    fulfillment_uri = threshold_fulfillment.serialize_uri()
    transfer_tx['inputs'][0]['fulfillment'] = fulfillment_uri
    return Transaction.from_dict(transfer_tx)
# instead of transfering to a simple public key we can craft
# custom cryptoconditions using thresholds, signatures, hashlocks, ...
# this example is a multisig between
#
#             bob     secret/hashlock
#      carly     \   /
#           \     and
#            \   /
#             and
#              |
#              o
#
#  the cryptocondition is added as an output
condition = ThresholdSha256Fulfillment(threshold=2)
condition.add_subfulfillment(
    Ed25519Fulfillment(public_key=Ed25519VerifyingKey(carly.public_key)))
subfulfillment = ThresholdSha256Fulfillment(threshold=2)
subfulfillment.add_subcondition(
    PreimageSha256Fulfillment(preimage=b'secret').condition)
subfulfillment.add_subfulfillment(
    Ed25519Fulfillment(public_key=Ed25519VerifyingKey(bob.public_key)))
condition.add_subfulfillment(subfulfillment)

# create the transfer transaction with the custom condition
tx_transfer_custom_condition = prepare_transfer(
    inputs=[{
        'tx': tx_create_alice_divisible_signed,
        'output': 0
    }],
    outputs=[
        {