示例#1
0
def test_deliver_tx__valid_create_updates_db_and_emits_event(b, init_chain_request):
    import multiprocessing as mp
    from bigchaindb import App
    from bigchaindb.models import Transaction
    from bigchaindb.common.crypto import generate_key_pair

    alice = generate_key_pair()
    bob = generate_key_pair()
    events = mp.Queue()

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

    app = App(b, events)

    app.init_chain(init_chain_request)

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)

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

    app.end_block(RequestEndBlock(height=99))
    app.commit()
    assert b.get_transaction(tx.id).id == tx.id
    block_event = events.get()
    assert block_event.data['transactions'] == [tx]
示例#2
0
def test_init_chain_ignores_invalid_init_chain_requests(b):
    validators = [generate_validator()]
    request = generate_init_chain_request('chain-XYZ', validators)
    res = App(b).init_chain(request)
    assert res == ResponseInitChain()

    validator_set = query.get_validator_set(b.connection)

    invalid_requests = [
        request,  # the same request again
        # different validator set
        generate_init_chain_request('chain-XYZ'),
        # different chain ID
        generate_init_chain_request('chain-ABC', validators),
    ]
    for r in invalid_requests:
        with pytest.raises(SystemExit):
            App(b).init_chain(r)
        # assert nothing changed - neither validator set, nor chain ID
        new_validator_set = query.get_validator_set(b.connection)
        assert new_validator_set == validator_set
        new_chain_id = query.get_latest_abci_chain(b.connection)['chain_id']
        assert new_chain_id == 'chain-XYZ'
        assert query.get_latest_block(b.connection) == {
            'height': 0,
            'app_hash': '',
            'transactions': [],
        }
示例#3
0
def test_deliver_tx__valid_create_updates_db(b, init_chain_request):
    from bigchaindb import App
    from bigchaindb.models import Transaction
    from bigchaindb.common.crypto import generate_key_pair

    alice = generate_key_pair()
    bob = generate_key_pair()

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

    app = App(b)

    app.init_chain(init_chain_request)

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)

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

    app.end_block(RequestEndBlock(height=99))
    app.commit()
    assert b.get_transaction(tx.id).id == tx.id
示例#4
0
def test_check_tx__unsigned_create_is_error(b):
    from bigchaindb import App
    from bigchaindb.models import Transaction
    from bigchaindb.common.crypto import generate_key_pair

    alice = generate_key_pair()
    bob = generate_key_pair()

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

    app = App(b)
    result = app.check_tx(encode_tx_to_bytes(tx))
    assert result.code == CodeTypeError
示例#5
0
def test_end_block_return_validator_updates(b, init_chain_request):
    app = App(b)
    app.init_chain(init_chain_request)

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)

    # generate a block containing a concluded validator election
    validators = generate_validators([1] * 4)
    b.store_validator_set(1, [v['storage'] for v in validators])

    new_validator = generate_validators([1])[0]

    public_key = validators[0]['public_key']
    private_key = validators[0]['private_key']
    voter_keys = [v['private_key'] for v in validators]

    election, votes = generate_election(b, ValidatorElection, public_key,
                                        private_key, new_validator['election'],
                                        voter_keys)
    b.store_block(
        Block(height=1, transactions=[election.id], app_hash='')._asdict())
    b.store_bulk_transactions([election])
    Election.process_block(b, 1, [election])

    app.block_transactions = votes

    resp = app.end_block(RequestEndBlock(height=2))
    assert resp.validator_updates[0].power == new_validator['election'][
        'power']
    expected = bytes.fromhex(new_validator['election']['public_key']['value'])
    assert expected == resp.validator_updates[0].pub_key.data
示例#6
0
def test_check_tx__unsigned_create_is_error(b):
    from bigchaindb import App
    from bigchaindb.models import Transaction
    from bigchaindb.common.crypto import generate_key_pair

    alice = generate_key_pair()
    bob = generate_key_pair()

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

    app = App(b)
    result = app.check_tx(encode_tx_to_bytes(tx))
    assert result.code == CodeTypeError
