Example #1
0
    def commit(self):
        """Store the new height and along with block hash."""

        self.abort_if_abci_chain_is_not_synced()

        data = self.block_txn_hash.encode('utf-8')

        # register a new block only when new transactions are received
        if self.block_txn_ids:
            self.bigchaindb.store_bulk_transactions(self.block_transactions)

        block = Block(app_hash=self.block_txn_hash,
                      height=self.new_height,
                      transactions=self.block_txn_ids)
        # NOTE: storing the block should be the last operation during commit
        # this effects crash recovery. Refer BEP#8 for details
        self.bigchaindb.store_block(block._asdict())

        logger.debug('Commit-ing new block with hash: apphash=%s ,'
                     'height=%s, txn ids=%s', data, self.new_height,
                     self.block_txn_ids)

        if self.events_queue:
            event = Event(EventTypes.BLOCK_VALID, {
                'height': self.new_height,
                'transactions': self.block_transactions
            })
            self.events_queue.put(event)

        return ResponseCommit(data=data)
Example #2
0
    def commit(self):
        """Store the new height and along with block hash."""

        self.abort_if_abci_chain_is_not_synced()

        data = self.block_txn_hash.encode('utf-8')

        # register a new block only when new transactions are received
        if self.block_txn_ids:
            self.bigchaindb.store_bulk_transactions(self.block_transactions)

        block = Block(app_hash=self.block_txn_hash,
                      height=self.new_height,
                      transactions=self.block_txn_ids)
        # NOTE: storing the block should be the last operation during commit
        # this effects crash recovery. Refer BEP#8 for details
        self.bigchaindb.store_block(block._asdict())

        logger.debug(
            'Commit-ing new block with hash: apphash=%s ,'
            'height=%s, txn ids=%s', data, self.new_height, self.block_txn_ids)

        if self.events_queue:
            event = Event(EventTypes.BLOCK_VALID, {
                'height': self.new_height,
                'transactions': self.block_transactions
            })
            self.events_queue.put(event)

        return ResponseCommit(data=data)
Example #3
0
def test_chain_migration_election_show_shows_inconclusive(b):
    validators = generate_validators([1] * 4)
    b.store_validator_set(1, [v['storage'] for v in validators])

    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, ChainMigrationElection, public_key,
                                        private_key, {}, voter_keys)

    assert not run_election_show(Namespace(election_id=election.id), b)

    Election.process_block(b, 1, [election])
    b.store_bulk_transactions([election])

    assert run_election_show(Namespace(election_id=election.id), b) == \
        'status=ongoing'

    b.store_block(Block(height=1, transactions=[], app_hash='')._asdict())
    b.store_validator_set(2, [v['storage'] for v in validators])

    assert run_election_show(Namespace(election_id=election.id), b) == \
        'status=ongoing'

    b.store_block(Block(height=2, transactions=[], app_hash='')._asdict())
    # TODO insert yet another block here when upgrading to Tendermint 0.22.4.

    assert run_election_show(Namespace(election_id=election.id), b) == \
        'status=inconclusive'
Example #4
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'
Example #5
0
    def init_chain(self, genesis):
        """Initialize chain with block of height 0"""

        validator_set = [decode_validator(v) for v in genesis.validators]
        block = Block(app_hash='', height=0, transactions=[])
        self.bigchaindb.store_block(block._asdict())
        self.bigchaindb.store_validator_set(1, validator_set)
        return ResponseInitChain()
Example #6
0
def test_store_block():
    from bigchaindb.backend import connect, query
    from bigchaindb.lib import Block
    conn = connect()

    block = Block(app_hash='random_utxo', height=3, transactions=[])
    query.store_block(conn, block._asdict())
    cursor = conn.db.blocks.find({}, projection={'_id': False})
    assert cursor.count() == 1
