示例#1
0
    def test_escrow_abort(self, fulfillment_sha256, fulfillment_ed25519):
        ilp_fulfillment_sha = Fulfillment.from_uri(
            fulfillment_sha256['fulfillment_uri'])
        ilp_fulfillment_ed = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])

        time_sleep = 0

        fulfillment_escrow = ThresholdSha256Fulfillment(threshold=1)
        fulfillment_timeout = TimeoutFulfillment(
            expire_time=str(float(timestamp()) + time_sleep))
        fulfillment_timeout_inverted = InvertedThresholdSha256Fulfillment(
            threshold=1)
        fulfillment_timeout_inverted.add_subfulfillment(fulfillment_timeout)

        # do not fulfill execute branch
        fulfillment_and_execute = ThresholdSha256Fulfillment(threshold=2)
        fulfillment_and_execute.add_subcondition(ilp_fulfillment_ed.condition)
        fulfillment_and_execute.add_subfulfillment(fulfillment_timeout)

        fulfillment_and_abort = ThresholdSha256Fulfillment(threshold=2)
        fulfillment_and_abort.add_subfulfillment(ilp_fulfillment_sha)
        fulfillment_and_abort.add_subfulfillment(fulfillment_timeout_inverted)

        fulfillment_escrow.add_subfulfillment(fulfillment_and_execute)
        fulfillment_escrow.add_subfulfillment(fulfillment_and_abort)

        # out-of-time validation
        assert fulfillment_escrow.validate(MESSAGE, now=timestamp()) is True
示例#2
0
    def test_weights(self, fulfillment_ed25519):
        ilp_fulfillment = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])

        fulfillment1 = ThresholdSha256Fulfillment(threshold=2)
        fulfillment1.add_subfulfillment(ilp_fulfillment, weight=2)
        parsed_fulfillment1 = fulfillment1.from_dict(fulfillment1.to_dict())

        assert parsed_fulfillment1.condition.serialize_uri(
        ) == fulfillment1.condition.serialize_uri()
        assert parsed_fulfillment1.to_dict() == fulfillment1.to_dict()
        assert parsed_fulfillment1.subconditions[0]['weight'] == 2
        assert parsed_fulfillment1.validate(MESSAGE) is True

        fulfillment2 = ThresholdSha256Fulfillment(threshold=3)
        fulfillment2.add_subfulfillment(ilp_fulfillment, weight=2)
        parsed_fulfillment2 = fulfillment1.from_dict(fulfillment2.to_dict())

        assert parsed_fulfillment2.subconditions[0]['weight'] == 2
        assert parsed_fulfillment2.validate(MESSAGE) is False

        fulfillment3 = ThresholdSha256Fulfillment(threshold=3)
        fulfillment3.add_subfulfillment(ilp_fulfillment, weight=3)
        parsed_fulfillment3 = fulfillment1.from_dict(fulfillment3.to_dict())

        assert parsed_fulfillment3.condition.serialize_uri(
        ) == fulfillment3.condition.serialize_uri()
        assert not (fulfillment3.condition.serialize_uri()
                    == fulfillment1.condition.serialize_uri())
        assert parsed_fulfillment3.validate(MESSAGE) is True

        fulfillment4 = ThresholdSha256Fulfillment(threshold=2)
        with pytest.raises(ValueError):
            fulfillment4.add_subfulfillment(ilp_fulfillment, weight=-2)
