예제 #1
0
    def test_get_spent_with_double_spend_detected(self, b, alice):
        from bigchaindb.models import Transaction
        from bigchaindb.common.exceptions import DoubleSpend
        from bigchaindb.exceptions import CriticalDoubleSpend

        tx = Transaction.create([alice.public_key], [([alice.public_key], 1)])
        tx = tx.sign([alice.private_key])

        b.store_bulk_transactions([tx])

        transfer_tx = Transaction.transfer(tx.to_inputs(), [([alice.public_key], 1)],
                                           asset_id=tx.id)
        transfer_tx = transfer_tx.sign([alice.private_key])
        transfer_tx2 = Transaction.transfer(tx.to_inputs(), [([alice.public_key], 2)],
                                            asset_id=tx.id)
        transfer_tx2 = transfer_tx2.sign([alice.private_key])

        with pytest.raises(DoubleSpend):
            b.validate_transaction(transfer_tx2, [transfer_tx])

        b.store_bulk_transactions([transfer_tx])

        with pytest.raises(DoubleSpend):
            b.validate_transaction(transfer_tx2)

        b.store_bulk_transactions([transfer_tx2])

        with pytest.raises(CriticalDoubleSpend):
            b.get_spent(tx.id, 0)
예제 #2
0
def test_post_transaction_responses(tendermint_ws_url, b):
    from bigchaindb.common.crypto import generate_key_pair
    from bigchaindb.models import Transaction

    alice = generate_key_pair()
    bob = generate_key_pair()
    tx = Transaction.create([alice.public_key],
                            [([alice.public_key], 1)],
                            asset=None)\
                    .sign([alice.private_key])

    code, message = b.write_transaction(tx, 'broadcast_tx_commit')
    assert code == 202

    tx_transfer = Transaction.transfer(tx.to_inputs(),
                                       [([bob.public_key], 1)],
                                       asset_id=tx.id)\
                             .sign([alice.private_key])

    code, message = b.write_transaction(tx_transfer, 'broadcast_tx_commit')
    assert code == 202

    carly = generate_key_pair()
    double_spend = Transaction.transfer(
        tx.to_inputs(),
        [([carly.public_key], 1)],
        asset_id=tx.id,
    ).sign([alice.private_key])
    for mode in ('broadcast_tx_sync', 'broadcast_tx_commit'):
        code, message = b.write_transaction(double_spend, mode)
        assert code == 500
        assert message == 'Transaction validation failed'
예제 #3
0
def test_get_spent_key_order(b, user_pk, user_sk, user2_pk, user2_sk):
    from bigchaindb import backend
    from bigchaindb.models import Transaction
    from bigchaindb.common.crypto import generate_key_pair
    from bigchaindb.common.exceptions import DoubleSpend

    alice = generate_key_pair()
    bob = generate_key_pair()

    tx1 = Transaction.create([user_pk],
                             [([alice.public_key], 3), ([user_pk], 2)],
                             asset=None)\
                     .sign([user_sk])
    b.store_bulk_transactions([tx1])

    inputs = tx1.to_inputs()
    tx2 = Transaction.transfer([inputs[1]], [([user2_pk], 2)], tx1.id).sign([user_sk])
    assert tx2.validate(b)

    tx2_dict = tx2.to_dict()
    fulfills = tx2_dict['inputs'][0]['fulfills']
    tx2_dict['inputs'][0]['fulfills'] = {'output_index': fulfills['output_index'],
                                         'transaction_id': fulfills['transaction_id']}

    backend.query.store_transactions(b.connection, [tx2_dict])

    tx3 = Transaction.transfer([inputs[1]], [([bob.public_key], 2)], tx1.id).sign([user_sk])

    with pytest.raises(DoubleSpend):
        tx3.validate(b)
예제 #4
0
def test_amount_error_transfer(alice, b, user_pk, user_sk):
    from bigchaindb.models import Transaction
    from bigchaindb.common.exceptions import AmountError

    # CREATE divisible asset
    tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()})
    tx_create_signed = tx_create.sign([alice.private_key])

    b.store_bulk_transactions([tx_create_signed])

    # TRANSFER
    # output amount less than input amount
    tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 50)],
                                       asset_id=tx_create.id)
    tx_transfer_signed = tx_transfer.sign([user_sk])

    with pytest.raises(AmountError):
        tx_transfer_signed.validate(b)

    # TRANSFER
    # output amount greater than input amount
    tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 101)],
                                       asset_id=tx_create.id)
    tx_transfer_signed = tx_transfer.sign([user_sk])

    with pytest.raises(AmountError):
        tx_transfer_signed.validate(b)
예제 #5
0
def test_get_divisble_transactions_returns_500(b, client):
    from bigchaindb.models import Transaction
    from bigchaindb.common import crypto
    import json

    TX_ENDPOINT = '/api/v1/transactions'

    def mine(tx_list):
        b.store_bulk_transactions(tx_list)

    alice_priv, alice_pub = crypto.generate_key_pair()
    bob_priv, bob_pub = crypto.generate_key_pair()
    carly_priv, carly_pub = crypto.generate_key_pair()

    create_tx = Transaction.create([alice_pub], [([alice_pub], 4)])
    create_tx.sign([alice_priv])

    res = client.post(TX_ENDPOINT, data=json.dumps(create_tx.to_dict()))
    assert res.status_code == 202

    mine([create_tx])

    transfer_tx = Transaction.transfer(create_tx.to_inputs(),
                                       [([alice_pub], 3), ([bob_pub], 1)],
                                       asset_id=create_tx.id)
    transfer_tx.sign([alice_priv])

    res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))
    assert res.status_code == 202

    mine([transfer_tx])

    transfer_tx_carly = Transaction.transfer([transfer_tx.to_inputs()[1]],
                                             [([carly_pub], 1)],
                                             asset_id=create_tx.id)
    transfer_tx_carly.sign([bob_priv])

    res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx_carly.to_dict()))
    assert res.status_code == 202

    mine([transfer_tx_carly])

    asset_id = create_tx.id

    url = TX_ENDPOINT + '?asset_id=' + asset_id
    assert client.get(url).status_code == 200
    assert len(client.get(url).json) == 3

    url = OUTPUTS_ENDPOINT + '?public_key=' + alice_pub
    assert client.get(url).status_code == 200

    url = OUTPUTS_ENDPOINT + '?public_key=' + bob_pub
    assert client.get(url).status_code == 200

    url = OUTPUTS_ENDPOINT + '?public_key=' + carly_pub
    assert client.get(url).status_code == 200
예제 #6
0
def test_get_spent_issue_1271(b, alice, bob, carol):
    from bigchaindb.models import Transaction

    tx_1 = Transaction.create(
        [carol.public_key],
        [([carol.public_key], 8)],
    ).sign([carol.private_key])
    assert tx_1.validate(b)
    b.store_bulk_transactions([tx_1])

    tx_2 = Transaction.transfer(
        tx_1.to_inputs(),
        [([bob.public_key], 2),
         ([alice.public_key], 2),
         ([carol.public_key], 4)],
        asset_id=tx_1.id,
    ).sign([carol.private_key])
    assert tx_2.validate(b)
    b.store_bulk_transactions([tx_2])

    tx_3 = Transaction.transfer(
        tx_2.to_inputs()[2:3],
        [([alice.public_key], 1),
         ([carol.public_key], 3)],
        asset_id=tx_1.id,
    ).sign([carol.private_key])
    assert tx_3.validate(b)
    b.store_bulk_transactions([tx_3])

    tx_4 = Transaction.transfer(
        tx_2.to_inputs()[1:2] + tx_3.to_inputs()[0:1],
        [([bob.public_key], 3)],
        asset_id=tx_1.id,
    ).sign([alice.private_key])
    assert tx_4.validate(b)
    b.store_bulk_transactions([tx_4])

    tx_5 = Transaction.transfer(
        tx_2.to_inputs()[0:1],
        [([alice.public_key], 2)],
        asset_id=tx_1.id,
    ).sign([bob.private_key])
    assert tx_5.validate(b)

    b.store_bulk_transactions([tx_5])

    assert b.get_spent(tx_2.id, 0) == tx_5
    assert not b.get_spent(tx_5.id, 0)
    assert b.get_outputs_filtered(alice.public_key)
    assert b.get_outputs_filtered(alice.public_key, spent=False)