Example #7
0
def ongoing_validator_election_2(b, valid_upsert_validator_election_2, ed25519_node_keys):
    validators = b.get_validators(height=1)
    genesis_validators = {'validators': validators,
                          'height': 0,
                          'election_id': None}
    query.store_validator_set(b.connection, genesis_validators)

    b.store_bulk_transactions([valid_upsert_validator_election_2])
    block_1 = Block(app_hash='hash_2', height=1, transactions=[valid_upsert_validator_election_2.id])
    b.store_block(block_1._asdict())
    return valid_upsert_validator_election_2
Example #8
0
def test_get_block():
    from bigchaindb.backend import connect, query
    from bigchaindb.lib import Block
    conn = connect()

    block = Block(app_hash='random_utxo', height=3, transactions=[])

    conn.db.blocks.insert_one(block._asdict())

    block = dict(query.get_block(conn, 3))
    assert block['height'] == 3
Example #9
0
def test_store_block():
    from bigchaindb.backend import connect, query
    from bigchaindb.lib import Block
    conn = connect()

    block = Block(app_hash='random_utxo',
                  height=3,
                  transactions=[])
    query.store_block(conn, block._asdict())
    cursor = conn.db.blocks.find({}, projection={'_id': False})
    assert cursor.count() == 1
Example #10
0
def ongoing_election(b, valid_election, ed25519_node_keys):
    validators = b.get_validators(height=1)
    genesis_validators = {'validators': validators,
                          'height': 0,
                          'election_id': None}
    query.store_validator_set(b.connection, genesis_validators)

    b.store_bulk_transactions([valid_election])
    block_1 = Block(app_hash='hash_1', height=1, transactions=[valid_election.id])
    b.store_block(block_1._asdict())
    return valid_election
Example #11
0
def ongoing_validator_election(b, valid_upsert_validator_election, ed25519_node_keys):
    validators = b.get_validators(height=1)
    genesis_validators = {'validators': validators,
                          'height': 0}
    query.store_validator_set(b.connection, genesis_validators)
    b.store_bulk_transactions([valid_upsert_validator_election])
    query.store_election(b.connection, valid_upsert_validator_election.id, 1,
                         is_concluded=False)
    block_1 = Block(app_hash='hash_1', height=1,
                    transactions=[valid_upsert_validator_election.id])
    b.store_block(block_1._asdict())
    return valid_upsert_validator_election
Example #12
0
def test_get_block():
    from bigchaindb.backend import connect, query
    from bigchaindb.lib import Block
    conn = connect()

    block = Block(app_hash='random_utxo',
                  height=3,
                  transactions=[])

    conn.db.blocks.insert_one(block._asdict())

    block = dict(query.get_block(conn, 3))
    assert block['height'] == 3
Example #13
0
def test_get_block_containing_transaction(b, client, alice):
    tx = Transaction.create([alice.public_key], [([alice.public_key], 1)],
                            asset={'cycle': 'hero'})
    tx = tx.sign([alice.private_key])
    b.store_bulk_transactions([tx])

    block = Block(app_hash='random_utxo', height=13, transactions=[tx.id])
    b.store_block(block._asdict())

    res = client.get('{}?transaction_id={}'.format(BLOCKS_ENDPOINT, tx.id))
    expected_response = [block.height]
    assert res.json == expected_response
    assert res.status_code == 200
def test_get_block_containing_transaction(b, client, alice):
    tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'})
    tx = tx.sign([alice.private_key])
    b.store_bulk_transactions([tx])

    block = Block(app_hash='random_utxo',
                  height=13,
                  transactions=[tx.id])
    b.store_block(block._asdict())

    res = client.get('{}?transaction_id={}'.format(BLOCKS_ENDPOINT, tx.id))
    expected_response = [block.height]
    assert res.json == expected_response
    assert res.status_code == 200
