def test_add_condition_to_tx(user_cond):
    from bigchaindb_common.transaction import Transaction, Asset

    tx = Transaction(Transaction.CREATE, Asset())
    tx.add_condition(user_cond)

    assert len(tx.conditions) == 1
def test_transaction_serialization(user_ffill, user_cond, data, data_id):
    from bigchaindb_common.transaction import Transaction, Asset

    tx_id = 'l0l'
    timestamp = '66666666666'

    expected = {
        'id': tx_id,
        'version': Transaction.VERSION,
        'transaction': {
            # NOTE: This test assumes that Fulfillments and Conditions can
            #       successfully be serialized
            'fulfillments': [user_ffill.to_dict(0)],
            'conditions': [user_cond.to_dict(0)],
            'operation': Transaction.CREATE,
            'timestamp': timestamp,
            'metadata': None,
            'asset': {
                'id': data_id,
                'divisible': False,
                'updatable': False,
                'refillable': False,
                'data': data,
            }
        }
    }

    tx = Transaction(Transaction.CREATE, Asset(data, data_id), [user_ffill],
                     [user_cond])
    tx_dict = tx.to_dict()
    tx_dict['id'] = tx_id
    tx_dict['transaction']['asset']['id'] = data_id
    tx_dict['transaction']['timestamp'] = timestamp

    assert tx_dict == expected
def test_add_fulfillment_to_tx(user_ffill):
    from bigchaindb_common.transaction import Transaction, Asset

    tx = Transaction(Transaction.CREATE, Asset(), [], [])
    tx.add_fulfillment(user_ffill)

    assert len(tx.fulfillments) == 1
def test_transaction_deserialization(user_ffill, user_cond, data, data_id):
    from bigchaindb_common.transaction import Transaction, Asset

    timestamp = '66666666666'

    expected_asset = Asset(data, data_id)
    expected = Transaction(Transaction.CREATE, expected_asset, [user_ffill],
                           [user_cond], None, timestamp, Transaction.VERSION)

    tx = {
        'version': Transaction.VERSION,
        'transaction': {
            # NOTE: This test assumes that Fulfillments and Conditions can
            #       successfully be serialized
            'fulfillments': [user_ffill.to_dict()],
            'conditions': [user_cond.to_dict()],
            'operation': Transaction.CREATE,
            'timestamp': timestamp,
            'metadata': None,
            'asset': {
                'id': data_id,
                'divisible': False,
                'updatable': False,
                'refillable': False,
                'data': data,
            }
        }
    }
    tx_no_signatures = Transaction._remove_signatures(tx)
    tx['id'] = Transaction._to_hash(Transaction._to_str(tx_no_signatures))
    tx = Transaction.from_dict(tx)

    assert tx == expected
def test_invalid_transaction_initialization():
    from bigchaindb_common.transaction import Transaction, Asset

    with raises(ValueError):
        Transaction(operation='invalid operation', asset=Asset())
    with raises(TypeError):
        Transaction(operation='CREATE', asset='invalid asset')
    with raises(TypeError):
        Transaction(
            operation='CREATE',
            asset=Asset(),
            conditions='invalid conditions'
        )
    with raises(TypeError):
        Transaction(
            operation='CREATE',
            asset=Asset(),
            conditions=[],
            fulfillments='invalid fulfillments'
        )
    with raises(TypeError):
        Transaction(
            operation='CREATE',
            asset=Asset(),
            conditions=[],
            fulfillments=[],
            metadata='invalid metadata'
        )
def test_validate_multiple_fulfillments(user_ffill, user_cond, user_priv):
    from copy import deepcopy

    from bigchaindb_common.crypto import SigningKey
    from bigchaindb_common.transaction import Transaction, Asset

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

    expected_first = deepcopy(tx)
    expected_second = deepcopy(tx)
    expected_first.fulfillments = [expected_first.fulfillments[0]]
    expected_first.conditions = [expected_first.conditions[0]]
    expected_second.fulfillments = [expected_second.fulfillments[1]]
    expected_second.conditions = [expected_second.conditions[1]]

    expected_first_bytes = str(expected_first).encode()
    expected_first.fulfillments[0].fulfillment.sign(expected_first_bytes,
                                                    SigningKey(user_priv))
    expected_second_bytes = str(expected_second).encode()
    expected_second.fulfillments[0].fulfillment.sign(expected_second_bytes,
                                                     SigningKey(user_priv))
    tx.sign([user_priv])

    assert tx.fulfillments[0].to_dict()['fulfillment'] == \
        expected_first.fulfillments[0].fulfillment.serialize_uri()
    assert tx.fulfillments[1].to_dict()['fulfillment'] == \
        expected_second.fulfillments[0].fulfillment.serialize_uri()
    assert tx.fulfillments_valid() is True