예제 #7
0
    def test_get_spent_multiple_owners(self, b, user_sk, user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()
        user3_sk, user3_pk = crypto.generate_key_pair()

        transactions = []
        for i in range(3):
            payload = {'somedata': i}
            tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)],
                                    payload)
            tx = tx.sign([alice.private_key])
            transactions.append(tx)

        b.store_bulk_transactions(transactions)

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        # check spents
        for input_tx in owned_inputs_user1:
            assert b.get_spent(input_tx.txid, input_tx.output) is None

        # create a transaction
        tx = Transaction.transfer(transactions[0].to_inputs(),
                                  [([user3_pk], 1)],
                                  asset_id=transactions[0].id)
        tx = tx.sign([user_sk, user2_sk])
        b.store_bulk_transactions([tx])

        # check that used inputs are marked as spent
        assert b.get_spent(transactions[0].id, 0) == tx
        # check that the other remain marked as unspent
        for unspent in transactions[1:]:
            assert b.get_spent(unspent.id, 0) is None
예제 #8
0
def test_cant_spend_same_input_twice_in_tx(b, genesis_block, alice):
    """Recreate duplicated fulfillments bug
    https://github.com/bigchaindb/bigchaindb/issues/1099
    """
    from bigchaindb.models import Transaction
    from bigchaindb.common.exceptions import DoubleSpend

    # create a divisible asset
    tx_create = Transaction.create([alice.public_key], [([alice.public_key], 100)])
    tx_create_signed = tx_create.sign([alice.private_key])
    assert b.validate_transaction(tx_create_signed) == tx_create_signed

    # create a block and valid vote
    block = b.create_block([tx_create_signed])
    b.write_block(block)
    vote = b.vote(block.id, genesis_block.id, True)
    b.write_vote(vote)

    # Create a transfer transaction with duplicated fulfillments
    dup_inputs = tx_create.to_inputs() + tx_create.to_inputs()
    tx_transfer = Transaction.transfer(dup_inputs, [([alice.public_key], 200)],
                                       asset_id=tx_create.id)
    tx_transfer_signed = tx_transfer.sign([alice.private_key])
    with pytest.raises(DoubleSpend):
        tx_transfer_signed.validate(b)
예제 #9
0
    def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.common.transaction import TransactionLink
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()
        user3_sk, user3_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)])
        tx = tx.sign([alice.private_key])

        b.store_bulk_transactions([tx])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user_pk)
        expected_owned_inputs_user1 = [TransactionLink(tx.id, 0)]

        assert owned_inputs_user1 == owned_inputs_user2
        assert owned_inputs_user1 == expected_owned_inputs_user1

        tx = Transaction.transfer(tx.to_inputs(), [([user3_pk], 1)],
                                  asset_id=tx.id)
        tx = tx.sign([user_sk, user2_sk])
        b.store_bulk_transactions([tx])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user2_pk)
        spent_user1 = b.get_spent(tx.id, 0)

        assert owned_inputs_user1 == owned_inputs_user2
        assert not spent_user1
예제 #10
0
    def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.common.transaction import TransactionLink
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk], 1)])
        tx = tx.sign([alice.private_key])
        b.store_bulk_transactions([tx])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user2_pk)
        assert owned_inputs_user1 == [TransactionLink(tx.id, 0)]
        assert owned_inputs_user2 == []

        tx_transfer = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
                                           asset_id=tx.id)
        tx_transfer = tx_transfer.sign([user_sk])
        b.store_bulk_transactions([tx_transfer])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user2_pk)

        assert owned_inputs_user1 == [TransactionLink(tx.id, 0)]
        assert owned_inputs_user2 == [TransactionLink(tx_transfer.id, 0)]
예제 #11
0
    def test_read_transaction_invalid_block_and_backlog(self, b, user_pk, user_sk):
        from bigchaindb.models import Transaction

        input_tx = b.get_owned_ids(user_pk).pop()
        input_tx = b.get_transaction(input_tx.txid)
        inputs = input_tx.to_inputs()
        tx = Transaction.transfer(inputs, [([user_pk], 1)],
                                  asset_id=input_tx.id)
        tx = tx.sign([user_sk])

        # Make sure there's a copy of tx in the backlog
        b.write_transaction(tx)

        # create block
        block = b.create_block([tx])
        b.write_block(block)

        # vote the block invalid
        vote = b.vote(block.id, b.get_last_voted_block().id, False)
        b.write_vote(vote)

        # a copy of the tx is both in the backlog and in an invalid
        # block, so get_transaction should return a transaction,
        # and a status of TX_IN_BACKLOG
        response, status = b.get_transaction(tx.id, include_status=True)
        assert tx.to_dict() == response.to_dict()
        assert status == b.TX_IN_BACKLOG
예제 #12
0
def test_get_asset_id_transfer_transaction(b, signed_create_tx, user_pk):
    from bigchaindb.models import Transaction

    tx_transfer = Transaction.transfer(signed_create_tx.to_inputs(),
                                       [([user_pk], 1)], signed_create_tx.id)
    asset_id = Transaction.get_asset_id(tx_transfer)
    assert asset_id == tx_transfer.asset['id']
예제 #13
0
    def test_multiple_owners_before_multiple_owners_after_single_input(
            self, b, user_sk, user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()
        user3_sk, user3_pk = crypto.generate_key_pair()
        user4_sk, user4_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)])
        tx = tx.sign([alice.private_key])
        b.store_bulk_transactions([tx])

        # get input
        tx_link = b.fastquery.get_outputs_by_public_key(user_pk).pop()
        tx_input = b.get_transaction(tx_link.txid)

        tx = Transaction.transfer(tx_input.to_inputs(),
                                  [([user3_pk, user4_pk], 1)],
                                  asset_id=tx_input.id)
        tx = tx.sign([user_sk, user2_sk])

        tx.validate(b)
        assert len(tx.inputs) == 1
        assert len(tx.outputs) == 1
예제 #14
0
    def test_multiple_owners_before_multiple_owners_after_single_input(self, b,
                                                                       user_sk,
                                                                       user_pk,
                                                                       alice):
        from bigchaindb.common import crypto
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()
        user3_sk, user3_pk = crypto.generate_key_pair()
        user4_sk, user4_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)])
        tx = tx.sign([alice.private_key])
        b.store_bulk_transactions([tx])

        # get input
        tx_link = b.fastquery.get_outputs_by_public_key(user_pk).pop()
        tx_input = b.get_transaction(tx_link.txid)

        tx = Transaction.transfer(tx_input.to_inputs(),
                                  [([user3_pk, user4_pk], 1)],
                                  asset_id=tx_input.id)
        tx = tx.sign([user_sk, user2_sk])

        tx.validate(b)
        assert len(tx.inputs) == 1
        assert len(tx.outputs) == 1