Example #15
0
def ongoing_validator_election(b, valid_upsert_validator_election,
                               ed25519_node_keys):
    validators = b.get_validators(height=1)
    genesis_validators = {'validators': validators, 'height': 0}
    query.store_validator_set(b.connection, genesis_validators)
    b.store_bulk_transactions([valid_upsert_validator_election])
    query.store_election(b.connection,
                         valid_upsert_validator_election.id,
                         1,
                         is_concluded=False)
    block_1 = Block(app_hash='hash_1',
                    height=1,
                    transactions=[valid_upsert_validator_election.id])
    b.store_block(block_1._asdict())
    return valid_upsert_validator_election
Example #16
0
    def init_chain(self, genesis):
        """Initialize chain upon genesis or a migration"""

        app_hash = ''
        height = 0

        known_chain = self.bigchaindb.get_latest_abci_chain()
        if known_chain is not None:
            chain_id = known_chain['chain_id']

            if known_chain['is_synced']:
                msg = f'Got invalid InitChain ABCI request ({genesis}) - ' + \
                      'the chain {chain_id} is already synced.'
                logger.error(msg)
                sys.exit(1)

            if chain_id != genesis.chain_id:
                validators = self.bigchaindb.get_validators()
                self.log_abci_migration_error(chain_id, validators)
                sys.exit(1)

            # set migration values for app hash and height
            block = self.bigchaindb.get_latest_block()
            app_hash = '' if block is None else block['app_hash']
            height = 0 if block is None else block['height'] + 1

        known_validators = self.bigchaindb.get_validators()
        validator_set = [
            vutils.decode_validator(v) for v in genesis.validators
        ]

        if known_validators and known_validators != validator_set:
            self.log_abci_migration_error(known_chain['chain_id'],
                                          known_validators)
            sys.exit(1)

        block = Block(app_hash=app_hash, height=height, transactions=[])
        self.bigchaindb.store_block(block._asdict())
        self.bigchaindb.store_validator_set(height + 1, validator_set)
        abci_chain_height = 0 if known_chain is None else known_chain['height']
        self.bigchaindb.store_abci_chain(abci_chain_height, genesis.chain_id,
                                         True)
        self.chain = {
            'height': abci_chain_height,
            'is_synced': True,
            'chain_id': genesis.chain_id
        }
        return ResponseInitChain()
Example #17
0
def inputs(user_pk, b, alice):
    from bigchaindb.models import Transaction
    # create blocks with transactions for `USER` to spend
    for height in range(1, 4):
        transactions = [
            Transaction.create(
                [alice.public_key],
                [([user_pk], 1)],
                metadata={'msg': random.random()},
            ).sign([alice.private_key])
            for _ in range(10)
        ]
        tx_ids = [tx.id for tx in transactions]
        block = Block(app_hash='hash'+str(height), height=height, transactions=tx_ids)
        b.store_block(block._asdict())
        b.store_bulk_transactions(transactions)