def test_validate_fulfillment_with_invalid_parameters(utx):
    from bigchaindb_common.transaction import Transaction

    input_conditions = [cond.fulfillment.condition_uri for cond
                        in utx.conditions]
    tx_dict = utx.to_dict()
    tx_dict = Transaction._remove_signatures(tx_dict)
    tx_serialized = Transaction._to_str(tx_dict)
    assert utx._fulfillment_valid(utx.fulfillments[0],
                                  tx_serialized,
                                  input_conditions) is False
def test_validate_tx_simple_create_signature(user_ffill, user_cond, user_priv):
    from copy import deepcopy
    from bigchaindb_common.crypto import SigningKey
    from bigchaindb_common.transaction import Transaction, Asset

    tx = Transaction(Transaction.CREATE, Asset(), [user_ffill], [user_cond])
    expected = deepcopy(user_cond)
    expected.fulfillment.sign(str(tx).encode(), SigningKey(user_priv))
    tx.sign([user_priv])

    assert tx.fulfillments[0].to_dict()['fulfillment'] == \
        expected.fulfillment.serialize_uri()
    assert tx.fulfillments_valid() is True
def test_multiple_fulfillment_validation_of_transfer_tx(user_ffill, user_cond,
                                                        user_priv, user2_pub,
                                                        user2_priv, user3_pub,
                                                        user3_priv):
    from copy import deepcopy
    from bigchaindb_common.transaction import (Transaction, TransactionLink,
                                               Fulfillment, Condition, Asset)
    from cryptoconditions import Ed25519Fulfillment

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

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

    assert transfer_tx.fulfillments_valid(tx.conditions) is True
def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
                                               user2_cond, user_priv, data_id):
    from copy import deepcopy
    from bigchaindb_common.crypto import SigningKey
    from bigchaindb_common.transaction import Transaction, Asset
    from bigchaindb_common.util import serialize

    expected = {
        'transaction': {
            'conditions': [user2_cond.to_dict(0)],
            'metadata': None,
            'asset': {
                'id': data_id,
            },
            'fulfillments': [
                {
                    'owners_before': [
                        user_pub
                    ],
                    'fid': 0,
                    'fulfillment': None,
                    'input': {
                        'txid': tx.id,
                        'cid': 0
                    }
                }
            ],
            'operation': 'TRANSFER',
        },
        'version': 1
    }
    inputs = tx.to_inputs([0])
    asset = Asset(None, data_id)
    transfer_tx = Transaction.transfer(inputs, [user2_pub], asset=asset)
    transfer_tx = transfer_tx.sign([user_priv])
    transfer_tx = transfer_tx.to_dict()
    transfer_tx_body = transfer_tx['transaction']

    expected_input = deepcopy(inputs[0])
    expected['id'] = transfer_tx['id']
    expected['transaction']['timestamp'] = transfer_tx_body['timestamp']
    expected_input.fulfillment.sign(serialize(expected).encode(),
                                    SigningKey(user_priv))
    expected_ffill = expected_input.fulfillment.serialize_uri()
    transfer_ffill = transfer_tx_body['fulfillments'][0]['fulfillment']

    assert transfer_ffill == expected_ffill

    transfer_tx = Transaction.from_dict(transfer_tx)
    assert transfer_tx.fulfillments_valid([tx.conditions[0]]) is True
Beispiel #11
0
    def from_dict(cls, block_body):
        block = block_body['block']
        block_serialized = serialize(block)
        block_id = hash_data(block_serialized)
        verifying_key = VerifyingKey(block['node_pubkey'])

        try:
            signature = block_body['signature']
        except KeyError:
            signature = None

        if block_id != block_body['id']:
            raise InvalidHash()

        if signature is not None:
            # NOTE: CC throws a `ValueError` on some wrong signatures
            #       https://github.com/bigchaindb/cryptoconditions/issues/27
            try:
                signature_valid = verifying_key.verify(block_serialized,
                                                       signature)
            except ValueError:
                signature_valid = False
            if signature_valid is False:
                raise InvalidSignature('Invalid block signature')

        transactions = [Transaction.from_dict(tx) for tx
                        in block['transactions']]

        return cls(transactions, block['node_pubkey'],
                   block['timestamp'], block['voters'], signature)