示例#7
0
def test_info(b):
    r = RequestInfo(version=__tm_supported_versions__[0])
    app = App(b)

    res = app.info(r)
    assert res.last_block_height == 0
    assert res.last_block_app_hash == b''

    b.store_block(Block(app_hash='1', height=1, transactions=[])._asdict())
    res = app.info(r)
    assert res.last_block_height == 1
    assert res.last_block_app_hash == b'1'

    # simulate a migration and assert the height is shifted
    b.store_abci_chain(2, 'chain-XYZ')
    app = App(b)
    b.store_block(Block(app_hash='2', height=2, transactions=[])._asdict())
    res = app.info(r)
    assert res.last_block_height == 0
    assert res.last_block_app_hash == b'2'

    b.store_block(Block(app_hash='3', height=3, transactions=[])._asdict())
    res = app.info(r)
    assert res.last_block_height == 1
    assert res.last_block_app_hash == b'3'

    # it's always the latest migration that is taken into account
    b.store_abci_chain(4, 'chain-XYZ-new')
    app = App(b)
    b.store_block(Block(app_hash='4', height=4, transactions=[])._asdict())
    res = app.info(r)
    assert res.last_block_height == 0
    assert res.last_block_app_hash == b'4'
def test_exit_when_tm_ver_not_supported(b):
    from bigchaindb import App

    app = App(b)
    p = ProtocolHandler(app)

    with pytest.raises(SystemExit):
        p.process('info', types.Request(info=types.RequestInfo(version='2')))
示例#9
0
def test_end_block_return_validator_updates(b):
    from bigchaindb import App
    from bigchaindb.backend import query
    from bigchaindb.core import encode_validator
    from bigchaindb.backend.query import VALIDATOR_UPDATE_ID

    app = App(b)
    app.init_chain(['ignore'])

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)

    validator = {
        'pub_key': {
            'type':
            'ed25519',
            'data':
            'B0E42D2589A455EAD339A035D6CE1C8C3E25863F268120AA0162AD7D003A4014'
        },
        'power': 10
    }
    validator_update = {
        'validator': validator,
        'update_id': VALIDATOR_UPDATE_ID
    }
    query.store_validator_update(b.connection, validator_update)

    resp = app.end_block(RequestEndBlock(height=99))
    assert resp.validator_updates[0] == encode_validator(validator)

    updates = b.get_validator_update()
    assert updates == []
示例#10
0
def test_end_block_return_validator_updates(b, init_chain_request):
    app = App(b)
    app.init_chain(init_chain_request)

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)

    # generate a block containing a concluded validator election
    validators = generate_validators([1] * 4)
    b.store_validator_set(1, [v['storage'] for v in validators])

    new_validator = generate_validators([1])[0]

    public_key = validators[0]['public_key']
    private_key = validators[0]['private_key']
    voter_keys = [v['private_key'] for v in validators]

    election, votes = generate_election(b,
                                        ValidatorElection,
                                        public_key, private_key,
                                        new_validator['election'],
                                        voter_keys)
    b.store_block(Block(height=1, transactions=[election.id],
                        app_hash='')._asdict())
    b.store_bulk_transactions([election])
    Election.process_block(b, 1, [election])

    app.block_transactions = votes

    resp = app.end_block(RequestEndBlock(height=2))
    assert resp.validator_updates[0].power == new_validator['election']['power']
    expected = bytes.fromhex(new_validator['election']['public_key']['value'])
    assert expected == resp.validator_updates[0].pub_key.data
示例#11
0
def test_init_chain_successfully_registers_chain(b):
    request = generate_init_chain_request('chain-XYZ')
    res = App(b).init_chain(request)
    assert res == ResponseInitChain()
    chain = query.get_latest_abci_chain(b.connection)
    assert chain == {'height': 0, 'chain_id': 'chain-XYZ', 'is_synced': True}
    assert query.get_latest_block(b.connection) == {
        'height': 0,
        'app_hash': '',
        'transactions': [],
    }
示例#12
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
示例#13
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
示例#14
0
def test_end_block_return_validator_updates(b, init_chain_request):
    from bigchaindb import App
    from bigchaindb.backend import query
    from bigchaindb.core import encode_validator
    from bigchaindb.backend.query import VALIDATOR_UPDATE_ID

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

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)

    validator = {'pub_key': {'type': 'ed25519',
                             'data': 'B0E42D2589A455EAD339A035D6CE1C8C3E25863F268120AA0162AD7D003A4014'},
                 'power': 10}
    validator_update = {'validator': validator,
                        'update_id': VALIDATOR_UPDATE_ID}
    query.store_validator_update(b.connection, validator_update)

    resp = app.end_block(RequestEndBlock(height=99))
    assert resp.validator_updates[0] == encode_validator(validator)

    updates = b.approved_update()
    assert not updates
