def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv,
                                             asset_definition):
    from cryptoconditions import Ed25519Sha256, ThresholdSha256
    from bigchaindb.common.transaction import Input, Output, Transaction

    threshold = ThresholdSha256(threshold=2)
    threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub)))
    threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub)))

    threshold_input = Input(threshold, [user_pub, user_pub])
    threshold_output = Output(threshold, [user_pub, user_pub])

    tx = Transaction(Transaction.CREATE, asset_definition, [threshold_input],
                     [threshold_output])
    expected = deepcopy(threshold_input)
    expected.fulfillment.subconditions[0]['body'].sign(
        str(tx).encode(), b58decode(user_priv))
    expected.fulfillment.subconditions[1]['body'].sign(
        str(tx).encode(), b58decode(user_priv))

    tx.sign([user_priv, user_priv])

    subconditions = tx.inputs[0].fulfillment.subconditions
    expected_subconditions = expected.fulfillment.subconditions
    assert subconditions[0]['body'].to_dict()['signature'] == \
        expected_subconditions[0]['body'].to_dict()['signature']
    assert subconditions[1]['body'].to_dict()['signature'] == \
        expected_subconditions[1]['body'].to_dict()['signature']

    assert tx.inputs[0].to_dict()['fulfillment'] == \
        expected.fulfillment.serialize_uri()
    assert tx.inputs_valid() is True
Example #2
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 = 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
Example #3
0
def test_generate_output_split_half_recursive(user_pub, user2_pub, user3_pub):
    from bigchaindb.common.transaction import Output
    from cryptoconditions import Ed25519Sha256, ThresholdSha256

    expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub))
    expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub))
    expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub))

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

    cond = Output.generate([user_pub, [user2_pub, expected_simple3]], 1)
    assert cond.fulfillment.to_dict() == expected.to_dict()
Example #4
0
def user_user2_threshold(user_pub, user2_pub):
    from cryptoconditions import ThresholdSha256, Ed25519Sha256
    user_pub_keys = [user_pub, user2_pub]
    threshold = ThresholdSha256(threshold=len(user_pub_keys))
    for user_pub in user_pub_keys:
        threshold.add_subfulfillment(
            Ed25519Sha256(public_key=b58decode(user_pub)))
    return threshold
Example #5
0
 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