def transfer_utx(user_cond, user2_cond, utx):
    from bigchaindb_common.transaction import (Fulfillment, TransactionLink,
                                               Transaction, Asset)
    user_cond = user_cond.to_dict()
    ffill = Fulfillment(utx.conditions[0].fulfillment,
                        user_cond['owners_after'], TransactionLink(utx.id, 0))
    return Transaction('TRANSFER', Asset(), [ffill], [user2_cond])
def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub,
                                               data):
    from bigchaindb_common.transaction import Transaction, Asset

    tx = Transaction.create([user_pub], [user_pub, user2_pub], data, Asset())
    tx = tx.sign([user_priv])
    assert tx.fulfillments_valid() is True
def test_validate_multiple_io_create_transaction(user_pub, user_priv,
                                                 user2_pub, user2_priv):
    from bigchaindb_common.transaction import Transaction

    tx = Transaction.create([user_pub, user2_pub], [user_pub, user2_pub],
                            {'message': 'hello'})
    tx = tx.sign([user_priv, user2_priv])
    assert tx.fulfillments_valid() is True
def test_create_transfer_with_invalid_parameters():
    from bigchaindb_common.transaction import Transaction, Asset

    with raises(TypeError):
        Transaction.transfer({}, [], Asset())
    with raises(ValueError):
        Transaction.transfer([], [], Asset())
    with raises(TypeError):
        Transaction.transfer(['fulfillment'], {}, Asset())
    with raises(ValueError):
        Transaction.transfer(['fulfillment'], [], Asset())
def test_create_default_asset_on_tx_initialization():
    from bigchaindb_common.transaction import Transaction, Asset

    tx = Transaction(Transaction.CREATE, None)
    expected = Asset()
    asset = tx.asset

    expected.data_id = None
    asset.data_id = None
    assert asset == expected
def test_create_create_transaction_hashlock(user_pub, data, data_id):
    from cryptoconditions import PreimageSha256Fulfillment
    from bigchaindb_common.transaction import Transaction, Condition, Asset

    secret = b'much secret, wow'
    hashlock = PreimageSha256Fulfillment(preimage=secret).condition_uri
    cond = Condition(hashlock)

    expected = {
        'transaction': {
            'conditions': [cond.to_dict(0)],
            'metadata': {
                'data': data,
            },
            'asset': {
                'id': data_id,
                'divisible': False,
                'updatable': False,
                'refillable': False,
                'data': data,
            },
            'fulfillments': [
                {
                    'owners_before': [
                        user_pub,
                    ],
                    'fid': 0,
                    'fulfillment': None,
                    'input': None
                },
            ],
            'operation': 'CREATE',
        },
        'version': 1
    }

    asset = Asset(data, data_id)
    tx = Transaction.create([user_pub], [], data, asset, secret).to_dict()
    tx.pop('id')
    tx['transaction']['metadata'].pop('id')
    tx['transaction'].pop('timestamp')
    tx['transaction']['fulfillments'][0]['fulfillment'] = None

    assert tx == expected
def test_tx_serialization_with_incorrect_hash(utx):
    from bigchaindb_common.transaction import Transaction
    from bigchaindb_common.exceptions import InvalidHash

    utx_dict = utx.to_dict()
    utx_dict['id'] = 'abc'
    with raises(InvalidHash):
        Transaction.from_dict(utx_dict)
    utx_dict.pop('id')
    with raises(InvalidHash):
        Transaction.from_dict(utx_dict)
    utx_dict['id'] = []
    with raises(InvalidHash):
        Transaction.from_dict(utx_dict)
def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub,
                                             user_user2_threshold_cond,
                                             user_user2_threshold_ffill, data,
                                             data_id):
    from bigchaindb_common.transaction import Transaction, Asset

    expected = {
        'transaction': {
            'conditions': [user_user2_threshold_cond.to_dict(0)],
            'metadata': {
                'data': data,
            },
            'asset': {
                'id': data_id,
                'divisible': False,
                'updatable': False,
                'refillable': False,
                'data': data,
            },
            'fulfillments': [
                {
                    'owners_before': [
                        user_pub,
                    ],
                    'fid': 0,
                    'fulfillment': None,
                    'input': None
                },
            ],
            'operation': 'CREATE',
        },
        'version': 1
    }
    asset = Asset(data, data_id)
    tx = Transaction.create([user_pub], [user_pub, user2_pub], data, asset)
    tx_dict = tx.to_dict()
    tx_dict.pop('id')
    tx_dict['transaction']['metadata'].pop('id')
    tx_dict['transaction'].pop('timestamp')
    tx_dict['transaction']['fulfillments'][0]['fulfillment'] = None

    assert tx_dict == expected