示例#3
0
    def test_serialize_condition_and_validate_fulfillment(
            self, fulfillment_sha256, fulfillment_ed25519,
            fulfillment_threshold):

        ilp_fulfillment_ed25519 = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])
        ilp_fulfillment_sha = Fulfillment.from_uri(
            fulfillment_sha256['fulfillment_uri'])

        assert ilp_fulfillment_ed25519.validate(MESSAGE) == True
        assert ilp_fulfillment_sha.validate(MESSAGE) == True

        threshold = 1

        # Create a threshold condition
        fulfillment = ThresholdSha256Fulfillment(threshold=threshold)
        fulfillment.add_subfulfillment(ilp_fulfillment_ed25519)
        fulfillment.add_subfulfillment(ilp_fulfillment_sha)

        assert fulfillment.condition.serialize_uri(
        ) == fulfillment_threshold['condition_uri']
        # Note: If there are more than enough fulfilled subconditions, shorter
        # fulfillments will be chosen over longer ones.
        # thresholdFulfillmentUri.length === 65
        assert fulfillment.serialize_uri(
        ) == fulfillment_threshold['fulfillment_uri']
        assert fulfillment.validate(MESSAGE)
示例#4
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
示例#5
0
    def test_serialize_deserialize_fulfillment(self, fulfillment_ed25519):
        ilp_fulfillment = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])
        num_fulfillments = 20
        threshold = ceil(num_fulfillments * 2 / 3)

        # Create a threshold condition
        fulfillment = ThresholdSha256Fulfillment(threshold=threshold)
        for i in range(num_fulfillments):
            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) == num_fulfillments
        assert deserialized_fulfillment.serialize_uri() == fulfillment_uri
        assert deserialized_fulfillment.validate(MESSAGE)
