Beispiel #1
0
    def from_dict(cls, data):
        """Transforms a Python dictionary to an Input object.

            Note:
                Optionally, this method can also serialize a Cryptoconditions-
                Fulfillment that is not yet signed.

            Args:
                data (dict): The Input to be transformed.

            Returns:
                :class:`~bigchaindb.common.transaction.Input`

            Raises:
                InvalidSignature: If an Input's URI couldn't be parsed.
        """
        try:
            fulfillment = Fulfillment.from_uri(data['fulfillment'])
        except ValueError:
            # TODO FOR CC: Throw an `InvalidSignature` error in this case.
            raise InvalidSignature("Fulfillment URI couldn't been parsed")
        except TypeError:
            # NOTE: See comment about this special case in
            #       `Input.to_dict`
            fulfillment = Fulfillment.from_dict(data['fulfillment'])
        fulfills = TransactionLink.from_dict(data['fulfills'])
        return cls(fulfillment, data['owners_before'], fulfills)
Beispiel #2
0
    def from_dict(cls, data):
        """Transforms a Python dictionary to an Input object.

            Note:
                Optionally, this method can also serialize a Cryptoconditions-
                Fulfillment that is not yet signed.

            Args:
                data (dict): The Input to be transformed.

            Returns:
                :class:`~bigchaindb.common.transaction.Input`

            Raises:
                InvalidSignature: If an Input's URI couldn't be parsed.
        """
        fulfillment = data['fulfillment']
        if not isinstance(fulfillment, Fulfillment):
            try:
                fulfillment = Fulfillment.from_uri(data['fulfillment'])
            except ASN1DecodeError:
                # TODO Remove as it is legacy code, and simply fall back on
                # ASN1DecodeError
                raise InvalidSignature("Fulfillment URI couldn't been parsed")
            except TypeError:
                # NOTE: See comment about this special case in
                #       `Input.to_dict`
                fulfillment = Fulfillment.from_dict(data['fulfillment'])
        fulfills = TransactionLink.from_dict(data['fulfills'])
        return cls(fulfillment, data['owners_before'], fulfills)
Beispiel #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)
Beispiel #4
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)
 def test_from_binary_with_invalid_value(self, fulfillment, error):
     from cryptoconditions import Fulfillment
     from cryptoconditions.exceptions import ASN1DecodeError
     with pytest.raises(ASN1DecodeError) as exc:
         Fulfillment.from_binary(fulfillment)
     assert exc.value.args == ('Failed to decode fulfillment.',)
     assert isinstance(exc.value.__cause__, error)
Beispiel #6
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
    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 = ThresholdSha256(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, ThresholdSha256)
        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(Ed25519Sha256(public_key=VerifyingKey(vk_ilp['b58'])))

        assert fulfillment.validate(MESSAGE) == True
Beispiel #8
0
    def from_dict(cls, ffill):
        """Transforms a Python dictionary to a Fulfillment object.

            Note:
                Optionally, this method can also serialize a Cryptoconditions-
                Fulfillment that is not yet signed.

            Args:
                ffill (dict): The Fulfillment to be transformed.

            Returns:
                :class:`~bigchaindb.common.transaction.Fulfillment`

            Raises:
                InvalidSignature: If a Fulfillment's URI couldn't be parsed.
        """
        try:
            fulfillment = CCFulfillment.from_uri(ffill['fulfillment'])
        except ValueError:
            # TODO FOR CC: Throw an `InvalidSignature` error in this case.
            raise InvalidSignature("Fulfillment URI couldn't been parsed")
        except TypeError:
            # NOTE: See comment about this special case in
            #       `Fulfillment.to_dict`
            fulfillment = CCFulfillment.from_dict(ffill['fulfillment'])
        input_ = TransactionLink.from_dict(ffill['input'])
        return cls(fulfillment, ffill['owners_before'], input_)