예제 #15
0
    def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk,
                                               alice):
        from bigchaindb.common import crypto
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk], 1)])
        tx = tx.sign([alice.private_key])
        block = b.create_block([tx])
        b.write_block(block)

        owned_inputs_user1 = b.get_owned_ids(user_pk).pop()

        # check spents
        input_txid = owned_inputs_user1.txid
        input_idx = owned_inputs_user1.output
        spent_inputs_user1 = b.get_spent(input_txid, input_idx)
        assert spent_inputs_user1 is None

        # create a transaction and block
        tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
                                  asset_id=tx.id)
        tx = tx.sign([user_sk])
        block = b.create_block([tx])
        b.write_block(block)

        spent_inputs_user1 = b.get_spent(input_txid, input_idx)
        assert spent_inputs_user1 == tx
예제 #16
0
def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(b, user_pk,
                                                            user_sk):
    from bigchaindb.models import Transaction
    from bigchaindb.common.transaction import _fulfillment_to_details

    # CREATE divisible asset
    tx_create = Transaction.create([b.me], [([user_pk], 50), ([user_pk, b.me], 50)],
                                   asset={'name': random.random()})
    tx_create_signed = tx_create.sign([b.me_private])

    # TRANSFER
    tx_transfer = Transaction.transfer(tx_create.to_inputs(),
                                       [([b.me], 50), ([b.me, user_pk], 50)],
                                       asset_id=tx_create.id)
    tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])

    b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])

    assert tx_transfer_signed.validate(b) == tx_transfer_signed
    assert len(tx_transfer_signed.outputs) == 2
    assert tx_transfer_signed.outputs[0].amount == 50
    assert tx_transfer_signed.outputs[1].amount == 50
    assert len(tx_transfer_signed.inputs) == 2

    cond_cid0 = tx_transfer_signed.outputs[0].to_dict()
    cond_cid1 = tx_transfer_signed.outputs[1].to_dict()
    assert 'subconditions' not in cond_cid0['condition']['details']
    assert 'subconditions' in cond_cid1['condition']['details']
    assert len(cond_cid1['condition']['details']['subconditions']) == 2

    ffill_fid0 = _fulfillment_to_details(tx_transfer_signed.inputs[0].fulfillment)
    ffill_fid1 = _fulfillment_to_details(tx_transfer_signed.inputs[1].fulfillment)
    assert 'subconditions' not in ffill_fid0
    assert 'subconditions' in ffill_fid1
    assert len(ffill_fid1['subconditions']) == 2
예제 #17
0
def test_single_in_multiple_own_single_out_single_own_transfer(b, user_pk,
                                                               user_sk):
    from bigchaindb.models import Transaction
    from bigchaindb.common.transaction import _fulfillment_to_details

    # CREATE divisible asset
    tx_create = Transaction.create([b.me], [([b.me, user_pk], 100)],
                                   asset={'name': random.random()})
    tx_create_signed = tx_create.sign([b.me_private])

    # TRANSFER
    tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([b.me], 100)],
                                       asset_id=tx_create.id)
    tx_transfer_signed = tx_transfer.sign([b.me_private, user_sk])

    b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])

    assert tx_transfer_signed.validate(b) == tx_transfer_signed
    assert len(tx_transfer_signed.outputs) == 1
    assert tx_transfer_signed.outputs[0].amount == 100
    assert len(tx_transfer_signed.inputs) == 1

    ffill = _fulfillment_to_details(tx_transfer_signed.inputs[0].fulfillment)
    assert 'subconditions' in ffill
    assert len(ffill['subconditions']) == 2
예제 #18
0
def test_single_in_single_own_single_out_multiple_own_transfer(b, user_pk,
                                                               user_sk):
    from bigchaindb.models import Transaction

    # CREATE divisible asset
    tx_create = Transaction.create([b.me], [([user_pk], 100)], asset={'name': random.random()})
    tx_create_signed = tx_create.sign([b.me_private])

    # TRANSFER
    tx_transfer = Transaction.transfer(tx_create.to_inputs(),
                                       [([b.me, b.me], 100)],
                                       asset_id=tx_create.id)
    tx_transfer_signed = tx_transfer.sign([user_sk])

    b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])

    assert tx_transfer_signed.validate(b) == tx_transfer_signed
    assert len(tx_transfer_signed.outputs) == 1
    assert tx_transfer_signed.outputs[0].amount == 100

    condition = tx_transfer_signed.outputs[0].to_dict()
    assert 'subconditions' in condition['condition']['details']
    assert len(condition['condition']['details']['subconditions']) == 2

    assert len(tx_transfer_signed.inputs) == 1
예제 #19
0
    def test_get_owned_ids_single_tx_single_output(self, b, user_sk, user_pk,
                                                   alice):
        from bigchaindb.common import crypto
        from bigchaindb.common.transaction import TransactionLink
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk], 1)])
        tx = tx.sign([alice.private_key])
        b.store_bulk_transactions([tx])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user2_pk)
        assert owned_inputs_user1 == [TransactionLink(tx.id, 0)]
        assert owned_inputs_user2 == []

        tx_transfer = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
                                           asset_id=tx.id)
        tx_transfer = tx_transfer.sign([user_sk])
        b.store_bulk_transactions([tx_transfer])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user2_pk)

        assert owned_inputs_user1 == [TransactionLink(tx.id, 0)]
        assert owned_inputs_user2 == [TransactionLink(tx_transfer.id, 0)]
예제 #20
0
    def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.common.transaction import TransactionLink
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()
        user3_sk, user3_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)])
        tx = tx.sign([alice.private_key])

        b.store_bulk_transactions([tx])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user_pk)
        expected_owned_inputs_user1 = [TransactionLink(tx.id, 0)]

        assert owned_inputs_user1 == owned_inputs_user2
        assert owned_inputs_user1 == expected_owned_inputs_user1

        tx = Transaction.transfer(tx.to_inputs(), [([user3_pk], 1)],
                                  asset_id=tx.id)
        tx = tx.sign([user_sk, user2_sk])
        b.store_bulk_transactions([tx])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user2_pk)
        spent_user1 = b.get_spent(tx.id, 0)

        assert owned_inputs_user1 == owned_inputs_user2
        assert not spent_user1
예제 #21
0
    def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk], 1)])
        tx = tx.sign([alice.private_key])
        b.store_bulk_transactions([tx])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk).pop()

        # check spents
        input_txid = owned_inputs_user1.txid
        spent_inputs_user1 = b.get_spent(input_txid, 0)
        assert spent_inputs_user1 is None

        # create a transaction and send it
        tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
                                  asset_id=tx.id)
        tx = tx.sign([user_sk])
        b.store_bulk_transactions([tx])

        spent_inputs_user1 = b.get_spent(input_txid, 0)
        assert spent_inputs_user1 == tx
예제 #22
0
def test_post_wrong_asset_division_transfer_returns_400(b, client, user_pk):
    from bigchaindb.models import Transaction
    from bigchaindb.common.exceptions import AmountError

    priv_key, pub_key = crypto.generate_key_pair()

    create_tx = Transaction.create([pub_key], [([pub_key], 10)],
                                   asset={
                                       'test': 'asset'
                                   }).sign([priv_key])
    res = client.post(TX_ENDPOINT + '?mode=commit',
                      data=json.dumps(create_tx.to_dict()))
    assert res.status_code == 202

    transfer_tx = Transaction.transfer(
        create_tx.to_inputs(),
        [([pub_key], 20)],  # 20 > 10
        asset_id=create_tx.id).sign([priv_key])
    res = client.post(TX_ENDPOINT + '?mode=commit',
                      data=json.dumps(transfer_tx.to_dict()))
    expected_error_message = \
        f'Invalid transaction ({AmountError.__name__}): ' + \
        'The amount used in the inputs `10` needs to be same as the amount used in the outputs `20`'

    assert res.status_code == 400
    assert res.json['message'] == expected_error_message