示例#15
0
def test_commit_aborts_if_chain_is_not_synced(b):
    b.store_abci_chain(0, 'chain-XYZ', False)

    with pytest.raises(SystemExit):
        App(b).commit()
示例#16
0
def test_end_block_aborts_if_chain_is_not_synced(b):
    b.store_abci_chain(0, 'chain-XYZ', False)

    with pytest.raises(SystemExit):
        App(b).info(RequestEndBlock())
示例#17
0
def test_deliver_tx_aborts_if_chain_is_not_synced(b):
    b.store_abci_chain(0, 'chain-XYZ', False)

    with pytest.raises(SystemExit):
        App(b).deliver_tx('some bytes')
示例#18
0
def test_store_pre_commit_state_in_end_block(b, alice, init_chain_request):
    from bigchaindb import App
    from bigchaindb.backend import query
    from bigchaindb.models import Transaction

    tx = Transaction.create([alice.public_key],
                            [([alice.public_key], 1)],
                            asset={'msg': 'live long and prosper'})\
                    .sign([alice.private_key])

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

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)
    app.deliver_tx(encode_tx_to_bytes(tx))
    app.end_block(RequestEndBlock(height=99))

    resp = query.get_pre_commit_state(b.connection)
    assert resp['height'] == 99
    assert resp['transactions'] == [tx.id]

    app.begin_block(begin_block)
    app.deliver_tx(encode_tx_to_bytes(tx))
    app.end_block(RequestEndBlock(height=100))
    resp = query.get_pre_commit_state(b.connection)
    assert resp['height'] == 100
    assert resp['transactions'] == [tx.id]

    # simulate a chain migration and assert the height is shifted
    b.store_abci_chain(100, 'new-chain')
    app = App(b)
    app.begin_block(begin_block)
    app.deliver_tx(encode_tx_to_bytes(tx))
    app.end_block(RequestEndBlock(height=1))
    resp = query.get_pre_commit_state(b.connection)
    assert resp['height'] == 101
    assert resp['transactions'] == [tx.id]
示例#19
0
def test_deliver_tx__double_spend_fails(b):
    from bigchaindb import App
    from bigchaindb.models import Transaction
    from bigchaindb.common.crypto import generate_key_pair

    alice = generate_key_pair()
    bob = generate_key_pair()

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

    app = App(b)
    app.init_chain(['ignore'])

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)

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

    app.end_block(RequestEndBlock(height=99))
    app.commit()

    assert b.get_transaction(tx.id).id == tx.id
    result = app.deliver_tx(encode_tx_to_bytes(tx))
    assert result.code == CodeTypeError
示例#20
0
def test_init_chain_recognizes_new_chain_after_migration(b):
    validators = [generate_validator()]
    request = generate_init_chain_request('chain-XYZ', validators)
    res = App(b).init_chain(request)
    assert res == ResponseInitChain()

    validator_set = query.get_validator_set(b.connection)['validators']

    # simulate a migration
    query.store_block(b.connection,
                      Block(app_hash='', height=1, transactions=[])._asdict())
    b.migrate_abci_chain()

    # the same or other mismatching requests are ignored
    invalid_requests = [
        request,
        generate_init_chain_request('unknown', validators),
        generate_init_chain_request('chain-XYZ'),
        generate_init_chain_request('chain-XYZ-migrated-at-height-1'),
    ]
    for r in invalid_requests:
        with pytest.raises(SystemExit):
            App(b).init_chain(r)
        assert query.get_latest_abci_chain(b.connection) == {
            'chain_id': 'chain-XYZ-migrated-at-height-1',
            'is_synced': False,
            'height': 2,
        }
        new_validator_set = query.get_validator_set(b.connection)['validators']
        assert new_validator_set == validator_set

    # a request with the matching chain ID and matching validator set
    # completes the migration
    request = generate_init_chain_request('chain-XYZ-migrated-at-height-1',
                                          validators)
    res = App(b).init_chain(request)
    assert res == ResponseInitChain()
    assert query.get_latest_abci_chain(b.connection) == {
        'chain_id': 'chain-XYZ-migrated-at-height-1',
        'is_synced': True,
        'height': 2,
    }
    assert query.get_latest_block(b.connection) == {
        'height': 2,
        'app_hash': '',
        'transactions': [],
    }

    # requests with old chain ID and other requests are ignored
    invalid_requests = [
        request,
        generate_init_chain_request('chain-XYZ', validators),
        generate_init_chain_request('chain-XYZ-migrated-at-height-1'),
    ]
    for r in invalid_requests:
        with pytest.raises(SystemExit):
            App(b).init_chain(r)
        assert query.get_latest_abci_chain(b.connection) == {
            'chain_id': 'chain-XYZ-migrated-at-height-1',
            'is_synced': True,
            'height': 2,
        }
        new_validator_set = query.get_validator_set(b.connection)['validators']
        assert new_validator_set == validator_set
        assert query.get_latest_block(b.connection) == {
            'height': 2,
            'app_hash': '',
            'transactions': [],
        }