Beispiel #9
0
 def test_from_binary_with_invalid_value(self, fulfillment, error):
     from cryptoconditions import Fulfillment
     from cryptoconditions.exceptions import ASN1DecodeError
     with pytest.raises(ASN1DecodeError) as exc:
         Fulfillment.from_binary(fulfillment)
     assert exc.value.args == ('Failed to decode fulfillment.', )
     assert isinstance(exc.value.__cause__, error)
Beispiel #10
0
def test_input_deserialization_with_unsigned_fulfillment(ffill_uri, user_pub):
    from bigchaindb.common.transaction import Input
    from cryptoconditions import Fulfillment

    expected = Input(Fulfillment.from_uri(ffill_uri), [user_pub])
    ffill = {
        'owners_before': [user_pub],
        'fulfillment': Fulfillment.from_uri(ffill_uri),
        'fulfills': None,
    }
    input = Input.from_dict(ffill)

    assert input == expected
def test_fulfillment_deserialization_with_unsigned_fulfillment(ffill_uri,
                                                               user_pub):
    from bigchaindb_common.transaction import Fulfillment
    from cryptoconditions import Fulfillment as CCFulfillment

    expected = Fulfillment(CCFulfillment.from_uri(ffill_uri), [user_pub])
    ffill = {
        'owners_before': [user_pub],
        'fulfillment': CCFulfillment.from_uri(ffill_uri),
        'input': None,
    }
    ffill = Fulfillment.from_dict(ffill)

    assert ffill == expected
    def test_deserialize_signed_dict_to_fulfillment(self, fulfillment_ed25519):
        fulfillment = Fulfillment.from_uri(fulfillment_ed25519['fulfillment_uri'])
        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())

        assert parsed_fulfillment.serialize_uri() == fulfillment_ed25519['fulfillment_uri']
        assert parsed_fulfillment.condition.serialize_uri() == fulfillment.condition.serialize_uri()
        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
    def test_fulfillment_serialize_to_dict(self, fulfillment_sha256):
        fulfillment = Fulfillment.from_uri(fulfillment_sha256['fulfillment_uri'])
        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())

        assert parsed_fulfillment.serialize_uri() == fulfillment.serialize_uri()
        assert parsed_fulfillment.condition.serialize_uri() == fulfillment.condition.serialize_uri()
        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
Beispiel #14
0
    def from_dict(cls, data):
        """Transforms a Python dictionary to an Input object.

            Note:
                Optionally, this method can also serialize a Cryptoconditions-
                Fulfillment that is not yet signed.

            Args:
                data (dict): The Input to be transformed.

            Returns:
                :class:`~bigchaindb.common.transaction.Input`

            Raises:
                InvalidSignature: If an Input's URI couldn't be parsed.
        """
        fulfillment = data['fulfillment']
        if not isinstance(fulfillment, Fulfillment):
            try:
                fulfillment = Fulfillment.from_uri(data['fulfillment'])
            except ASN1DecodeError:
                # TODO Remove as it is legacy code, and simply fall back on
                # ASN1DecodeError
                raise InvalidSignature("Fulfillment URI couldn't been parsed")
            except TypeError:
                # NOTE: See comment about this special case in
                #       `Input.to_dict`
                fulfillment = _fulfillment_from_details(data['fulfillment'])
        fulfills = TransactionLink.from_dict(data['fulfills'])
        return cls(fulfillment, data['owners_before'], fulfills)
Beispiel #15
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)
Beispiel #16
0
    def from_dict(cls, data):
        """Transforms a Python dictionary to an Output object.

            Note:
                To pass a serialization cycle multiple times, a
                Cryptoconditions Fulfillment needs to be present in the
                passed-in dictionary, as Condition URIs are not serializable
                anymore.

            Args:
                data (dict): The dict to be transformed.

            Returns:
                :class:`~bigchaindb.common.transaction.Output`
        """
        try:
            fulfillment = Fulfillment.from_dict(data['condition']['details'])
        except KeyError:
            # NOTE: Hashlock condition case
            fulfillment = data['condition']['uri']
        try:
            amount = int(data['amount'])
        except ValueError:
            raise AmountError('Invalid amount: %s' % data['amount'])
        return cls(fulfillment, data['public_keys'], amount)