예제 #23
0
def test_threshold_same_public_key(alice, b, user_pk, user_sk):
    # If we try to fulfill a threshold condition where each subcondition has
    # the same key get_subcondition_from_vk will always return the first
    # subcondition. This means that only the 1st subfulfillment will be
    # generated
    # Creating threshold conditions with the same key does not make sense but
    # that does not mean that the code shouldn't work.

    from bigchaindb.models import Transaction

    # CREATE divisible asset
    tx_create = Transaction.create([alice.public_key], [([user_pk, user_pk], 100)],
                                   asset={'name': random.random()})
    tx_create_signed = tx_create.sign([alice.private_key])

    # TRANSFER
    tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)],
                                       asset_id=tx_create.id)
    tx_transfer_signed = tx_transfer.sign([user_sk, user_sk])

    b.store_bulk_transactions([tx_create_signed])

    assert tx_transfer_signed.validate(b) == tx_transfer_signed

    b.store_bulk_transactions([tx_transfer_signed])
    with pytest.raises(DoubleSpend):
        tx_transfer_signed.validate(b)
예제 #24
0
def test_get_asset_id_transfer_transaction(b, signed_create_tx, user_pk):
    from bigchaindb.models import Transaction

    tx_transfer = Transaction.transfer(signed_create_tx.to_inputs(), [([user_pk], 1)],
                                       signed_create_tx.id)
    asset_id = Transaction.get_asset_id(tx_transfer)
    assert asset_id == tx_transfer.asset['id']
예제 #25
0
    def test_get_owned_ids_single_tx_multiple_outputs(self, b, user_sk,
                                                      user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.common.transaction import TransactionLink
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()

        # create divisible asset
        tx_create = Transaction.create([alice.public_key], [([user_pk], 1), ([user_pk], 1)])
        tx_create_signed = tx_create.sign([alice.private_key])
        b.store_bulk_transactions([tx_create_signed])

        # get input
        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user2_pk)

        expected_owned_inputs_user1 = [TransactionLink(tx_create.id, 0),
                                       TransactionLink(tx_create.id, 1)]
        assert owned_inputs_user1 == expected_owned_inputs_user1
        assert owned_inputs_user2 == []

        # transfer divisible asset divided in two outputs
        tx_transfer = Transaction.transfer(tx_create.to_inputs(),
                                           [([user2_pk], 1), ([user2_pk], 1)],
                                           asset_id=tx_create.id)
        tx_transfer_signed = tx_transfer.sign([user_sk])
        b.store_bulk_transactions([tx_transfer_signed])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        owned_inputs_user2 = b.fastquery.get_outputs_by_public_key(user2_pk)
        assert owned_inputs_user1 == expected_owned_inputs_user1
        assert owned_inputs_user2 == [TransactionLink(tx_transfer.id, 0),
                                      TransactionLink(tx_transfer.id, 1)]
예제 #26
0
def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk,
                                                               user_sk):
    from bigchaindb.models import Transaction
    from bigchaindb.common.transaction import _fulfillment_to_details

    # CREATE divisible asset
    tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)],
                                   asset={'name': random.random()})
    tx_create_signed = tx_create.sign([alice.private_key])

    # TRANSFER
    tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([alice.public_key], 100)],
                                       asset_id=tx_create.id)
    tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk])

    b.store_bulk_transactions([tx_create_signed])

    assert tx_transfer_signed.validate(b) == tx_transfer_signed
    assert len(tx_transfer_signed.outputs) == 1
    assert tx_transfer_signed.outputs[0].amount == 100
    assert len(tx_transfer_signed.inputs) == 2

    ffill_fid0 = _fulfillment_to_details(tx_transfer_signed.inputs[0].fulfillment)
    ffill_fid1 = _fulfillment_to_details(tx_transfer_signed.inputs[1].fulfillment)
    assert 'subconditions' not in ffill_fid0
    assert 'subconditions' in ffill_fid1
    assert len(ffill_fid1['subconditions']) == 2

    b.store_bulk_transactions([tx_transfer_signed])
    with pytest.raises(DoubleSpend):
        tx_transfer_signed.validate(b)
예제 #27
0
    def test_multiple_owners_before_multiple_owners_after_single_input(self, b,
                                                                       user_sk,
                                                                       user_pk,
                                                                       alice):
        from bigchaindb.common import crypto
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()
        user3_sk, user3_pk = crypto.generate_key_pair()
        user4_sk, user4_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)])
        tx = tx.sign([alice.private_key])
        block = b.create_block([tx])
        b.write_block(block)

        # vote block valid
        vote = b.vote(block.id, b.get_last_voted_block().id, True)
        b.write_vote(vote)

        # get input
        tx_link = b.get_owned_ids(user_pk).pop()
        tx_input = b.get_transaction(tx_link.txid)

        tx = Transaction.transfer(tx_input.to_inputs(),
                                  [([user3_pk, user4_pk], 1)],
                                  asset_id=tx_input.id)
        tx = tx.sign([user_sk, user2_sk])

        tx.validate(b)
        assert len(tx.inputs) == 1
        assert len(tx.outputs) == 1
예제 #28
0
def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk,
                                                            user_sk):
    from bigchaindb.models import Transaction

    # CREATE divisible asset
    tx_create = Transaction.create([alice.public_key], [([user_pk], 100)], asset={'name': random.random()})
    tx_create_signed = tx_create.sign([alice.private_key])

    # TRANSFER
    tx_transfer = Transaction.transfer(tx_create.to_inputs(),
                                       [([alice.public_key], 50), ([alice.public_key, alice.public_key], 50)],
                                       asset_id=tx_create.id)
    tx_transfer_signed = tx_transfer.sign([user_sk])

    b.store_bulk_transactions([tx_create_signed])

    assert tx_transfer_signed.validate(b) == tx_transfer_signed
    assert len(tx_transfer_signed.outputs) == 2
    assert tx_transfer_signed.outputs[0].amount == 50
    assert tx_transfer_signed.outputs[1].amount == 50

    output_cid1 = tx_transfer_signed.outputs[1].to_dict()
    assert 'subconditions' in output_cid1['condition']['details']
    assert len(output_cid1['condition']['details']['subconditions']) == 2

    assert len(tx_transfer_signed.inputs) == 1

    b.store_bulk_transactions([tx_transfer_signed])
    with pytest.raises(DoubleSpend):
        tx_transfer_signed.validate(b)
예제 #29
0
    def test_get_owned_ids_multiple_owners(self, b, user_sk, user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.common.transaction import TransactionLink
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()
        user3_sk, user3_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk, user2_pk], 1)])
        tx = tx.sign([alice.private_key])
        block = b.create_block([tx])
        b.write_block(block)

        owned_inputs_user1 = b.get_owned_ids(user_pk)
        owned_inputs_user2 = b.get_owned_ids(user2_pk)
        expected_owned_inputs_user1 = [TransactionLink(tx.id, 0)]

        assert owned_inputs_user1 == owned_inputs_user2
        assert owned_inputs_user1 == expected_owned_inputs_user1

        tx = Transaction.transfer(tx.to_inputs(), [([user3_pk], 1)],
                                  asset_id=tx.id)
        tx = tx.sign([user_sk, user2_sk])
        block = b.create_block([tx])
        b.write_block(block)

        owned_inputs_user1 = b.get_owned_ids(user_pk)
        owned_inputs_user2 = b.get_owned_ids(user2_pk)
        assert owned_inputs_user1 == owned_inputs_user2
        assert owned_inputs_user1 == []