def test_create_create_transaction_multiple_io(user_cond, user2_cond, user_pub,
                                               user2_pub):
    from bigchaindb_common.transaction import Transaction

    expected = {
        'transaction': {
            'conditions': [user_cond.to_dict(0), user2_cond.to_dict(1)],
            'metadata': {
                'data': {
                    'message': 'hello'
                }
            },
            'fulfillments': [
                {
                    'owners_before': [
                        user_pub,
                    ],
                    'fid': 0,
                    'fulfillment': None,
                    'input': None
                },
                {
                    'owners_before': [
                        user2_pub,
                    ],
                    'fid': 1,
                    'fulfillment': None,
                    'input': None
                }
            ],
            'operation': 'CREATE',
        },
        'version': 1
    }
    tx = Transaction.create([user_pub, user2_pub], [user_pub, user2_pub],
                            {'message': 'hello'}).to_dict()
    tx.pop('id')
    tx['transaction']['metadata'].pop('id')
    tx['transaction'].pop('timestamp')

    assert tx == expected
def test_create_transfer_transaction_multiple_io(user_pub, user_priv,
                                                 user2_pub, user2_priv,
                                                 user3_pub, user2_cond):
    from bigchaindb_common.transaction import Transaction

    tx1 = Transaction.create([user_pub], [user_pub], {'message': 'hello'})
    tx1 = tx1.sign([user_priv])
    tx2 = Transaction.create([user2_pub], [user2_pub], {'message': 'hello'})
    tx2 = tx2.sign([user2_priv])

    expected = {
        'transaction': {
            'conditions': [user2_cond.to_dict(0), user2_cond.to_dict(1)],
            'metadata': None,
            'fulfillments': [
                {
                    'owners_before': [
                        user_pub
                    ],
                    'fid': 0,
                    'fulfillment': None,
                    'input': {
                        'txid': tx1.id,
                        'cid': 0
                    }
                }, {
                    'owners_before': [
                        user2_pub
                    ],
                    'fid': 1,
                    'fulfillment': None,
                    'input': {
                        'txid': tx2.id,
                        'cid': 0
                    }
                }
            ],
            'operation': 'TRANSFER',
        },
        'version': 1
    }
    tx1_inputs = tx1.to_inputs()
    tx2_inputs = tx2.to_inputs()
    tx_inputs = tx1_inputs + tx2_inputs

    transfer_tx = Transaction.transfer(tx_inputs, [[user2_pub], [user2_pub]])
    transfer_tx = transfer_tx.sign([user_priv, user2_priv])
    transfer_tx = transfer_tx

    assert len(transfer_tx.fulfillments) == 2
    assert len(transfer_tx.conditions) == 2

    combined_conditions = tx1.conditions + tx2.conditions
    assert transfer_tx.fulfillments_valid(combined_conditions) is True

    transfer_tx = transfer_tx.to_dict()
    transfer_tx['transaction']['fulfillments'][0]['fulfillment'] = None
    transfer_tx['transaction']['fulfillments'][1]['fulfillment'] = None
    transfer_tx['transaction'].pop('timestamp')
    transfer_tx.pop('id')

    assert expected == transfer_tx
def utx(user_ffill, user_cond):
    from bigchaindb_common.transaction import Transaction, Asset
    return Transaction(Transaction.CREATE, Asset(), [user_ffill], [user_cond])
def test_cant_add_empty_fulfillment():
    from bigchaindb_common.transaction import Transaction
    tx = Transaction(Transaction.CREATE, None)
    with raises(TypeError):
        tx.add_fulfillment(None)
def test_create_create_transaction_with_invalid_parameters():
    from bigchaindb_common.transaction import Transaction

    with raises(TypeError):
        Transaction.create('not a list')
    with raises(TypeError):
        Transaction.create([], 'not a list')
    with raises(NotImplementedError):
        Transaction.create(['a', 'b'], ['c', 'd'])
    with raises(NotImplementedError):
        Transaction.create(['a'], [], time_expire=123)
    with raises(ValueError):
        Transaction.create(['a'], [], secret=None)
    with raises(ValueError):
        Transaction.create([], [], secret='wow, much secret')
def test_validate_hashlock_create_transaction(user_pub, user_priv, data):
    from bigchaindb_common.transaction import Transaction, Asset

    tx = Transaction.create([user_pub], [], data, Asset(), b'much secret, wow')
    tx = tx.sign([user_priv])
    assert tx.fulfillments_valid() is True
def test_add_condition_to_tx_with_invalid_parameters():
    from bigchaindb_common.transaction import Transaction, Asset

    tx = Transaction(Transaction.CREATE, Asset(), [], [])
    with raises(TypeError):
        tx.add_condition('somewronginput')