Beispiel #17
0
    def from_dict(cls, data):
        """Transforms a Python dictionary to an Output object.

            Note:
                To pass a serialization cycle multiple times, a
                Cryptoconditions Fulfillment needs to be present in the
                passed-in dictionary, as Condition URIs are not serializable
                anymore.

            Args:
                data (dict): The dict to be transformed.

            Returns:
                :class:`~bigchaindb.common.transaction.Output`
        """
        try:
            fulfillment = Fulfillment.from_dict(data['condition']['details'])
        except KeyError:
            # NOTE: Hashlock condition case
            fulfillment = data['condition']['uri']
        try:
            amount = int(data['amount'])
        except ValueError:
            raise AmountError('Invalid amount: %s' % data['amount'])
        return cls(fulfillment, data['public_keys'], amount)
Beispiel #18
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
Beispiel #19
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
Beispiel #20
0
    def test_deserialize_and_validate_fulfillment(self, fulfillment_sha256):
        fulfillment = Fulfillment.from_uri(
            fulfillment_sha256['fulfillment_uri'])

        assert fulfillment.serialize_uri(
        ) == fulfillment_sha256['fulfillment_uri']
        assert fulfillment.condition.serialize_uri(
        ) == fulfillment_sha256['condition_uri']
        assert fulfillment.validate()
Beispiel #21
0
    def test_deserialize_signed_dict_to_fulfillment(self, fulfillment_ed25519):
        fulfillment = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])
        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())

        assert parsed_fulfillment.serialize_uri(
        ) == fulfillment_ed25519['fulfillment_uri']
        assert parsed_fulfillment.condition.serialize_uri(
        ) == fulfillment.condition.serialize_uri()
        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
    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 = ThresholdSha256(threshold=2)
        fulfillment.add_subfulfillment(ilp_fulfillment_sha)

        assert fulfillment.validate(MESSAGE) is False

        # 1-of-2 (OR with 2 inputs)
        nested_fulfillment = ThresholdSha256(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, ThresholdSha256)
        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
Beispiel #23
0
    def test_fulfillment_serialize_to_dict(self, fulfillment_sha256):
        fulfillment = Fulfillment.from_uri(
            fulfillment_sha256['fulfillment_uri'])
        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())

        assert parsed_fulfillment.serialize_uri() == fulfillment.serialize_uri(
        )
        assert parsed_fulfillment.condition.serialize_uri(
        ) == fulfillment.condition.serialize_uri()
        assert parsed_fulfillment.to_dict() == fulfillment.to_dict()
def test_fulfillment_serialization(ffill_uri, user_pub):
    from bigchaindb_common.transaction import Fulfillment
    from cryptoconditions import Fulfillment as CCFulfillment

    expected = {
        'owners_before': [user_pub],
        'fulfillment': ffill_uri,
        'input': None,
    }
    ffill = Fulfillment(CCFulfillment.from_uri(ffill_uri), [user_pub])
    assert ffill.to_dict() == expected
Beispiel #25
0
def test_input_serialization(ffill_uri, user_pub):
    from bigchaindb.common.transaction import Input
    from cryptoconditions import Fulfillment

    expected = {
        'owners_before': [user_pub],
        'fulfillment': ffill_uri,
        'fulfills': None,
    }
    input = Input(Fulfillment.from_uri(ffill_uri), [user_pub])
    assert input.to_dict() == expected
    def test_serialize_signed_dict_to_fulfillment(self, fulfillment_ed25519):
        fulfillment = Fulfillment.from_uri(fulfillment_ed25519['fulfillment_uri'])

        assert fulfillment.to_dict()== \
            {'bitmask': 32,
             'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
             'signature': '4eCt6SFPCzLQSAoQGW7CTu3MHdLj6FezSpjktE7tHsYGJ4pNSUnpHtV9XgdHF2XYd62M9fTJ4WYdhTVck27qNoHj',
             'type': 'fulfillment',
             'type_id': 4}

        assert fulfillment.validate(MESSAGE) == True