예제 #30
0
    def test_get_spent_multiple_owners(self, b, user_sk, user_pk, alice):
        from bigchaindb.common import crypto
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()
        user3_sk, user3_pk = crypto.generate_key_pair()

        transactions = []
        for i in range(3):
            payload = {'somedata': i}
            tx = Transaction.create([alice.public_key],
                                    [([user_pk, user2_pk], 1)], payload)
            tx = tx.sign([alice.private_key])
            transactions.append(tx)

        b.store_bulk_transactions(transactions)

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(user_pk)
        # check spents
        for input_tx in owned_inputs_user1:
            assert b.get_spent(input_tx.txid, input_tx.output) is None

        # create a transaction
        tx = Transaction.transfer(transactions[0].to_inputs(),
                                  [([user3_pk], 1)],
                                  asset_id=transactions[0].id)
        tx = tx.sign([user_sk, user2_sk])
        b.store_bulk_transactions([tx])

        # check that used inputs are marked as spent
        assert b.get_spent(transactions[0].id, 0) == tx
        # check that the other remain marked as unspent
        for unspent in transactions[1:]:
            assert b.get_spent(unspent.id, 0) is None
예제 #31
0
    def test_get_spent_single_tx_single_output(self, b, user_sk, user_pk,
                                               alice):
        from bigchaindb.common import crypto
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()

        tx = Transaction.create([alice.public_key], [([user_pk], 1)])
        tx = tx.sign([alice.private_key])
        b.store_bulk_transactions([tx])

        owned_inputs_user1 = b.fastquery.get_outputs_by_public_key(
            user_pk).pop()

        # check spents
        input_txid = owned_inputs_user1.txid
        spent_inputs_user1 = b.get_spent(input_txid, 0)
        assert spent_inputs_user1 is None

        # create a transaction and send it
        tx = Transaction.transfer(tx.to_inputs(), [([user2_pk], 1)],
                                  asset_id=tx.id)
        tx = tx.sign([user_sk])
        b.store_bulk_transactions([tx])

        spent_inputs_user1 = b.get_spent(input_txid, 0)
        assert spent_inputs_user1 == tx
예제 #32
0
def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol):
    from bigchaindb.models import Transaction
    from bigchaindb.exceptions import CriticalDoubleSpend
    from bigchaindb.common.exceptions import DoubleSpend

    asset = {'test': 'asset'}

    tx = Transaction.create([alice.public_key],
                            [([alice.public_key], 1)],
                            asset=asset)\
                    .sign([alice.private_key])

    tx_transfer = Transaction.transfer(tx.to_inputs(),
                                       [([bob.public_key], 1)],
                                       asset_id=tx.id)\
                             .sign([alice.private_key])

    double_spend = Transaction.transfer(tx.to_inputs(),
                                        [([carol.public_key], 1)],
                                        asset_id=tx.id)\
                              .sign([alice.private_key])

    same_input_double_spend = Transaction.transfer(tx.to_inputs() + tx.to_inputs(),
                                                   [([bob.public_key], 1)],
                                                   asset_id=tx.id)\
                                         .sign([alice.private_key])

    b.store_bulk_transactions([tx])

    with pytest.raises(DoubleSpend):
        same_input_double_spend.validate(b)

    assert b.get_spent(tx.id, tx_transfer.inputs[0].fulfills.output, [tx_transfer])

    with pytest.raises(DoubleSpend):
        b.get_spent(tx.id, tx_transfer.inputs[0].fulfills.output,
                    [tx_transfer, double_spend])

    b.store_bulk_transactions([tx_transfer])

    with pytest.raises(DoubleSpend):
        b.get_spent(tx.id, tx_transfer.inputs[0].fulfills.output, [double_spend])

    b.store_bulk_transactions([double_spend])

    with pytest.raises(CriticalDoubleSpend):
        b.get_spent(tx.id, tx_transfer.inputs[0].fulfills.output)
예제 #33
0
def test_get_spent_issue_1271(b, alice, bob, carol):
    from bigchaindb.models import Transaction

    tx_1 = Transaction.create(
        [carol.public_key],
        [([carol.public_key], 8)],
    ).sign([carol.private_key])
    assert b.validate_transaction(tx_1)
    b.store_bulk_transactions([tx_1])

    tx_2 = Transaction.transfer(
        tx_1.to_inputs(),
        [([bob.public_key], 2), ([alice.public_key], 2),
         ([carol.public_key], 4)],
        asset_id=tx_1.id,
    ).sign([carol.private_key])
    assert b.validate_transaction(tx_2)
    b.store_bulk_transactions([tx_2])

    tx_3 = Transaction.transfer(
        tx_2.to_inputs()[2:3],
        [([alice.public_key], 1), ([carol.public_key], 3)],
        asset_id=tx_1.id,
    ).sign([carol.private_key])
    assert b.validate_transaction(tx_3)
    b.store_bulk_transactions([tx_3])

    tx_4 = Transaction.transfer(
        tx_2.to_inputs()[1:2] + tx_3.to_inputs()[0:1],
        [([bob.public_key], 3)],
        asset_id=tx_1.id,
    ).sign([alice.private_key])
    assert b.validate_transaction(tx_4)
    b.store_bulk_transactions([tx_4])

    tx_5 = Transaction.transfer(
        tx_2.to_inputs()[0:1],
        [([alice.public_key], 2)],
        asset_id=tx_1.id,
    ).sign([bob.private_key])
    assert b.validate_transaction(tx_5)
    b.store_bulk_transactions([tx_5])

    assert b.get_spent(tx_2.id, 0) == tx_5
    assert not b.get_spent(tx_5.id, 0)
    assert b.get_outputs_filtered(alice.public_key)
    assert b.get_outputs_filtered(alice.public_key, spent=False)
예제 #34
0
def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol):
    from bigchaindb.models import Transaction
    from bigchaindb.exceptions import CriticalDoubleSpend
    from bigchaindb.common.exceptions import DoubleSpend

    asset = {'test': 'asset'}

    tx = Transaction.create([alice.public_key],
                            [([alice.public_key], 1)],
                            asset=asset)\
                    .sign([alice.private_key])

    tx_transfer = Transaction.transfer(tx.to_inputs(),
                                       [([bob.public_key], 1)],
                                       asset_id=tx.id)\
                             .sign([alice.private_key])

    double_spend = Transaction.transfer(tx.to_inputs(),
                                        [([carol.public_key], 1)],
                                        asset_id=tx.id)\
                              .sign([alice.private_key])

    same_input_double_spend = Transaction.transfer(tx.to_inputs() + tx.to_inputs(),
                                                   [([bob.public_key], 1)],
                                                   asset_id=tx.id)\
                                         .sign([alice.private_key])

    b.store_bulk_transactions([tx])

    with pytest.raises(DoubleSpend):
        same_input_double_spend.validate(b)

    assert b.get_spent(tx.id, tx_transfer.inputs[0].fulfills.output, [tx_transfer])

    with pytest.raises(DoubleSpend):
        b.get_spent(tx.id, tx_transfer.inputs[0].fulfills.output,
                    [tx_transfer, double_spend])

    b.store_bulk_transactions([tx_transfer])

    with pytest.raises(DoubleSpend):
        b.get_spent(tx.id, tx_transfer.inputs[0].fulfills.output, [double_spend])

    b.store_bulk_transactions([double_spend])

    with pytest.raises(CriticalDoubleSpend):
        b.get_spent(tx.id, tx_transfer.inputs[0].fulfills.output)
