Esempio n. 1
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': [],
        }
Esempio n. 2
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()
Esempio n. 3
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': [],
    }
Esempio n. 4
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()
Esempio n. 5
0
 def init_chain(self, req):
     self.validators = req.validators
     return ResponseInitChain()
Esempio n. 6
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': [],
        }
Esempio n. 7
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()