Beispiel #27
0
    def test_serialize_signed_dict_to_fulfillment(self, fulfillment_ed25519):
        fulfillment = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])

        assert fulfillment.to_dict()== \
            {'bitmask': 32,
             'public_key': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
             'signature': '4eCt6SFPCzLQSAoQGW7CTu3MHdLj6FezSpjktE7tHsYGJ4pNSUnpHtV9XgdHF2XYd62M9fTJ4WYdhTVck27qNoHj',
             'type': 'fulfillment',
             'type_id': 4}

        assert fulfillment.validate(MESSAGE) == True
Beispiel #28
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
Beispiel #29
0
    def test_deserialize_fulfillment(self, vk_ilp, fulfillment_ed25519):
        fulfillment = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])

        assert isinstance(fulfillment, Ed25519Fulfillment)
        assert fulfillment.serialize_uri(
        ) == fulfillment_ed25519['fulfillment_uri']
        assert fulfillment.condition.serialize_uri(
        ) == fulfillment_ed25519['condition_uri']
        assert binascii.hexlify(fulfillment.condition.hash
                                ) == fulfillment_ed25519['condition_hash']
        assert fulfillment.public_key.encode(encoding='hex') == vk_ilp['hex']
        assert fulfillment.validate(MESSAGE)
Beispiel #30
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
    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 = ThresholdSha256(threshold=2)
        fulfillment.add_subfulfillment(ilp_fulfillment_sha)

        max_depth = 6

        def add_nested_fulfillment(parent, current_depth=0):
            current_depth += 1
            child = ThresholdSha256(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'], ThresholdSha256)
        assert isinstance(fulfillment.subconditions[1]['body'].subconditions[0]['body'], ThresholdSha256)

        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
def verify_signature():
    if request.method == 'POST':
        request_json = json.loads(request.get_data())
        # print(request_json['message'])
        request_json['type'] = 'ed25519-sha-256'
        fulfillment_object = Fulfillment.from_dict(request_json)
        encoded_message = sha3_256(request_json['message'].encode()).digest()
        # print(request_json['hash'])
        decoded_message = bytes.fromhex(request_json['hash'])
        # response = {"result": fulfillment_object.validate(message=encoded_message)}
        response = {
            "result": fulfillment_object.validate(message=decoded_message)
        }
        return json.dumps(response)
def test_fulfill_transaction(alice_transaction, alice_sk):
    from bigchaindb_driver.offchain import fulfill_transaction
    fulfilled_transaction = fulfill_transaction(alice_transaction,
                                                private_keys=alice_sk)
    inputs = fulfilled_transaction['inputs']
    assert len(inputs) == 1
    alice_transaction['inputs'][0]['fulfillment'] = None
    message = rapidjson.dumps(
        alice_transaction,
        skipkeys=False,
        ensure_ascii=False,
        sort_keys=True,
    ).encode()
    fulfillment_uri = inputs[0]['fulfillment']
    assert Fulfillment.from_uri(fulfillment_uri).validate(message=message)
Beispiel #34
0
    def _input_valid(self,
                     input_,
                     operation,
                     message,
                     output_condition_uri=None):
        """Validates a single Input against a single Output.

            Note:
                In case of a `CREATE` Transaction, this method
                does not validate against `output_condition_uri`.

            Args:
                input_ (:class:`~bigchaindb.common.transaction.
                    Input`) The Input to be signed.
                operation (str): The type of Transaction.
                message (str): The fulfillment message.
                output_condition_uri (str, optional): An Output to check the
                    Input against.

            Returns:
                bool: If the Input is valid.
        """
        ccffill = input_.fulfillment
        try:
            parsed_ffill = Fulfillment.from_uri(ccffill.serialize_uri())
        except (TypeError, ValueError, ParsingError, ASN1DecodeError,
                ASN1EncodeError):
            return False

        if operation == self.CREATE:
            # NOTE: In the case of a `CREATE` transaction, the
            #       output is always valid.
            output_valid = True
        else:
            output_valid = output_condition_uri == ccffill.condition_uri

        message = sha3_256(message.encode())
        if input_.fulfills:
            message.update('{}{}'.format(input_.fulfills.txid,
                                         input_.fulfills.output).encode())

        # NOTE: We pass a timestamp to `.validate`, as in case of a timeout
        #       condition we'll have to validate against it

        # cryptoconditions makes no assumptions of the encoding of the
        # message to sign or verify. It only accepts bytestrings
        ffill_valid = parsed_ffill.validate(message=message.digest())
        return output_valid and ffill_valid
Beispiel #35
0
    def test_serialize_condition_and_validate_fulfillment(
            self, fulfillment_ed25519):
        ilp_fulfillment_ed = Fulfillment.from_uri(
            fulfillment_ed25519['fulfillment_uri'])

        fulfillment = InvertedThresholdSha256Fulfillment(threshold=1)
        fulfillment.add_subfulfillment(ilp_fulfillment_ed)
        parsed_fulfillment = fulfillment.from_dict(fulfillment.to_dict())

        assert parsed_fulfillment.condition_uri == fulfillment.condition_uri
        assert parsed_fulfillment.serialize_uri() == fulfillment.serialize_uri(
        )
        assert parsed_fulfillment.validate(MESSAGE) is False
        assert parsed_fulfillment.validate() is True
        assert isinstance(parsed_fulfillment,
                          InvertedThresholdSha256Fulfillment)
Beispiel #36
0
    def test_deserialize_fulfillment(self, fulfillment_threshold):
        num_fulfillments = 2
        threshold = 1

        fulfillment = Fulfillment.from_uri(
            fulfillment_threshold['fulfillment_uri'])

        assert isinstance(fulfillment, ThresholdSha256Fulfillment)
        assert fulfillment.threshold == threshold
        assert len([
            f for f in fulfillment.subconditions if f['type'] == 'fulfillment'
        ]) == threshold
        assert fulfillment.serialize_uri(
        ) == fulfillment_threshold['fulfillment_uri']
        assert len(fulfillment.subconditions) == num_fulfillments
        assert fulfillment.validate(MESSAGE)
Beispiel #37
0
    def _input_valid(input_, operation, tx_serialized, output_condition_uri=None):
        """Validates a single Input against a single Output.

            Note:
                In case of a `CREATE` or `GENESIS` Transaction, this method
                does not validate against `output_condition_uri`.

            Args:
                input_ (:class:`~bigchaindb.common.transaction.
                    Input`) The Input to be signed.
                operation (str): The type of Transaction.
                tx_serialized (str): The Transaction used as a message when
                    initially signing it.
                output_condition_uri (str, optional): An Output to check the
                    Input against.

            Returns:
                bool: If the Input is valid.
        """
        ccffill = input_.fulfillment
        try:
            parsed_ffill = Fulfillment.from_uri(ccffill.serialize_uri())
        except (TypeError, ValueError,
                ParsingError, ASN1DecodeError, ASN1EncodeError):
            return False

        if operation in (Transaction.CREATE, Transaction.GENESIS):
            # NOTE: In the case of a `CREATE` or `GENESIS` transaction, the
            #       output is always valid.
            output_valid = True
        else:
            output_valid = output_condition_uri == ccffill.condition_uri

        # NOTE: We pass a timestamp to `.validate`, as in case of a timeout
        #       condition we'll have to validate against it

        # cryptoconditions makes no assumptions of the encoding of the
        # message to sign or verify. It only accepts bytestrings
        try:
            # the validation of RSA in cryptoconditions should return a boolean
            # but instead raises and exception in case of an invalid signature
            ffill_valid = parsed_ffill.validate(message=tx_serialized.encode())
        except ValidationError:
            ffill_valid = False
        return output_valid and ffill_valid
def verify(reading_id):
    transaction = transactions.find_one({"id": reading_id})
    reading = collection.find_one({"id": reading_id})
    formatted_reading = format_reading(reading)
    public_key = transaction['outputs'][0]['condition']['details'][
        'public_key']
    uri = transaction['outputs'][0]['condition']['uri']
    fulfillment = Fulfillment.from_uri(
        transaction['inputs'][0]['fulfillment']).to_dict()
    print(fulfillment)
    signature = fulfillment['signature']
    message = generate_message(reading['data'], public_key, uri)
    return json.dumps({
        "reading": formatted_reading,
        "message": str(message),
        "public_key": str(public_key),
        "signature": str(signature)
    })
Beispiel #39
0
    def CREATETransactionFromDict(cls, dictionary):
        transaction = Transaction()
        try:
            if dictionary["data"]["condition"][
                    "type"] == Ed25519Sha256.TYPE_NAME:
                transaction.condition = dictionary['data']["condition_uri"]
            elif dictionary["data"]["condition"][
                    "type"] == ThresholdSha256.TYPE_NAME:
                transaction.condition = dictionary['data']["condition_uri"]
            else:
                raise InvalidCreateTransaction()

            transaction.fulfillment = Fulfillment.from_uri(
                dictionary["data"]["fulfillment"]["fulfillment_uri"])
            transaction.id = dictionary["id"]
        except:
            raise InvalidCreateTransaction()
        return transaction
Beispiel #40
0
    def _input_valid(input_, operation, message, output_condition_uri=None):
        """Validates a single Input against a single Output.

            Note:
                In case of a `CREATE` or `GENESIS` Transaction, this method
                does not validate against `output_condition_uri`.

            Args:
                input_ (:class:`~bigchaindb.common.transaction.
                    Input`) The Input to be signed.
                operation (str): The type of Transaction.
                message (str): The fulfillment message.
                output_condition_uri (str, optional): An Output to check the
                    Input against.

            Returns:
                bool: If the Input is valid.
        """
        ccffill = input_.fulfillment
        try:
            parsed_ffill = Fulfillment.from_uri(ccffill.serialize_uri())
        except (TypeError, ValueError,
                ParsingError, ASN1DecodeError, ASN1EncodeError):
            return False

        if operation in (Transaction.CREATE, Transaction.GENESIS):
            # NOTE: In the case of a `CREATE` or `GENESIS` transaction, the
            #       output is always valid.
            output_valid = True
        else:
            output_valid = output_condition_uri == ccffill.condition_uri

        message = sha3_256(message.encode())
        if input_.fulfills:
            message.update('{}{}'.format(
                input_.fulfills.txid, input_.fulfills.output).encode())

        # NOTE: We pass a timestamp to `.validate`, as in case of a timeout
        #       condition we'll have to validate against it

        # cryptoconditions makes no assumptions of the encoding of the
        # message to sign or verify. It only accepts bytestrings
        ffill_valid = parsed_ffill.validate(message=message.digest())
        return output_valid and ffill_valid
    def test_serialize_signed_dict_to_fulfillment(self, fulfillment_threshold):
        fulfillment = Fulfillment.from_uri(fulfillment_threshold['fulfillment_uri'])

        assert fulfillment.to_dict() == \
            {'bitmask': 43,
             'subfulfillments': [{'bitmask': 3,
                                  'preimage': '',
                                  'type': 'fulfillment',
                                  'type_id': 0,
                                  'weight': 1},
                                 {'bitmask': 32,
                                  'hash': 'Gtbi6WQDB6wUePiZm8aYs5XZ5pUqx9jMMLvRVHPESTjU',
                                  'max_fulfillment_length': 96,
                                  'type': 'condition',
                                  'type_id': 4,
                                  'weight': 1}],
             'threshold': 1,
             'type': 'fulfillment',
             'type_id': 2}
Beispiel #42
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)
Beispiel #43
0
    def _input_valid(input_,
                     operation,
                     tx_serialized,
                     output_condition_uri=None):
        """Validates a single Input against a single Output.

            Note:
                In case of a `CREATE` or `GENESIS` Transaction, this method
                does not validate against `output_condition_uri`.

            Args:
                input_ (:class:`~bigchaindb.common.transaction.
                    Input`) The Input to be signed.
                operation (str): The type of Transaction.
                tx_serialized (str): The Transaction used as a message when
                    initially signing it.
                output_condition_uri (str, optional): An Output to check the
                    Input against.

            Returns:
                bool: If the Input is valid.
        """
        ccffill = input_.fulfillment
        try:
            parsed_ffill = Fulfillment.from_uri(ccffill.serialize_uri())
        except (TypeError, ValueError, ParsingError, ASN1DecodeError,
                ASN1EncodeError):
            return False

        if operation in (Transaction.CREATE, Transaction.GENESIS):
            # NOTE: In the case of a `CREATE` or `GENESIS` transaction, the
            #       output is always valid.
            output_valid = True
        else:
            output_valid = output_condition_uri == ccffill.condition_uri

        # NOTE: We pass a timestamp to `.validate`, as in case of a timeout
        #       condition we'll have to validate against it

        # cryptoconditions makes no assumptions of the encoding of the
        # message to sign or verify. It only accepts bytestrings
        ffill_valid = parsed_ffill.validate(message=tx_serialized.encode())
        return output_valid and ffill_valid