def txlist(b, user_pk, user2_pk, user_sk, user2_sk, genesis_block):
    from bigchaindb.models import Transaction
    prev_block_id = genesis_block.id

    # Create first block with CREATE transactions
    create1 = Transaction.create([user_pk], [([user2_pk], 6)]) \
        .sign([user_sk])
    create2 = Transaction.create([user2_pk],
                                 [([user2_pk], 5), ([user_pk], 5)]) \
                         .sign([user2_sk])
    block1 = b.create_block([create1, create2])
    b.write_block(block1)

    # Create second block with TRANSFER transactions
    transfer1 = Transaction.transfer(create1.to_inputs(), [([user_pk], 8)],
                                     create1.id).sign([user2_sk])
    block2 = b.create_block([transfer1])
    b.write_block(block2)

    # Create block with double spend
    tx_doublespend = Transaction.transfer(create1.to_inputs(),
                                          [([user_pk], 9)],
                                          create1.id).sign([user2_sk])
    block_doublespend = b.create_block([tx_doublespend])
    b.write_block(block_doublespend)

    # Vote on all the blocks
    prev_block_id = genesis_block.id
    for bid in [block1.id, block2.id]:
        vote = b.vote(bid, prev_block_id, True)
        prev_block_id = bid
        b.write_vote(vote)

    # Create undecided block
    untx = Transaction.create([user_pk], [([user2_pk], 7)]) \
        .sign([user_sk])
    block_undecided = b.create_block([untx])
    b.write_block(block_undecided)

    return type('', (), {
        'create1': create1,
        'transfer1': transfer1,
    })
def generate_create_and_transfer(keypair=None):
    if not keypair:
        keypair = generate_key_pair()
    priv_key, pub_key = keypair
    create_tx = Transaction.create([pub_key], [([pub_key], 10)]).sign([priv_key])
    transfer_tx = Transaction.transfer(
            create_tx.to_inputs(),
            [([pub_key], 10)],
            asset_id=create_tx.id).sign([priv_key])
    return create_tx, transfer_tx
def test_get_spending_transactions(user_pk):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Block, Transaction
    conn = connect()

    out = [([user_pk], 1)]
    tx1 = Transaction.create([user_pk], out * 3)
    inputs = tx1.to_inputs()
    tx2 = Transaction.transfer([inputs[0]], out, tx1.id)
    tx3 = Transaction.transfer([inputs[1]], out, tx1.id)
    tx4 = Transaction.transfer([inputs[2]], out, tx1.id)
    block = Block([tx1, tx2, tx3, tx4])
    conn.db.bigchain.insert_one(block.to_dict())

    links = [inputs[0].fulfills.to_dict(), inputs[2].fulfills.to_dict()]
    res = list(query.get_spending_transactions(conn, links))

    # tx3 not a member because input 1 not asked for
    assert res == [(block.id, tx2.to_dict()), (block.id, tx4.to_dict())]
예제 #38
0
def generate_create_and_transfer(keypair=None):
    if not keypair:
        keypair = generate_key_pair()
    priv_key, pub_key = keypair
    create_tx = Transaction.create([pub_key], [([pub_key], 10)]).sign([priv_key])
    transfer_tx = Transaction.transfer(
            create_tx.to_inputs(),
            [([pub_key], 10)],
            asset_id=create_tx.id).sign([priv_key])
    return create_tx, transfer_tx
예제 #39
0
def test_deliver_transfer_tx__double_spend_fails(a, b, init_chain_request):
    from bigchaindb import App
    from bigchaindb.models import Transaction
    from bigchaindb.common.crypto import generate_key_pair

    app = App(a, b)
    app.init_chain(init_chain_request)

    begin_block = types.RequestBeginBlock()
    app.begin_block(begin_block)

    alice = generate_key_pair()
    bob = generate_key_pair()
    carly = generate_key_pair()

    asset = {
        'msg': 'live long and prosper'
    }

    tx = Transaction.create([alice.public_key],
                            [([alice.public_key], 1)],
                            asset=asset)\
                    .sign([alice.private_key])

    result = app.deliver_tx(encode_tx_to_bytes(tx))
    assert result.code == CodeTypeOk

    tx_transfer = Transaction.transfer(tx.to_inputs(),
                                       [([bob.public_key], 1)],
                                       asset_id=tx.id)\
                             .sign([alice.private_key])

    result = app.deliver_tx(encode_tx_to_bytes(tx_transfer))
    assert result.code == CodeTypeOk

    double_spend = Transaction.transfer(tx.to_inputs(),
                                        [([carly.public_key], 1)],
                                        asset_id=tx.id)\
                              .sign([alice.private_key])

    result = app.deliver_tx(encode_tx_to_bytes(double_spend))
    assert result.code == CodeTypeError
예제 #40
0
def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request):
    from bigchaindb import App
    from bigchaindb.models import Transaction
    from bigchaindb.common.crypto import generate_key_pair

    app = App(b)
    app.init_chain(init_chain_request)

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)

    alice = generate_key_pair()
    bob = generate_key_pair()
    carly = generate_key_pair()

    asset = {
        'msg': 'live long and prosper'
    }

    tx = Transaction.create([alice.public_key],
                            [([alice.public_key], 1)],
                            asset=asset)\
                    .sign([alice.private_key])

    result = app.deliver_tx(encode_tx_to_bytes(tx))
    assert result.code == CodeTypeOk

    tx_transfer = Transaction.transfer(tx.to_inputs(),
                                       [([bob.public_key], 1)],
                                       asset_id=tx.id)\
                             .sign([alice.private_key])

    result = app.deliver_tx(encode_tx_to_bytes(tx_transfer))
    assert result.code == CodeTypeOk

    double_spend = Transaction.transfer(tx.to_inputs(),
                                        [([carly.public_key], 1)],
                                        asset_id=tx.id)\
                              .sign([alice.private_key])

    result = app.deliver_tx(encode_tx_to_bytes(double_spend))
    assert result.code == CodeTypeError
예제 #41
0
def test_get_spending_transactions(user_pk, user_sk):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Transaction
    conn = connect()

    out = [([user_pk], 1)]
    tx1 = Transaction.create([user_pk], out * 3)
    tx1.sign([user_sk])
    inputs = tx1.to_inputs()
    tx2 = Transaction.transfer([inputs[0]], out, tx1.id)
    tx3 = Transaction.transfer([inputs[1]], out, tx1.id)
    tx4 = Transaction.transfer([inputs[2]], out, tx1.id)
    txns = [tx.to_dict() for tx in [tx1, tx2, tx3, tx4]]
    conn.db.transactions.insert_many(txns)

    links = [inputs[0].fulfills.to_dict(), inputs[2].fulfills.to_dict()]
    txns = list(query.get_spending_transactions(conn, links))

    # tx3 not a member because input 1 not asked for
    assert txns == [tx2.to_dict(), tx4.to_dict()]
예제 #42
0
def test_validation_with_transaction_buffer(b):
    from bigchaindb.common.crypto import generate_key_pair
    from bigchaindb.models import Transaction

    priv_key, pub_key = generate_key_pair()

    create_tx = Transaction.create([pub_key], [([pub_key], 10)]).sign([priv_key])
    transfer_tx = Transaction.transfer(create_tx.to_inputs(),
                                       [([pub_key], 10)],
                                       asset_id=create_tx.id).sign([priv_key])
    double_spend = Transaction.transfer(create_tx.to_inputs(),
                                        [([pub_key], 10)],
                                        asset_id=create_tx.id).sign([priv_key])

    assert b.is_valid_transaction(create_tx)
    assert b.is_valid_transaction(transfer_tx, [create_tx])

    assert not b.is_valid_transaction(create_tx, [create_tx])
    assert not b.is_valid_transaction(transfer_tx, [create_tx, transfer_tx])
    assert not b.is_valid_transaction(double_spend, [create_tx, transfer_tx])