Example #6
0
    def test_deserialize_unsigned_dict_to_fulfillment(self, vk_ilp):
        fulfillment = ThresholdSha256(threshold=1)
        fulfillment.add_subfulfillment(
            Ed25519Sha256(public_key=VerifyingKey(vk_ilp['b58'])))
        fulfillment.add_subfulfillment(
            Ed25519Sha256(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()
Example #7
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.ThresholdSha256`):
                    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.ThresholdSha256`:
        """
        try:
            threshold = len(new_public_keys)
        except TypeError:
            threshold = None

        if isinstance(new_public_keys, list) and len(new_public_keys) > 1:
            ffill = ThresholdSha256(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
            # 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.
            if isinstance(new_public_keys, Fulfillment):
                ffill = new_public_keys
            else:
                ffill = Ed25519Sha256(
                    public_key=base58.b58decode(new_public_keys))
        initial.add_subfulfillment(ffill)
        return initial
Example #8
0
    def generate(cls, public_keys, amount):
        """Generates a Output 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:
                public_keys (: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 Output.

            Returns:
                An Output that can be used in a Transaction.

            Raises:
                TypeError: If `public_keys` is not an instance of `list`.
                ValueError: If `public_keys` is an empty list.
        """
        threshold = len(public_keys)
        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(public_keys, list):
            raise TypeError('`public_keys` must be an instance of list')
        if len(public_keys) == 0:
            raise ValueError('`public_keys` needs to contain at least one'
                             'owner')
        elif len(public_keys) == 1 and not isinstance(public_keys[0], list):
            if isinstance(public_keys[0], Fulfillment):
                ffill = public_keys[0]
            else:
                ffill = Ed25519Sha256(
                    public_key=base58.b58decode(public_keys[0]))
            return cls(ffill, public_keys, amount=amount)
        else:
            initial_cond = ThresholdSha256(threshold=threshold)
            threshold_cond = reduce(cls._gen_condition, public_keys,
                                    initial_cond)
            return cls(threshold_cond, public_keys, amount=amount)
Example #9
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 = 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
Example #10
0
def sign_service(message, owner_priv_keys):
    """
    finalize the generated service message by adding condition attributes

    Args:
        message(dict) - a dictionary representing an unsigned attribute.
        owner_priv_keys([str]) - list of owner base58 private keys that will be used to create the conditions
        fulfillments([fulfillments]) -list of fulfillments needed to be fulfilled by the private keys
        returns :
            a message with fulfilled conditions representing a valid creation transaction
    raises:
        Invalid public private key pairing
        Insufficient private keys
    """
    fulfillment = None

    jsonMessage = json.dumps(
        message,
        sort_keys=True,
        separators=(',', ':'),
        ensure_ascii=False,
    )

    encoded_message = sha3.sha3_256(jsonMessage.encode())

    message['data']['fulfillment'] = {}

    if len(owner_priv_keys) == 1:
        fulfillment = ThresholdSha256(threshold=len(owner_priv_keys))
        message['data']['fulfillment']['type'] = ThresholdSha256.TYPE_NAME
        for key in owner_priv_keys:
            f = Ed25519Sha256()
            f.sign(encoded_message.digest(), base58.b58decode(key))
            fulfillment.add_subfulfillment(f)
    else:
        fulfillment = Ed25519Sha256()
        fulfillment.sign(encoded_message.digest(),
                         base58.b58decode(owner_priv_keys[0]))
        message['data']['fulfillment']['type'] = Ed25519Sha256.TYPE_NAME

    message['data']['fulfillment'][
        'fulfillment_uri'] = fulfillment.serialize_uri()
    message['id'] = encoded_message.hexdigest()
    return message
Example #11
0
def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv,
                                             asset_definition):
    from cryptoconditions import Ed25519Sha256, ThresholdSha256
    from bigchaindb.common.transaction import Input, Output, Transaction

    threshold = ThresholdSha256(threshold=2)
    threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub)))
    threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub)))

    threshold_input = Input(threshold, [user_pub, user_pub])
    threshold_output = Output(threshold, [user_pub, user_pub])

    tx = Transaction(Transaction.CREATE, asset_definition, [threshold_input],
                     [threshold_output])

    tx_dict = tx.to_dict()
    tx_dict['inputs'][0]['fulfillment'] = None
    serialized_tx = json.dumps(tx_dict,
                               sort_keys=True,
                               separators=(',', ':'),
                               ensure_ascii=True)
    message = sha3_256(serialized_tx.encode()).digest()

    expected = deepcopy(threshold_input)
    expected.fulfillment.subconditions[0]['body'].sign(message,
                                                       b58decode(user_priv))
    expected.fulfillment.subconditions[1]['body'].sign(message,
                                                       b58decode(user_priv))

    tx.sign([user_priv, user_priv])

    subconditions = tx.inputs[0].fulfillment.subconditions
    expected_subconditions = expected.fulfillment.subconditions
    assert subconditions[0]['body'].to_dict()['signature'] == \
        expected_subconditions[0]['body'].to_dict()['signature']
    assert subconditions[1]['body'].to_dict()['signature'] == \
        expected_subconditions[1]['body'].to_dict()['signature']

    assert tx.inputs[0].to_dict()['fulfillment'] == \
        expected.fulfillment.serialize_uri()
    assert tx.inputs_valid() is True
Example #12
0
def _fulfillment_from_details(data, _depth=0):
    """Load a fulfillment for a signing spec dictionary

    Args:
        data: tx.output[].condition.details dictionary
    """
    if _depth == 100:
        raise ThresholdTooDeep()

    if data['type'] == 'ed25519-sha-256':
        public_key = base58.b58decode(data['public_key'])
        return Ed25519Sha256(public_key=public_key)

    if data['type'] == 'threshold-sha-256':
        threshold = ThresholdSha256(data['threshold'])
        for cond in data['subconditions']:
            cond = _fulfillment_from_details(cond, _depth+1)
            threshold.add_subfulfillment(cond)
        return threshold

    raise UnsupportedTypeError(data.get('type'))
Example #13
0
def generate_service(service_key,
                     owner_keys,
                     auth_keys=[],
                     owners_authorize=True):
    """
    create a an unsigned service msg
    Args:
        service_keys ([str])- service denoted by base58 encoded keys
        owner_keys ([str]) - public keys recognizing ownership of the services and therefore administrators
        auth_keys ([str])- those who can give access to a resource. Generally owners must also be authorizers

        returns:
            a message without any signature or identity resolution
    """
    message = MessageShell.messageForType(MSGTYPE.REGISTER)
    message['data']['service'] = service_key
    message['data']['owners'] = owner_keys
    if owners_authorize:
        message['data']['authorities'] = owner_keys + auth_keys
    else:
        message['data']['authorities'] = auth_keys

    condition = None

    if len(owner_keys) != 1:
        condition = ThresholdSha256(threshold=len(owner_keys))
        for key in owner_keys:
            condition.add_subfulfillment(
                Ed25519Sha256(public_key=base58.b58decode(key)))
    else:
        condition = Ed25519Sha256(public_key=base58.b58decode(owner_keys[0]))

    message['data']['condition'] = condition.to_dict()
    message['data']['condition_uri'] = condition.condition_uri
    message['data']['fulfillment'] = None
    message['id'] = None

    return message
Example #14
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 = 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
Example #15
0
    def test_serialize_unsigned_dict_to_fulfillment(self, vk_ilp):
        fulfillment = ThresholdSha256(threshold=1)
        fulfillment.add_subfulfillment(
            Ed25519Sha256(public_key=VerifyingKey(vk_ilp['b58'])))
        fulfillment.add_subfulfillment(
            Ed25519Sha256(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}
Example #16
0
def test_permission_add_role(b):
    from .utils import create_simple_tx, post_tx, transfer_simple_tx, prepare_transfer, get_message_to_sign
    from bigchaindb.models import Transaction
    from cryptoconditions import ThresholdSha256, Ed25519Sha256, PreimageSha256
    from cryptoconditions.crypto import Ed25519VerifyingKey, Ed25519SigningKey

    # admin, albi, bruce
    admin_priv, admin_pub = crypto.generate_key_pair()
    albi_priv, albi_pub = crypto.generate_key_pair()
    bruce_priv, bruce_pub = crypto.generate_key_pair()

    assert len(b.get_owned_ids(admin_pub)) == 0
    assert len(b.get_owned_ids(albi_pub)) == 0
    assert len(b.get_owned_ids(bruce_pub)) == 0

    # admin CREATES role: tx_create_role, 202
    tx_create_role = Transaction.create(
        [admin_pub], [([admin_pub], 1)],
        asset={
            "policy": [
                {
                    "condition":
                    "transaction.operation == 'TRANSFER'",
                    "rule":
                    "transaction.inputs[0].owners_before[0] == '{}'".format(
                        admin_pub)
                },
            ]
        })
    # trick to not include in balance part 1
    tx_create_role.outputs[0].public_keys = []
    tx_create_role = tx_create_role.sign([admin_priv])
    response = post_tx(b, None, tx_create_role)
    tx_create_role_retrieved = b.get_transaction(tx_create_role.id)

    assert response.status_code == 202
    assert tx_create_role_retrieved.id == tx_create_role.id

    #  admin.unspents = [] # admin doesnt have role, only created it
    #  user_a.unspents = [] # user_a has no role
    #  user_b.unspents = [] # user_b has no role

    assert len(b.get_owned_ids(admin_pub)) == 0
    assert len(b.get_owned_ids(albi_pub)) == 0
    assert len(b.get_owned_ids(bruce_pub)) == 0

    # admin TRANSFERS tx_create_role TO user_a: tx_transfer_role_a, 202

    # tx_transfer_role_a = Transaction.transfer(
    #     [
    #         Input(
    #             fulfillment=Ed25519Sha256(
    #                 public_key=b58decode(admin_pub)),
    #             owners_before=[admin_pub], # trick to not include in balance part 2
    #             fulfills=TransactionLink(
    #                 txid=tx_create_role.id,
    #                 output=0)
    #             )
    #     ],
    #     [([albi_pub], 1)],
    #     tx_create_role.id)
    # tx_transfer_role_a = tx_transfer_role_a.sign([admin_priv])

    output_condition = ThresholdSha256(threshold=1)
    output_condition.add_subfulfillment(
        Ed25519Sha256(public_key=b58decode(admin_pub)))

    output_condition.add_subfulfillment(
        Ed25519Sha256(public_key=b58decode(albi_pub)))

    tx_transfer_role_a = prepare_transfer(inputs=[{
        'tx':
        tx_create_role.to_dict(),
        'output':
        0
    }],
                                          outputs=[
                                              {
                                                  'condition':
                                                  output_condition,
                                                  'public_keys': [albi_pub]
                                              },
                                          ])

    input_fulfillment = Ed25519Sha256(public_key=b58decode(admin_pub))
    tx_transfer_role_a.inputs[0].owners_before = [admin_pub]
    message_to_sign = get_message_to_sign(tx_transfer_role_a)
    input_fulfillment.sign(message_to_sign, b58decode(admin_priv))
    tx_transfer_role_a.inputs[0].fulfillment = input_fulfillment

    tx_transfer_role_a.validate(b)

    response = post_tx(b, None, tx_transfer_role_a)
    # tx_create_role_retrieved = b.get_transaction(tx_create_role.id)

    assert response.status_code == 202

    #  user_a.unspents = [tx_transfer_role_a] # user_a has role
    assert len(b.get_owned_ids(admin_pub)) == 0
    assert len(b.get_owned_ids(albi_pub)) == 1
    assert len(b.get_owned_ids(bruce_pub)) == 0

    # user TRANSFERS tx_transfer_role_a TO user_b: -, 400 # only admin can assign role
    tx_transfer_role_b = prepare_transfer(
        inputs=[{
            'tx': tx_transfer_role_a.to_dict(),
            'output': 0
        }],
        outputs=[
            {
                'condition': Ed25519Sha256(public_key=b58decode(bruce_pub)),
            },
        ])

    tx_transfer_role_b.inputs[0].owners_before = [albi_pub]

    message_to_sign = get_message_to_sign(tx_transfer_role_b)
    input_fulfillment = ThresholdSha256(threshold=1)
    albi_fulfillment = Ed25519Sha256(public_key=b58decode(albi_pub))
    albi_fulfillment.sign(message_to_sign, b58decode(albi_priv))

    input_fulfillment.add_subfulfillment(albi_fulfillment)
    input_fulfillment.add_subcondition(
        Ed25519Sha256(public_key=b58decode(admin_pub)).condition_uri)
    tx_transfer_role_b.inputs[0].fulfillment = input_fulfillment
    input_fulfillment.serialize_uri()
    tx_transfer_role_b.validate(b)

    response = post_tx(b, None, tx_transfer_role_b)

    assert response.status_code == 202

    #  user_a.unspents = [tx_transfer_role_a] # user_a has role
    #  user_b.unspents = [] # user_b has no role
    assert len(b.get_owned_ids(admin_pub)) == 0
    assert len(b.get_owned_ids(albi_pub)) == 0
    assert len(b.get_owned_ids(bruce_pub)) == 0