Ejemplo n.º 1
0
def test_gap_continuity(changes):
    MAX_BLOCK_NUM = 21

    # method to get all the block numbers that are in a gap right now
    _all_missing = compose(
        set, partial(_all_gap_numbers, highest_block_number=MAX_BLOCK_NUM))

    @to_set
    def _all_inserted(chain_gaps):
        """List all the inserted headers, the block numbers not in gaps"""
        missing = _all_missing(chain_gaps)
        for block_num in range(MAX_BLOCK_NUM + 1):
            if block_num not in missing:
                yield block_num

    chain_gaps = GENESIS_CHAIN_GAPS

    for do_insert, block_num in changes:
        starts_inserted = _all_inserted(chain_gaps)
        starts_missing = _all_missing(chain_gaps)

        if do_insert:
            to_insert = block_num
            _, chain_gaps = fill_gap(to_insert, chain_gaps)
            assert not is_block_number_in_gap(to_insert, chain_gaps)

            # Make sure that at most this one block number was filled
            finished_inserted = _all_inserted(chain_gaps)
            assert to_insert in finished_inserted
            new_inserts = finished_inserted - starts_inserted
            if block_num in starts_inserted:
                assert new_inserts == set()
            else:
                assert new_inserts == {block_num}

            # Make sure that no new gaps were created
            finished_missing = _all_missing(chain_gaps)
            assert to_insert not in finished_missing
            new_missing = finished_missing - starts_missing
            assert new_missing == set()
        else:
            to_remove = block_num
            # Note that removing a header is inserting a gap
            chain_gaps = reopen_gap(to_remove, chain_gaps)
            assert is_block_number_in_gap(to_remove, chain_gaps)

            # Make sure that no gaps were filled
            finished_inserted = _all_inserted(chain_gaps)
            new_inserts = finished_inserted - starts_inserted
            assert new_inserts == set()

            # Make sure that at most this one block number gap was reopened
            finished_missing = _all_missing(chain_gaps)
            new_missing = finished_missing - starts_missing
            if block_num in starts_missing:
                assert new_missing == set()
            else:
                assert new_missing == {block_num}

        _validate_gap_invariants(chain_gaps)
Ejemplo n.º 2
0
    def _update_chain_gaps(cls,
                           db: DatabaseAPI,
                           persisted_block: BlockAPI,
                           base_gaps: ChainGaps = None) -> GapInfo:

        # If we make many updates in a row, we can avoid reloading the integrity info by
        # continuously caching it and providing it as a parameter to this API
        if base_gaps is None:
            base_gaps = cls._get_chain_gaps(db)

        gap_change, gaps = fill_gap(persisted_block.number, base_gaps)
        if gap_change is not GapChange.NoChange:
            db.set(SchemaV1.make_chain_gaps_lookup_key(),
                   rlp.encode(gaps, sedes=chain_gaps))

        return gap_change, gaps
Ejemplo n.º 3
0
def test_corrupt_gaps():
    with pytest.raises(GapTrackingCorrupted, match="(1, 3)"):
        fill_gap(2, (((1, 3), (2, 4)), 6))
    with pytest.raises(GapTrackingCorrupted, match="(2, 4)"):
        fill_gap(2, (((1, 3), (2, 4)), 6))