def test_asset_transfer(b, signed_create_tx, user_pk, user_sk):
    from bigchaindb.models import Transaction

    tx_transfer = Transaction.transfer(signed_create_tx.to_inputs(),
                                       [([user_pk], 1)], signed_create_tx.id)
    tx_transfer_signed = tx_transfer.sign([user_sk])

    b.store_bulk_transactions([signed_create_tx])

    assert tx_transfer_signed.validate(b) == tx_transfer_signed
    assert tx_transfer_signed.asset['id'] == signed_create_tx.id
예제 #44
0
def test_get_spending_transactions(user_pk, user_sk):
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Transaction
    conn = connect()

    out = [([user_pk], 1)]
    tx1 = Transaction.create([user_pk], out * 3)
    tx1.sign([user_sk])
    inputs = tx1.to_inputs()
    tx2 = Transaction.transfer([inputs[0]], out, tx1.id).sign([user_sk])
    tx3 = Transaction.transfer([inputs[1]], out, tx1.id).sign([user_sk])
    tx4 = Transaction.transfer([inputs[2]], out, tx1.id).sign([user_sk])
    txns = [deepcopy(tx.to_dict()) for tx in [tx1, tx2, tx3, tx4]]
    conn.db.transactions.insert_many(txns)

    links = [inputs[0].fulfills.to_dict(), inputs[2].fulfills.to_dict()]
    txns = list(query.get_spending_transactions(conn, links))

    # tx3 not a member because input 1 not asked for
    assert txns == [tx2.to_dict(), tx4.to_dict()]
예제 #45
0
def test_asset_transfer(b, signed_create_tx, user_pk, user_sk):
    from bigchaindb.models import Transaction

    tx_transfer = Transaction.transfer(signed_create_tx.to_inputs(), [([user_pk], 1)],
                                       signed_create_tx.id)
    tx_transfer_signed = tx_transfer.sign([user_sk])

    b.store_bulk_transactions([signed_create_tx])

    assert tx_transfer_signed.validate(b) == tx_transfer_signed
    assert tx_transfer_signed.asset['id'] == signed_create_tx.id
예제 #46
0
def test_validation_with_transaction_buffer(b):
    from bigchaindb.common.crypto import generate_key_pair
    from bigchaindb.models import Transaction

    priv_key, pub_key = generate_key_pair()

    create_tx = Transaction.create([pub_key], [([pub_key], 10)]).sign([priv_key])
    transfer_tx = Transaction.transfer(create_tx.to_inputs(),
                                       [([pub_key], 10)],
                                       asset_id=create_tx.id).sign([priv_key])
    double_spend = Transaction.transfer(create_tx.to_inputs(),
                                        [([pub_key], 10)],
                                        asset_id=create_tx.id).sign([priv_key])

    assert b.is_valid_transaction(create_tx)
    assert b.is_valid_transaction(transfer_tx, [create_tx])

    assert not b.is_valid_transaction(create_tx, [create_tx])
    assert not b.is_valid_transaction(transfer_tx, [create_tx, transfer_tx])
    assert not b.is_valid_transaction(double_spend, [create_tx, transfer_tx])
예제 #47
0
def test_multiple_in_different_transactions(alice, b, user_pk, user_sk):
    from bigchaindb.models import Transaction

    # CREATE divisible asset
    # `b` creates a divisible asset and assigns 50 shares to `b` and
    # 50 shares to `user_pk`
    tx_create = Transaction.create([alice.public_key],
                                   [([user_pk], 50), ([alice.public_key], 50)],
                                   asset={'name': random.random()})
    tx_create_signed = tx_create.sign([alice.private_key])

    # TRANSFER divisible asset
    # `b` transfers its 50 shares to `user_pk`
    # after this transaction `user_pk` will have a total of 100 shares
    # split across two different transactions
    tx_transfer1 = Transaction.transfer(tx_create.to_inputs([1]),
                                        [([user_pk], 50)],
                                        asset_id=tx_create.id)
    tx_transfer1_signed = tx_transfer1.sign([alice.private_key])

    # TRANSFER
    # `user_pk` combines two different transaction with 50 shares each and
    # transfers a total of 100 shares back to `b`
    tx_transfer2 = Transaction.transfer(tx_create.to_inputs([0]) +
                                        tx_transfer1.to_inputs([0]),
                                        [([alice.private_key], 100)],
                                        asset_id=tx_create.id)
    tx_transfer2_signed = tx_transfer2.sign([user_sk])

    b.store_bulk_transactions(
        [tx_create_signed, tx_transfer1_signed, tx_transfer2_signed])

    assert tx_transfer2_signed.validate(b) == tx_transfer2_signed
    assert len(tx_transfer2_signed.outputs) == 1
    assert tx_transfer2_signed.outputs[0].amount == 100
    assert len(tx_transfer2_signed.inputs) == 2

    fid0_input = tx_transfer2_signed.inputs[0].fulfills.txid
    fid1_input = tx_transfer2_signed.inputs[1].fulfills.txid
    assert fid0_input == tx_create.id
    assert fid1_input == tx_transfer1.id
예제 #48
0
def test_get_spending_transactions_multiple_inputs():
    from bigchaindb.backend import connect, query
    from bigchaindb.models import Transaction
    from bigchaindb.common.crypto import generate_key_pair
    conn = connect()
    (alice_sk, alice_pk) = generate_key_pair()
    (bob_sk, bob_pk) = generate_key_pair()
    (carol_sk, carol_pk) = generate_key_pair()

    out = [([alice_pk], 9)]
    tx1 = Transaction.create([alice_pk], out).sign([alice_sk])

    inputs1 = tx1.to_inputs()
    tx2 = Transaction.transfer([inputs1[0]],
                               [([alice_pk], 6), ([bob_pk], 3)],
                               tx1.id).sign([alice_sk])

    inputs2 = tx2.to_inputs()
    tx3 = Transaction.transfer([inputs2[0]],
                               [([bob_pk], 3), ([carol_pk], 3)],
                               tx1.id).sign([alice_sk])

    inputs3 = tx3.to_inputs()
    tx4 = Transaction.transfer([inputs2[1], inputs3[0]],
                               [([carol_pk], 6)],
                               tx1.id).sign([bob_sk])

    txns = [deepcopy(tx.to_dict()) for tx in [tx1, tx2, tx3, tx4]]
    conn.db.transactions.insert_many(txns)

    links = [
        ({'transaction_id': tx2.id, 'output_index': 0}, 1, [tx3.id]),
        ({'transaction_id': tx2.id, 'output_index': 1}, 1, [tx4.id]),
        ({'transaction_id': tx3.id, 'output_index': 0}, 1, [tx4.id]),
        ({'transaction_id': tx3.id, 'output_index': 1}, 0, None),
    ]
    for l, num, match in links:
        txns = list(query.get_spending_transactions(conn, [l]))
        assert len(txns) == num
        if len(txns):
            assert [tx['id'] for tx in txns] == match