Example #18
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
Example #19
0
def test_chain_migration_election_show_shows_concluded(b):
    validators = generate_validators([1] * 4)
    b.store_validator_set(1, [v['storage'] for v in validators])

    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, ChainMigrationElection, public_key,
                                        private_key, {}, voter_keys)

    assert not run_election_show(Namespace(election_id=election.id), b)

    b.store_bulk_transactions([election])
    Election.process_block(b, 1, [election])

    assert run_election_show(Namespace(election_id=election.id), b) == \
        'status=ongoing'

    b.store_abci_chain(1, 'chain-X')
    b.store_block(
        Block(height=1,
              transactions=[v.id for v in votes],
              app_hash='last_app_hash')._asdict())
    Election.process_block(b, 2, votes)

    assert run_election_show(Namespace(election_id=election.id), b) == \
        f'''status=concluded
Example #20
0
def inputs(user_pk, b, alice):
    from bigchaindb.models import Transaction
    # create blocks with transactions for `USER` to spend
    for block in range(4):
        transactions = [
            Transaction.create(
                [alice_pubkey(alice)],
                [([user_pk], 1)],
                metadata={
                    'msg': random.random()
                },
            ).sign([alice_privkey(alice)]).to_dict() for _ in range(10)
        ]
        block = Block(app_hash='',
                      height=_get_height(b),
                      transactions=transactions)
        b.store_block(block._asdict())
def test_get_block_endpoint(tb, client, alice):
    b = tb
    tx = Transaction.create([alice.public_key], [([alice.public_key], 1)],
                            asset={'cycle': 'hero'})
    tx = tx.sign([alice.private_key])
    b.store_transaction(tx)

    block = Block(app_hash='random_utxo', height=31, transactions=[tx.id])
    b.store_block(block._asdict())

    res = client.get(BLOCKS_ENDPOINT + str(block.height))
    expected_response = {
        'height': block.height,
        'transactions': [tx.to_dict()]
    }
    assert res.json == expected_response
    assert res.status_code == 200
Example #22
0
def test_migrate_abci_chain_generates_new_chains(b, chain, block_height,
                                                 expected):
    b.store_abci_chain(*chain)
    b.store_block(
        Block(app_hash='', height=block_height, transactions=[])._asdict())
    b.migrate_abci_chain()
    latest_chain = b.get_latest_abci_chain()
    assert latest_chain == expected
Example #23
0
def test_rollback_pre_commit_state_after_crash(b):
    validators = generate_validators([1] * 4)
    b.store_validator_set(1, [v['storage'] for v in validators])
    b.store_block(Block(height=1, transactions=[], app_hash='')._asdict())

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

    migration_election, votes = generate_election(b, ChainMigrationElection,
                                                  public_key, private_key, {},
                                                  voter_keys)

    total_votes = votes
    txs = [migration_election, *votes]

    new_validator = generate_validators([1])[0]
    validator_election, votes = generate_election(b, ValidatorElection,
                                                  public_key, private_key,
                                                  new_validator['election'],
                                                  voter_keys)

    total_votes += votes
    txs += [validator_election, *votes]

    b.store_bulk_transactions(txs)
    b.store_abci_chain(2, 'new_chain')
    b.store_validator_set(2, [v['storage'] for v in validators])
    # TODO change to `4` when upgrading to Tendermint 0.22.4.
    b.store_validator_set(3, [new_validator['storage']])
    b.store_election(migration_election.id, 2, is_concluded=False)
    b.store_election(validator_election.id, 2, is_concluded=True)

    # no pre-commit state
    rollback(b)

    for tx in txs:
        assert b.get_transaction(tx.id)
    assert b.get_latest_abci_chain()
    assert len(b.get_validator_change()['validators']) == 1
    assert b.get_election(migration_election.id)
    assert b.get_election(validator_election.id)

    b.store_pre_commit_state({
        'height': 2,
        'transactions': [tx.id for tx in txs]
    })

    rollback(b)

    for tx in txs:
        assert not b.get_transaction(tx.id)
    assert not b.get_latest_abci_chain()
    assert len(b.get_validator_change()['validators']) == 4
    assert len(b.get_validator_change(2)['validators']) == 4
    assert not b.get_election(migration_election.id)
    assert not b.get_election(validator_election.id)
Example #24
0
    def init_chain(self, genesis):
        """Initialize chain upon genesis or a migration"""

        app_hash = ''
        height = 0

        known_chain = self.bigchaindb.get_latest_abci_chain()
        if known_chain is not None:
            chain_id = known_chain['chain_id']

            if known_chain['is_synced']:
                msg = f'Got invalid InitChain ABCI request ({genesis}) - ' + \
                      'the chain {chain_id} is already synced.'
                logger.error(msg)
                sys.exit(1)

            if chain_id != genesis.chain_id:
                validators = self.bigchaindb.get_validators()
                self.log_abci_migration_error(chain_id, validators)
                sys.exit(1)

            # set migration values for app hash and height
            block = self.bigchaindb.get_latest_block()
            app_hash = '' if block is None else block['app_hash']
            height = 0 if block is None else block['height'] + 1

        known_validators = self.bigchaindb.get_validators()
        validator_set = [vutils.decode_validator(v)
                         for v in genesis.validators]

        if known_validators and known_validators != validator_set:
            self.log_abci_migration_error(known_chain['chain_id'],
                                          known_validators)
            sys.exit(1)

        block = Block(app_hash=app_hash, height=height, transactions=[])
        self.bigchaindb.store_block(block._asdict())
        self.bigchaindb.store_validator_set(height + 1, validator_set)
        abci_chain_height = 0 if known_chain is None else known_chain['height']
        self.bigchaindb.store_abci_chain(abci_chain_height,
                                         genesis.chain_id, True)
        self.chain = {'height': abci_chain_height, 'is_synced': True,
                      'chain_id': genesis.chain_id}
        return ResponseInitChain()
Example #25
0
def test_process_block_does_not_approve_after_validator_update(b):
    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)
    txs = [election]
    total_votes = votes

    b.store_block(
        Block(height=1, transactions=[tx.id for tx in txs],
              app_hash='')._asdict())
    Election.process_block(b, 1, txs)
    b.store_bulk_transactions(txs)

    second_election, second_votes = generate_election(b,
                                                      ChainMigrationElection,
                                                      public_key, private_key,
                                                      {}, voter_keys)

    Election.process_block(b, 2, total_votes + [second_election])

    b.store_block(
        Block(height=2,
              transactions=[v.id for v in total_votes + [second_election]],
              app_hash='')._asdict())

    b.store_abci_chain(1, 'chain-X')
    Election.process_block(b, 3, second_votes)

    assert not b.get_election(second_election.id)['is_concluded']
    assert b.get_latest_abci_chain() == {
        'height': 1,
        'chain_id': 'chain-X',
        'is_synced': True
    }
Example #26
0
def inputs(user_pk, b, alice):
    from bigchaindb.models import Transaction
    # create blocks with transactions for `USER` to spend
    for height in range(1, 4):
        transactions = [
            Transaction.create(
                [alice.public_key],
                [([user_pk], 1)],
                metadata={
                    'msg': random.random()
                },
            ).sign([alice.private_key]) for _ in range(10)
        ]
        tx_ids = [tx.id for tx in transactions]
        block = Block(app_hash='hash' + str(height),
                      height=height,
                      transactions=tx_ids)
        b.store_block(block._asdict())
        b.store_bulk_transactions(transactions)
Example #27
0
def test_run_recover(b, alice, bob):
    from bigchaindb.commands.bigchaindb import run_recover
    from bigchaindb.models import Transaction
    from bigchaindb.lib import Block, PreCommitState
    from bigchaindb.backend.query import PRE_COMMIT_ID
    from bigchaindb.backend import query

    tx1 = Transaction.create([alice.public_key],
                             [([alice.public_key], 1)],
                             asset={'cycle': 'hero'},
                             metadata={'name': 'hohenheim'}) \
                     .sign([alice.private_key])
    tx2 = Transaction.create([bob.public_key],
                             [([bob.public_key], 1)],
                             asset={'cycle': 'hero'},
                             metadata={'name': 'hohenheim'}) \
                     .sign([bob.private_key])

    # store the transactions
    b.store_bulk_transactions([tx1, tx2])

    # create a random block
    block8 = Block(app_hash='random_app_hash1',
                   height=8,
                   transactions=['txid_doesnt_matter'])._asdict()
    b.store_block(block8)

    # create the next block
    block9 = Block(app_hash='random_app_hash1',
                   height=9,
                   transactions=[tx1.id])._asdict()
    b.store_block(block9)

    # create a pre_commit state which is ahead of the commit state
    pre_commit_state = PreCommitState(commit_id=PRE_COMMIT_ID,
                                      height=10,
                                      transactions=[tx2.id])._asdict()
    b.store_pre_commit_state(pre_commit_state)

    run_recover(b)

    assert not query.get_transaction(b.connection, tx2.id)
Example #28
0
def test_process_block_approves_after_pending_validator_update(b):
    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)
    txs = [election]
    total_votes = votes

    another_validator = generate_validators([1])[0]

    election, votes = generate_election(b, ValidatorElection, public_key,
                                        private_key,
                                        another_validator['election'],
                                        voter_keys)
    txs += [election]
    total_votes += votes

    election, votes = generate_election(b, ChainMigrationElection, public_key,
                                        private_key, {}, voter_keys)

    txs += [election]
    total_votes += votes

    b.store_abci_chain(1, 'chain-X')
    Election.process_block(b, 1, txs)
    b.store_block(
        Block(height=1, transactions=[tx.id for tx in txs],
              app_hash='')._asdict())
    b.store_bulk_transactions(txs)

    Election.process_block(b, 2, total_votes)

    validators = b.get_validators()
    assert len(validators) == 5
    assert new_validator['storage'] in validators
    assert another_validator['storage'] not in validators

    assert b.get_election(txs[0].id)['is_concluded']
    assert not b.get_election(txs[1].id)['is_concluded']
    assert b.get_election(txs[2].id)['is_concluded']

    assert b.get_latest_abci_chain() == {
        'height': 2,
        'chain_id': 'chain-X-migrated-at-height-1',
        'is_synced': False
    }
Example #29
0
    def commit(self):
        """Store the new height and along with block hash."""

        data = self.block_txn_hash.encode('utf-8')

        # register a new block only when new transactions are received
        if self.block_txn_ids:
            self.bigchaindb.store_bulk_transactions(self.block_transactions)
            block = Block(app_hash=self.block_txn_hash,
                          height=self.new_height,
                          transactions=self.block_txn_ids)
            # NOTE: storing the block should be the last operation during commit
            # this effects crash recovery. Refer BEP#8 for details
            self.bigchaindb.store_block(block._asdict())

        logger.debug(
            'Commit-ing new block with hash: apphash=%s ,'
            'height=%s, txn ids=%s', data, self.new_height, self.block_txn_ids)
        logger.benchmark('COMMIT_BLOCK, height:%s', self.new_height)
        return ResponseCommit(data=data)
Example #30
0
def test_get_block_endpoint(b, client, alice):
    import copy
    tx = Transaction.create([alice.public_key], [([alice.public_key], 1)],
                            asset={'cycle': 'hero'})
    tx = tx.sign([alice.private_key])

    # with store_bulk_transactions we use `insert_many` where PyMongo
    # automatically adds an `_id` field to the tx, therefore we need the
    # deepcopy, for more info see:
    # https://api.mongodb.com/python/current/faq.html#writes-and-ids
    tx_dict = copy.deepcopy(tx.to_dict())
    b.store_bulk_transactions([tx])

    block = Block(app_hash='random_utxo', height=31, transactions=[tx.id])
    b.store_block(block._asdict())

    res = client.get(BLOCKS_ENDPOINT + str(block.height))
    expected_response = {'height': block.height, 'transactions': [tx_dict]}
    assert res.json == expected_response
    assert res.status_code == 200
def test_get_block_endpoint(b, client, alice):
    import copy
    tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], asset={'cycle': 'hero'})
    tx = tx.sign([alice.private_key])

    # with store_bulk_transactions we use `insert_many` where PyMongo
    # automatically adds an `_id` field to the tx, therefore we need the
    # deepcopy, for more info see:
    # https://api.mongodb.com/python/current/faq.html#writes-and-ids
    tx_dict = copy.deepcopy(tx.to_dict())
    b.store_bulk_transactions([tx])

    block = Block(app_hash='random_utxo',
                  height=31,
                  transactions=[tx.id])
    b.store_block(block._asdict())

    res = client.get(BLOCKS_ENDPOINT + str(block.height))
    expected_response = {'height': block.height, 'transactions': [tx_dict]}
    assert res.json == expected_response
    assert res.status_code == 200
Example #32
0
def test_get_latest_block(b):
    from bigchaindb.lib import Block

    for i in range(10):
        app_hash = os.urandom(16).hex()
        txn_id = os.urandom(16).hex()
        block = Block(app_hash=app_hash, height=i,
                      transactions=[txn_id])._asdict()
        b.store_block(block)

    block = b.get_latest_block()
    assert block['height'] == 9
Example #33
0
def test_approved_elections_concludes_all_elections(b):
    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']
    election, votes = generate_election(b,
                                        ValidatorElection,
                                        public_key, private_key,
                                        new_validator['election'])
    txs = [election]
    total_votes = votes

    election, votes = generate_election(b,
                                        ChainMigrationElection,
                                        public_key, private_key,
                                        {})

    txs += [election]
    total_votes += votes

    b.store_abci_chain(1, 'chain-X')
    b.store_block(Block(height=1,
                        transactions=[tx.id for tx in txs],
                        app_hash='')._asdict())
    b.store_bulk_transactions(txs)

    Election.approved_elections(b, 1, total_votes)

    validators = b.get_validators()
    assert len(validators) == 5
    assert new_validator['storage'] in validators

    chain = b.get_latest_abci_chain()
    assert chain
    assert chain == {
        'height': 2,
        'is_synced': False,
        'chain_id': 'chain-X-migrated-at-height-1',
    }

    for tx in txs:
        election = b.get_election(tx.id)
        assert election
Example #34
0
def test_process_block_approves_only_one_validator_update(b):
    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)
    txs = [election]
    total_votes = votes

    another_validator = generate_validators([1])[0]

    election, votes = generate_election(b, ValidatorElection, public_key,
                                        private_key,
                                        another_validator['election'],
                                        voter_keys)
    txs += [election]
    total_votes += votes

    Election.process_block(b, 1, txs)
    b.store_block(
        Block(height=1, transactions=[tx.id for tx in txs],
              app_hash='')._asdict())
    b.store_bulk_transactions(txs)

    Election.process_block(b, 2, total_votes)

    validators = b.get_validators()
    assert len(validators) == 5
    assert new_validator['storage'] in validators
    assert another_validator['storage'] not in validators

    assert b.get_election(txs[0].id)['is_concluded']
    assert not b.get_election(txs[1].id)['is_concluded']
Example #35
0
def test_process_block_applies_only_one_migration(b):
    validators = generate_validators([1] * 4)
    b.store_validator_set(1, [v['storage'] for v in validators])

    public_key = validators[0]['public_key']
    private_key = validators[0]['private_key']
    election, votes = generate_election(b,
                                        ChainMigrationElection,
                                        public_key, private_key,
                                        {})
    txs = [election]
    total_votes = votes

    election, votes = generate_election(b,
                                        ChainMigrationElection,
                                        public_key, private_key,
                                        {})

    txs += [election]
    total_votes += votes

    b.store_abci_chain(1, 'chain-X')
    Election.process_block(b, 1, txs)
    b.store_block(Block(height=1,
                        transactions=[tx.id for tx in txs],
                        app_hash='')._asdict())
    b.store_bulk_transactions(txs)

    Election.process_block(b, 1, total_votes)
    chain = b.get_latest_abci_chain()
    assert chain
    assert chain == {
        'height': 2,
        'is_synced': False,
        'chain_id': 'chain-X-migrated-at-height-1',
    }

    assert b.get_election(txs[0].id)['is_concluded']
    assert not b.get_election(txs[1].id)['is_concluded']
Example #36
0
    def init_chain(self, validators):
        """Initialize chain with block of height 0"""

        block = Block(app_hash='', height=0, transactions=[])
        self.bigchaindb.store_block(block._asdict())
        return ResponseInitChain()
Example #37
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': [],
        }