示例#21
0
def test_begin_aborts_if_chain_is_not_synced(a, b):
    b.store_abci_chain(0, 'chain-XYZ', False)

    with pytest.raises(SystemExit):
        App(a, b).info(types.RequestBeginBlock())
示例#22
0
def test_store_pre_commit_state_in_end_block(b, alice):
    from bigchaindb import App
    from bigchaindb.backend import query
    from bigchaindb.models import Transaction
    from bigchaindb.backend.query import PRE_COMMIT_ID

    tx = Transaction.create([alice.public_key],
                            [([alice.public_key], 1)],
                            asset={'msg': 'live long and prosper'})\
                    .sign([alice.private_key])

    app = App(b)
    app.init_chain(['ignore'])

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)
    app.deliver_tx(encode_tx_to_bytes(tx))
    app.end_block(RequestEndBlock(height=99))

    resp = query.get_pre_commit_state(b.connection, PRE_COMMIT_ID)
    assert resp['commit_id'] == PRE_COMMIT_ID
    assert resp['height'] == 99
    assert resp['transactions'] == [tx.id]

    app.begin_block(begin_block)
    app.deliver_tx(encode_tx_to_bytes(tx))
    app.end_block(RequestEndBlock(height=100))
    resp = query.get_pre_commit_state(b.connection, PRE_COMMIT_ID)
    assert resp['commit_id'] == PRE_COMMIT_ID
    assert resp['height'] == 100
    assert resp['transactions'] == [tx.id]
示例#23
0
def test_info(b):
    r = RequestInfo(version=__tm_supported_versions__[0])
    app = App(b)

    res = app.info(r)
    assert res.last_block_height == 0
    assert res.last_block_app_hash == b''

    b.store_block(Block(app_hash='1', height=1, transactions=[])._asdict())
    res = app.info(r)
    assert res.last_block_height == 1
    assert res.last_block_app_hash == b'1'

    # simulate a migration and assert the height is shifted
    b.store_abci_chain(2, 'chain-XYZ')
    app = App(b)
    b.store_block(Block(app_hash='2', height=2, transactions=[])._asdict())
    res = app.info(r)
    assert res.last_block_height == 0
    assert res.last_block_app_hash == b'2'

    b.store_block(Block(app_hash='3', height=3, transactions=[])._asdict())
    res = app.info(r)
    assert res.last_block_height == 1
    assert res.last_block_app_hash == b'3'

    # it's always the latest migration that is taken into account
    b.store_abci_chain(4, 'chain-XYZ-new')
    app = App(b)
    b.store_block(Block(app_hash='4', height=4, transactions=[])._asdict())
    res = app.info(r)
    assert res.last_block_height == 0
    assert res.last_block_app_hash == b'4'
示例#24
0
def test_store_pre_commit_state_in_end_block(b, alice, init_chain_request):
    from bigchaindb import App
    from bigchaindb.backend import query
    from bigchaindb.models import Transaction

    tx = Transaction.create([alice.public_key],
                            [([alice.public_key], 1)],
                            asset={'msg': 'live long and prosper'})\
                    .sign([alice.private_key])

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

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)
    app.deliver_tx(encode_tx_to_bytes(tx))
    app.end_block(RequestEndBlock(height=99))

    resp = query.get_pre_commit_state(b.connection)
    assert resp['height'] == 99
    assert resp['transactions'] == [tx.id]

    app.begin_block(begin_block)
    app.deliver_tx(encode_tx_to_bytes(tx))
    app.end_block(RequestEndBlock(height=100))
    resp = query.get_pre_commit_state(b.connection)
    assert resp['height'] == 100
    assert resp['transactions'] == [tx.id]

    # simulate a chain migration and assert the height is shifted
    b.store_abci_chain(100, 'new-chain')
    app = App(b)
    app.begin_block(begin_block)
    app.deliver_tx(encode_tx_to_bytes(tx))
    app.end_block(RequestEndBlock(height=1))
    resp = query.get_pre_commit_state(b.connection)
    assert resp['height'] == 101
    assert resp['transactions'] == [tx.id]
