def test_orphan_block_pool(): pool = OrphanBlockPool() b0 = BeaconBlockFactory() b1 = BeaconBlockFactory(parent=b0) b2 = BeaconBlockFactory(parent=b0, state_root=b"\x11" * 32) # test: add pool.add(b1) assert b1 in pool._pool assert len(pool._pool) == 1 # test: add: no side effect for adding twice pool.add(b1) assert len(pool._pool) == 1 # test: `__contains__` assert b1 in pool assert b1.signing_root in pool assert b2 not in pool assert b2.signing_root not in pool # test: add: two blocks pool.add(b2) assert len(pool._pool) == 2 # test: get assert pool.get(b1.signing_root) == b1 assert pool.get(b2.signing_root) == b2 # test: pop_children b2_children = pool.pop_children(b2.signing_root) assert len(b2_children) == 0 assert len(pool._pool) == 2 b0_children = pool.pop_children(b0.signing_root) assert len(b0_children) == 2 and (b1 in b0_children) and (b2 in b0_children) assert len(pool._pool) == 0
async def test_sync_from_old_head(request, event_loop, event_bus): genesis = BeaconBlockFactory() alice_branch = (genesis, ) + BeaconBlockFactory.create_branch(length=49, root=genesis) bob_branch = alice_branch + BeaconBlockFactory.create_branch( length=50, root=alice_branch[-1]) async with get_sync_setup(request, event_loop, event_bus, alice_branch, bob_branch) as (alice, bob): assert_synced(alice, bob, bob_branch)
async def test_reorg_sync(request, event_loop, event_bus): genesis = BeaconBlockFactory() alice_branch = (genesis, ) + BeaconBlockFactory.create_branch( length=49, root=genesis, state_root=b"\x11" * 32) bob_branch = (genesis, ) + BeaconBlockFactory.create_branch( length=99, root=genesis, state_root=b"\x22" * 32) async with get_sync_setup(request, event_loop, event_bus, alice_branch, bob_branch) as (alice, bob): assert_synced(alice, bob, bob_branch)
async def test_reorg_sync(request, event_loop, event_bus, genesis_state): genesis_block = get_genesis_block(genesis_state.hash_tree_root, BeaconBlock) alice_branch = (genesis_block, ) + BeaconBlockFactory.create_branch( length=49, root=genesis_block, state_root=b"\x11" * 32) bob_branch = (genesis_block, ) + BeaconBlockFactory.create_branch( length=99, root=genesis_block, state_root=b"\x22" * 32) async with get_sync_setup(request, event_loop, event_bus, genesis_state, alice_branch, bob_branch) as (alice, bob): assert_synced(alice, bob, bob_branch)
async def test_sync_from_old_head(request, event_loop, event_bus, genesis_state): genesis_block = get_genesis_block(genesis_state.hash_tree_root, BeaconBlock) alice_branch = (genesis_block, ) + BeaconBlockFactory.create_branch( length=49, root=genesis_block) bob_branch = alice_branch + BeaconBlockFactory.create_branch( length=50, root=alice_branch[-1]) async with get_sync_setup(request, event_loop, event_bus, genesis_state, alice_branch, bob_branch) as (alice, bob): assert_synced(alice, bob, bob_branch)
async def test_sync_skipped_slots(request, event_loop, event_bus): genesis = BeaconBlockFactory() alice_branch = (genesis, ) + BeaconBlockFactory.create_branch(length=0, root=genesis) bob_branch = (genesis, ) + BeaconBlockFactory.create_branch_by_slots( slots=tuple(range(4, 99)), root=genesis) assert bob_branch[0].slot == 0 assert bob_branch[1].slot == 4 async with get_sync_setup(request, event_loop, event_bus, alice_branch, bob_branch) as (alice, bob): assert_synced(alice, bob, bob_branch)
async def test_sync_skipped_slots(request, event_loop, event_bus, genesis_state): genesis_block = get_genesis_block(genesis_state.hash_tree_root, BeaconBlock) alice_branch = (genesis_block, ) + BeaconBlockFactory.create_branch( length=0, root=genesis_block) bob_branch = (genesis_block, ) + BeaconBlockFactory.create_branch_by_slots( slots=tuple(range(4, 99)), root=genesis_block) assert bob_branch[0].slot == 0 assert bob_branch[1].slot == 4 async with get_sync_setup(request, event_loop, event_bus, genesis_state, alice_branch, bob_branch) as (alice, bob): assert_synced(alice, bob, bob_branch)
async def test_sync_when_already_at_best_head(request, event_loop, event_bus): genesis = BeaconBlockFactory() alice_branch = (genesis, ) + BeaconBlockFactory.create_branch( length=99, root=genesis, state_root=b"\x11" * 32) bob_branch = (genesis, ) + BeaconBlockFactory.create_branch( length=50, root=genesis, state_root=b"\x22" * 32) async with get_sync_setup(request, event_loop, event_bus, alice_branch, bob_branch) as (alice, bob): alice_head = alice.chain.get_canonical_head() assert alice_head.slot == 99 for correct_block in alice_branch: slot = correct_block.slot alice_block = alice.chain.get_canonical_block_by_slot(slot) assert alice_block == correct_block
async def test_get_blocks_from_fork_chain_by_root(fork_chain_block_slots, slot_of_requested_blocks, expected_block_slots): fork_chain_blocks = BeaconBlockFactory.create_branch_by_slots( fork_chain_block_slots) mock_root_to_block_db = { block.signing_root: block for block in fork_chain_blocks } class Chain: def get_block_by_root(self, root): if root in mock_root_to_block_db: return mock_root_to_block_db[root] else: raise BlockNotFound requested_blocks = get_blocks_from_fork_chain_by_root( chain=Chain(), start_slot=slot_of_requested_blocks[0], peer_head_block=fork_chain_blocks[-1], slot_of_requested_blocks=slot_of_requested_blocks, ) expected_blocks = [ block for block in fork_chain_blocks if block.slot in expected_block_slots ] assert len(requested_blocks) == len(expected_blocks) assert set(requested_blocks) == set(expected_blocks)
async def test_get_canonical_block_range_by_root(request, event_loop, event_bus): chain_db = AsyncBeaconChainDBFactory(blocks=()) genesis = BeaconBlockFactory() base_branch = BeaconBlockFactory.create_branch(3, root=genesis) non_canonical_branch = BeaconBlockFactory.create_branch( 3, root=base_branch[-1], state_root=b"\x00" * 32, ) canonical_branch = BeaconBlockFactory.create_branch( 4, root=base_branch[-1], state_root=b"\x11" * 32, ) for branch in [[genesis], base_branch, non_canonical_branch, canonical_branch]: scorings = (higher_slot_scoring for block in branch) await chain_db.coro_persist_block_chain(branch, BeaconBlock, scorings) async with get_request_server_setup(request, event_loop, event_bus, chain_db) as (alice, response_buffer): alice.sub_proto.send_get_blocks(base_branch[1].signing_root, 4, request_id=5) response = await response_buffer.msg_queue.get() assert isinstance(response.command, BeaconBlocks) assert response.payload["request_id"] == 5 blocks = tuple( ssz.decode(block, BeaconBlock) for block in response.payload["encoded_blocks"]) assert len(blocks) == 4 assert [block.slot for block in blocks ] == [genesis.slot + s for s in [2, 3, 4, 5]] assert blocks == base_branch[1:] + canonical_branch[:2]
async def test_get_single_block_by_root(request, event_loop, event_bus): block = BeaconBlockFactory() chain_db = AsyncBeaconChainDBFactory(blocks=(block, )) async with get_request_server_setup(request, event_loop, event_bus, chain_db) as (alice, response_buffer): alice.sub_proto.send_get_blocks(block.slot, 1, request_id=5) response = await response_buffer.msg_queue.get() assert isinstance(response.command, BeaconBlocks) assert response.payload == { "request_id": 5, "encoded_blocks": (ssz.encode(block), ), }
async def test_get_blocks_from_canonical_chain_by_slot( db_block_slots, slot_of_requested_blocks, expected_block_slots): chain = BeaconBlockFactory.create_branch_by_slots(db_block_slots) # Mock up block database mock_slot_to_block_db = {block.slot: block for block in chain} class Chain: def get_canonical_block_by_slot(self, slot): if slot in mock_slot_to_block_db: return mock_slot_to_block_db[slot] else: raise BlockNotFound result_blocks = get_blocks_from_canonical_chain_by_slot( chain=Chain(), slot_of_requested_blocks=slot_of_requested_blocks) expected_blocks = [ mock_slot_to_block_db[slot] for slot in expected_block_slots ] assert len(result_blocks) == len(expected_blocks) assert set(result_blocks) == set(expected_blocks)
async def get_fake_chain() -> FakeChain: genesis_config = Eth2GenesisConfig(MINIMAL_SERENITY_CONFIG) chain_db = AsyncBeaconChainDBFactory(genesis_config=genesis_config) genesis_block = BeaconBlockFactory() chain_db.persist_block(genesis_block, SerenityBeaconBlock, HigherSlotScoring()) return FakeChain(base_db=chain_db.db, genesis_config=genesis_config)