示例#6
0
    def test_fulfillment_nested_and_or(self, fulfillment_sha256,
                                       fulfillment_ed25519,
                                       fulfillment_threshold_nested_and_or):
        ilp_fulfillment_sha = Fulfillment.from_uri(
            fulfillment_sha256['fulfillment_uri'])
        ilp_fulfillment_ed = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])

        # 2-of-2 (AND with 2 inputs)
        fulfillment = ThresholdSha256Fulfillment(threshold=2)
        fulfillment.add_subfulfillment(ilp_fulfillment_sha)

        assert fulfillment.validate(MESSAGE) is False

        # 1-of-2 (OR with 2 inputs)
        nested_fulfillment = ThresholdSha256Fulfillment(threshold=1)
        nested_fulfillment.add_subfulfillment(ilp_fulfillment_ed)
        assert nested_fulfillment.validate(MESSAGE) is True
        nested_fulfillment.add_subfulfillment(ilp_fulfillment_ed)
        assert nested_fulfillment.validate(MESSAGE) is True

        fulfillment.add_subfulfillment(nested_fulfillment)
        assert fulfillment.validate(MESSAGE) is True

        fulfillment_uri = fulfillment.serialize_uri()
        assert fulfillment.condition_uri == fulfillment_threshold_nested_and_or[
            'condition_uri']
        assert fulfillment_uri == fulfillment_threshold_nested_and_or[
            'fulfillment_uri']

        print(fulfillment_uri)
        deserialized_fulfillment = Fulfillment.from_uri(fulfillment_uri)

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

        assert isinstance(deserialized_fulfillment, ThresholdSha256Fulfillment)
        assert deserialized_fulfillment.threshold == 2
        assert len(deserialized_fulfillment.subconditions) == 2
        assert len(deserialized_fulfillment.subconditions[1]
                   ['body'].subconditions) == 2
        assert deserialized_fulfillment.serialize_uri() == fulfillment_uri
        assert deserialized_fulfillment.validate(MESSAGE)
        assert deserialized_condition.serialize_uri() == condition_uri
        vk = ilp_fulfillment_ed.public_key.encode(encoding='base58')
        assert len(fulfillment.get_subcondition_from_vk(vk)) == 2
        assert len(deserialized_fulfillment.get_subcondition_from_vk(vk)) == 1
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
示例#8
0
 def add_nested_fulfillment(parent, current_depth=0):
     current_depth += 1
     child = ThresholdSha256Fulfillment(threshold=1)
     if current_depth < max_depth:
         add_nested_fulfillment(child, current_depth)
     else:
         child.add_subfulfillment(ilp_fulfillment_ed1)
     parent.add_subfulfillment(child)
     return parent
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()
示例#10
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 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()
示例#12
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_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()
示例#14
0
    def test_serialize_condition_and_validate_fulfillment(
            self, fulfillment_sha256, fulfillment_ed25519):
        ilp_fulfillment_sha = Fulfillment.from_uri(
            fulfillment_sha256['fulfillment_uri'])
        ilp_fulfillment_ed = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])

        fulfillment_escrow = ThresholdSha256Fulfillment(threshold=1)
        fulfillment_timeout = TimeoutFulfillment(
            expire_time=str(float(timestamp()) + 1000))
        fulfillment_timeout_inverted = InvertedThresholdSha256Fulfillment(
            threshold=1)
        fulfillment_timeout_inverted.add_subfulfillment(fulfillment_timeout)

        fulfillment_and_execute = ThresholdSha256Fulfillment(threshold=2)
        fulfillment_and_execute.add_subfulfillment(ilp_fulfillment_ed)
        fulfillment_and_execute.add_subfulfillment(fulfillment_timeout)

        assert fulfillment_and_execute.validate(MESSAGE,
                                                now=timestamp()) is True

        fulfillment_and_abort = ThresholdSha256Fulfillment(threshold=2)
        fulfillment_and_abort.add_subfulfillment(ilp_fulfillment_sha)
        fulfillment_and_abort.add_subfulfillment(fulfillment_timeout_inverted)

        # timeout has not occured (over about 1000 seconds)
        assert fulfillment_and_abort.validate(MESSAGE,
                                              now=timestamp()) is False

        fulfillment_escrow.add_subfulfillment(fulfillment_and_execute)
        fulfillment_escrow.add_subfulfillment(fulfillment_and_abort)

        parsed_fulfillment = fulfillment_escrow.from_dict(
            fulfillment_escrow.to_dict())

        assert parsed_fulfillment.condition_uri == fulfillment_escrow.condition_uri
        assert parsed_fulfillment.serialize_uri(
        ) == fulfillment_escrow.serialize_uri()
        assert parsed_fulfillment.validate(MESSAGE, now=timestamp()) is True
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()
示例#16
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
示例#17
0
    def test_fulfillment_nested(
        self,
        fulfillment_sha256,
        fulfillment_ed25519_2,
    ):
        ilp_fulfillment_sha = Fulfillment.from_uri(
            fulfillment_sha256['fulfillment_uri'])
        ilp_fulfillment_ed1 = Fulfillment.from_uri(
            fulfillment_ed25519_2['fulfillment_uri'])

        # 2-of-2 (AND with 2 inputs)
        fulfillment = ThresholdSha256Fulfillment(threshold=2)
        fulfillment.add_subfulfillment(ilp_fulfillment_sha)

        max_depth = 6

        def add_nested_fulfillment(parent, current_depth=0):
            current_depth += 1
            child = ThresholdSha256Fulfillment(threshold=1)
            if current_depth < max_depth:
                add_nested_fulfillment(child, current_depth)
            else:
                child.add_subfulfillment(ilp_fulfillment_ed1)
            parent.add_subfulfillment(child)
            return parent

        fulfillment = add_nested_fulfillment(fulfillment)

        assert fulfillment.validate(MESSAGE) is True
        assert len(fulfillment.subconditions) == 2
        assert isinstance(fulfillment.subconditions[1]['body'],
                          ThresholdSha256Fulfillment)
        assert isinstance(
            fulfillment.subconditions[1]['body'].subconditions[0]['body'],
            ThresholdSha256Fulfillment)

        fulfillment_uri = fulfillment.serialize_uri()
        deserialized_fulfillment = Fulfillment.from_uri(fulfillment_uri)

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

        assert deserialized_fulfillment.serialize_uri() == fulfillment_uri
        assert deserialized_fulfillment.validate(MESSAGE) is True
        assert deserialized_condition.serialize_uri() == condition_uri
示例#18
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)
示例#19
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
示例#20
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
示例#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 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)
                                  driver=bdb)

# 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
    }],