Beispiel #44
0
    def from_dict(cls, cond):
        """Transforms a Python dictionary to a Condition object.

            Note:
                To pass a serialization cycle multiple times, a
                Cryptoconditions Fulfillment needs to be present in the
                passed-in dictionary, as Condition URIs are not serializable
                anymore.

            Args:
                cond (dict): The Condition to be transformed.

            Returns:
                :class:`~bigchaindb.common.transaction.Condition`
        """
        try:
            fulfillment = CCFulfillment.from_dict(cond['condition']['details'])
        except KeyError:
            # NOTE: Hashlock condition case
            fulfillment = cond['condition']['uri']
        return cls(fulfillment, cond['owners_after'], cond['amount'])
Beispiel #45
0
    def _fulfillment_valid(fulfillment, operation, tx_serialized,
                           input_condition_uri=None):
        """Validates a single Fulfillment against a single Condition.

            Note:
                In case of a `CREATE` or `GENESIS` Transaction, this method
                does not validate against `input_condition_uri`.

            Args:
                fulfillment (:class:`~bigchaindb.common.transaction.
                    Fulfillment`) The Fulfillment to be signed.
                operation (str): The type of Transaction.
                tx_serialized (str): The Transaction used as a message when
                    initially signing it.
                input_condition_uri (str, optional): A Condition to check the
                    Fulfillment against.

            Returns:
                bool: If the Fulfillment is valid.
        """
        ccffill = fulfillment.fulfillment
        try:
            parsed_ffill = CCFulfillment.from_uri(ccffill.serialize_uri())
        except (TypeError, ValueError, ParsingError):
            return False

        if operation in (Transaction.CREATE, Transaction.GENESIS):
            # NOTE: In the case of a `CREATE` or `GENESIS` transaction, the
            #       input condition is always validate to `True`.
            input_cond_valid = True
        else:
            input_cond_valid = input_condition_uri == ccffill.condition_uri

        # NOTE: We pass a timestamp to `.validate`, as in case of a timeout
        #       condition we'll have to validate against it

        # cryptoconditions makes no assumptions of the encoding of the
        # message to sign or verify. It only accepts bytestrings
        return parsed_ffill.validate(message=tx_serialized.encode(),
                                     now=gen_timestamp()) and input_cond_valid
 def test_from_uri_with_invalid_type(self):
     from cryptoconditions import Fulfillment
     with pytest.raises(TypeError) as exc:
         Fulfillment.from_uri(123)
     assert exc.value.args == ('Serialized fulfillment must be a string',)
 def test_condition_binary(self, test_vector):
     from cryptoconditions import Fulfillment
     fulfillment = Fulfillment.from_uri(test_vector.fulfillment)
     assert fulfillment.condition_binary == test_vector.condition_binary