示例#25
0
def test_app(tb, init_chain_request):
    from bigchaindb import App
    from bigchaindb.tendermint_utils import calculate_hash
    from bigchaindb.common.crypto import generate_key_pair
    from bigchaindb.models import Transaction

    b = tb
    app = App(b)
    p = ProtocolHandler(app)

    data = p.process('info',
                     types.Request(info=types.RequestInfo(version='2')))
    res = next(read_messages(BytesIO(data), types.Response))
    assert res
    assert res.info.last_block_app_hash == b''
    assert res.info.last_block_height == 0
    assert not b.get_latest_block()

    p.process('init_chain', types.Request(init_chain=init_chain_request))
    block0 = b.get_latest_block()
    assert block0
    assert block0['height'] == 0
    assert block0['app_hash'] == ''

    pk = codecs.encode(init_chain_request.validators[0].pub_key.data,
                       'base64').decode().strip('\n')
    [validator] = b.get_validators(height=1)
    assert validator['pub_key']['data'] == pk
    assert validator['voting_power'] == 10

    alice = generate_key_pair()
    bob = generate_key_pair()
    tx = Transaction.create([alice.public_key],
                            [([bob.public_key], 1)])\
                    .sign([alice.private_key])
    etxn = json.dumps(tx.to_dict()).encode('utf8')

    r = types.Request(check_tx=types.RequestCheckTx(tx=etxn))
    data = p.process('check_tx', r)
    res = next(read_messages(BytesIO(data), types.Response))
    assert res
    assert res.check_tx.code == 0

    r = types.Request()
    r.begin_block.hash = b''
    p.process('begin_block', r)

    r = types.Request(deliver_tx=types.RequestDeliverTx(tx=etxn))
    data = p.process('deliver_tx', r)
    res = next(read_messages(BytesIO(data), types.Response))
    assert res
    assert res.deliver_tx.code == 0

    new_block_txn_hash = calculate_hash([tx.id])

    r = types.Request(end_block=types.RequestEndBlock(height=1))
    data = p.process('end_block', r)
    res = next(read_messages(BytesIO(data), types.Response))
    assert res
    assert 'end_block' == res.WhichOneof('value')

    new_block_hash = calculate_hash([block0['app_hash'], new_block_txn_hash])

    data = p.process('commit', None)
    res = next(read_messages(BytesIO(data), types.Response))
    assert res.commit.data == new_block_hash.encode('utf-8')
    assert b.get_transaction(tx.id).id == tx.id

    block0 = b.get_latest_block()
    assert block0
    assert block0['height'] == 1
    assert block0['app_hash'] == new_block_hash

    # empty block should not update height
    r = types.Request()
    r.begin_block.hash = new_block_hash.encode('utf-8')
    p.process('begin_block', r)

    r = types.Request()
    r.end_block.height = 2
    p.process('end_block', r)

    data = p.process('commit', None)
    res = next(read_messages(BytesIO(data), types.Response))
    assert res.commit.data == new_block_hash.encode('utf-8')

    block0 = b.get_latest_block()
    assert block0
    assert block0['height'] == 1

    # when empty block is generated hash of previous block should be returned
    assert block0['app_hash'] == new_block_hash
示例#26
0
def test_deliver_tx__valid_create_updates_db_and_emits_event(
        b, init_chain_request):
    import multiprocessing as mp
    from bigchaindb import App
    from bigchaindb.models import Transaction
    from bigchaindb.common.crypto import generate_key_pair

    alice = generate_key_pair()
    bob = generate_key_pair()
    events = mp.Queue()

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

    app = App(b, events)

    app.init_chain(init_chain_request)

    begin_block = RequestBeginBlock()
    app.begin_block(begin_block)

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

    app.end_block(RequestEndBlock(height=99))
    app.commit()
    assert b.get_transaction(tx.id).id == tx.id
    block_event = events.get()
    assert block_event.data['transactions'] == [tx]