예제 #49
0
def test_asset_transfer(b, user_pk, user_sk):
    from bigchaindb.models import Transaction

    tx_input = b.get_owned_ids(user_pk).pop()
    tx_create = b.get_transaction(tx_input.txid)

    tx_transfer = Transaction.transfer(tx_create.to_inputs(), [([user_pk], 1)],
                                       tx_create.id)
    tx_transfer_signed = tx_transfer.sign([user_sk])

    assert tx_transfer_signed.validate(b) == tx_transfer_signed
    assert tx_transfer_signed.asset['id'] == tx_create.id
예제 #50
0
def test_multiple_in_different_transactions(alice, b, user_pk, user_sk):
    from bigchaindb.models import Transaction

    # CREATE divisible asset
    # `b` creates a divisible asset and assigns 50 shares to `b` and
    # 50 shares to `user_pk`
    tx_create = Transaction.create([alice.public_key], [([user_pk], 50), ([alice.public_key], 50)],
                                   asset={'name': random.random()})
    tx_create_signed = tx_create.sign([alice.private_key])

    # TRANSFER divisible asset
    # `b` transfers its 50 shares to `user_pk`
    # after this transaction `user_pk` will have a total of 100 shares
    # split across two different transactions
    tx_transfer1 = Transaction.transfer(tx_create.to_inputs([1]),
                                        [([user_pk], 50)],
                                        asset_id=tx_create.id)
    tx_transfer1_signed = tx_transfer1.sign([alice.private_key])

    # TRANSFER
    # `user_pk` combines two different transaction with 50 shares each and
    # transfers a total of 100 shares back to `b`
    tx_transfer2 = Transaction.transfer(tx_create.to_inputs([0]) +
                                        tx_transfer1.to_inputs([0]),
                                        [([alice.private_key], 100)],
                                        asset_id=tx_create.id)
    tx_transfer2_signed = tx_transfer2.sign([user_sk])

    b.store_bulk_transactions([tx_create_signed, tx_transfer1_signed])

    assert tx_transfer2_signed.validate(b) == tx_transfer2_signed
    assert len(tx_transfer2_signed.outputs) == 1
    assert tx_transfer2_signed.outputs[0].amount == 100
    assert len(tx_transfer2_signed.inputs) == 2

    fid0_input = tx_transfer2_signed.inputs[0].fulfills.txid
    fid1_input = tx_transfer2_signed.inputs[1].fulfills.txid
    assert fid0_input == tx_create.id
    assert fid1_input == tx_transfer1.id
예제 #51
0
def test_validate_transfer_asset_id_mismatch(b, signed_create_tx, user_pk, user_sk):
    from bigchaindb.common.exceptions import AssetIdMismatch
    from bigchaindb.models import Transaction

    tx_transfer = Transaction.transfer(signed_create_tx.to_inputs(), [([user_pk], 1)],
                                       signed_create_tx.id)
    tx_transfer.asset['id'] = 'a' * 64
    tx_transfer_signed = tx_transfer.sign([user_sk])

    b.store_bulk_transactions([signed_create_tx])

    with pytest.raises(AssetIdMismatch):
        tx_transfer_signed.validate(b)
예제 #52
0
    def test_non_create_input_not_found(self, b, user_pk):
        from cryptoconditions import Ed25519Sha256
        from bigchaindb.common.exceptions import InputDoesNotExist
        from bigchaindb.common.transaction import Input, TransactionLink
        from bigchaindb.models import Transaction

        # Create an input for a non existing transaction
        input = Input(Ed25519Sha256(public_key=b58decode(user_pk)),
                      [user_pk],
                      TransactionLink('somethingsomething', 0))
        tx = Transaction.transfer([input], [([user_pk], 1)],
                                  asset_id='mock_asset_link')
        with pytest.raises(InputDoesNotExist):
            tx.validate(b)
예제 #53
0
def test_post_transfer_transaction_endpoint(client, user_pk, user_sk, posted_create_tx):
    from bigchaindb.models import Transaction

    transfer_tx = Transaction.transfer(posted_create_tx.to_inputs(),
                                       [([user_pk], 1)],
                                       asset_id=posted_create_tx.id)
    transfer_tx = transfer_tx.sign([user_sk])

    res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))

    assert res.status_code == 202

    assert res.json['inputs'][0]['owners_before'][0] == user_pk
    assert res.json['outputs'][0]['public_keys'][0] == user_pk
예제 #54
0
def test_post_invalid_transfer_transaction_returns_400(client, user_pk, posted_create_tx):
    from bigchaindb.models import Transaction
    from bigchaindb.common.exceptions import InvalidSignature

    transfer_tx = Transaction.transfer(posted_create_tx.to_inputs(),
                                       [([user_pk], 1)],
                                       asset_id=posted_create_tx.id)
    transfer_tx._hash()

    res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))
    expected_status_code = 400
    expected_error_message = 'Invalid transaction ({}): {}'.format(
        InvalidSignature.__name__, 'Transaction signature is invalid.')
    assert res.status_code == expected_status_code
    assert res.json['message'] == expected_error_message
예제 #55
0
    def test_transfer_single_owner_single_input(self, b, inputs, user_pk,
                                                user_sk):
        from bigchaindb.common import crypto
        from bigchaindb.models import Transaction

        user2_sk, user2_pk = crypto.generate_key_pair()

        tx_link = b.fastquery.get_outputs_by_public_key(user_pk).pop()
        input_tx = b.get_transaction(tx_link.txid)
        inputs = input_tx.to_inputs()
        tx = Transaction.transfer(inputs, [([user2_pk], 1)],
                                  asset_id=input_tx.id)
        tx = tx.sign([user_sk])

        # validate transaction
        tx.validate(b)
        assert len(tx.inputs) == 1
        assert len(tx.outputs) == 1
예제 #56
0
def test_validation_worker_process_multiple_transactions(b):
    import multiprocessing as mp
    from bigchaindb.parallel_validation import ValidationWorker, RESET, EXIT

    keypair = generate_key_pair()
    create_tx, transfer_tx = generate_create_and_transfer(keypair)
    double_spend = Transaction.transfer(
            create_tx.to_inputs(),
            [([keypair.public_key], 10)],
            asset_id=create_tx.id).sign([keypair.private_key])

    in_queue, results_queue = mp.Queue(), mp.Queue()
    vw = ValidationWorker(in_queue, results_queue)

    # Note: in the following instructions, the worker will encounter two
    # `RESET` messages, and an `EXIT` message. When a worker processes a
    # `RESET` message, it forgets all transactions it has validated. This allow
    # us to re-validate the same transactions. This won't happen in real life,
    # but it's quite handy to check if the worker actually forgot about the
    # past transactions (if not, it will return `False` because the
    # transactions look like a double spend).
    # `EXIT` makes the worker to stop the infinite loop.
    in_queue.put((0, create_tx.to_dict()))
    in_queue.put((10, transfer_tx.to_dict()))
    in_queue.put((20, double_spend.to_dict()))
    in_queue.put(RESET)
    in_queue.put((0, create_tx.to_dict()))
    in_queue.put((5, transfer_tx.to_dict()))
    in_queue.put(RESET)
    in_queue.put((20, create_tx.to_dict()))
    in_queue.put((25, double_spend.to_dict()))
    in_queue.put((30, transfer_tx.to_dict()))
    in_queue.put(EXIT)

    vw.run()

    assert results_queue.get() == (0, create_tx)
    assert results_queue.get() == (10, transfer_tx)
    assert results_queue.get() == (20, False)
    assert results_queue.get() == (0, create_tx)
    assert results_queue.get() == (5, transfer_tx)
    assert results_queue.get() == (20, create_tx)
    assert results_queue.get() == (25, double_spend)
    assert results_queue.get() == (30, False)