def __init__( self, privkey: datatypes.PrivateKey, address: Address, network_id: int, min_peers: int = 0, peer_class: Type[BasePeer] = ShardingPeer, peer_pool_class: Type[PeerPool] = PeerPool, bootstrap_nodes: List[str] = [], ) -> None: BaseService.__init__(self, CancelToken('ShardingServer')) self.privkey = privkey self.address = address self.network_id = network_id self.peer_class = peer_class self.discovery = DiscoveryProtocol(self.privkey, self.address, bootstrap_nodes=bootstrap_nodes) # XXX: This is not supposed to work and causes both the PeerPool and Server to crash, but # the tests in test_sharding.py don't seem to care self.headerdb = None self.peer_pool = peer_pool_class( peer_class, self.headerdb, self.network_id, self.privkey, self.discovery, min_peers=min_peers, ) shard_db = ShardDB(MemoryDB()) shard = Shard(shard_db, 0) self.syncer = ShardSyncer(shard, self.peer_pool, self.cancel_token) # type: ignore
async def test_syncer_requests_new_collations(request, event_loop): # setup a-b topology peer_a_b, peer_b_a = await get_directly_linked_sharding_peers( request, event_loop) peer_a_b_subscriber = asyncio.Queue() peer_a_b.add_subscriber(peer_a_b_subscriber) peer_pool_b = MockPeerPoolWithConnectedPeers([peer_b_a]) # setup shard dbs at b shard_db = ShardDB(MemoryDB()) shard = Shard(shard_db, 0) # start shard syncer syncer = ShardSyncer(shard, peer_pool_b) asyncio.ensure_future(syncer.run()) def finalizer(): event_loop.run_until_complete(syncer.cancel()) request.addfinalizer(finalizer) # notify b about new hashes at a and check that it requests them hashes_and_periods = ((b"\xaa" * 32, 0), ) peer_a_b.sub_proto.send_new_collation_hashes(hashes_and_periods) peer, cmd, msg = await asyncio.wait_for( peer_a_b_subscriber.get(), timeout=1, ) assert peer == peer_a_b assert isinstance(cmd, GetCollations) assert msg["collation_hashes"] == (hashes_and_periods[0][0], )
def shard_chain(shard_chaindb, funded_address, funded_address_initial_balance): # noqa: F811 genesis_params = { "bloom": 0, "coinbase": to_canonical_address("8888f1f195afa192cfee860698584c030f4c9db1"), "difficulty": 131072, "extra_data": b"B", "gas_limit": 3141592, "gas_used": 0, "mix_hash": decode_hex( "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" ), # noqa: E501 "nonce": decode_hex("0102030405060708"), "block_number": 0, "parent_hash": decode_hex( "0000000000000000000000000000000000000000000000000000000000000000" ), # noqa: E501 "transaction_root": constants.EMPTY_SHA3, "receipt_root": constants.EMPTY_SHA3, "timestamp": 1422494849, "uncles_hash": decode_hex( "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" ) # noqa: E501 } genesis_state = { funded_address: { "balance": funded_address_initial_balance, "nonce": 0, "code": b"", "storage": {} } } klass = Shard.configure(__name__='TestChain', vm_configuration=((constants.GENESIS_BLOCK_NUMBER, ShardingVM), )) shard = klass.from_genesis(shard_chaindb, genesis_params, genesis_state) return shard
async def test_new_collations_notification(request, event_loop): # setup a-b-c topology peer_a_b, peer_b_a = await get_directly_linked_sharding_peers( request, event_loop) peer_b_c, peer_c_b = await get_directly_linked_sharding_peers( request, event_loop) peer_c_b_subscriber = asyncio.Queue() peer_c_b.add_subscriber(peer_c_b_subscriber) peer_pool_b = MockPeerPoolWithConnectedPeers([peer_b_a, peer_b_c]) # setup shard dbs at b shard_db = ShardDB(MemoryDB()) shard = Shard(shard_db, 0) # start shard syncer syncer = ShardSyncer(shard, peer_pool_b) asyncio.ensure_future(syncer.run()) def finalizer(): event_loop.run_until_complete(syncer.cancel()) request.addfinalizer(finalizer) # send collation from a to b and check that c gets notified c1 = next(collations) peer_a_b.sub_proto.send_collations(0, [c1]) peer, cmd, msg = await asyncio.wait_for( peer_c_b_subscriber.get(), timeout=1, ) assert peer == peer_c_b assert isinstance(cmd, NewCollationHashes) assert msg["collation_hashes_and_periods"] == ((c1.hash, c1.period), ) # check that c won't be notified about c1 again c2 = next(collations) peer_a_b.sub_proto.send_collations(0, [c1, c2]) peer, cmd, msg = await asyncio.wait_for( peer_c_b_subscriber.get(), timeout=1, ) assert peer == peer_c_b assert isinstance(cmd, NewCollationHashes) assert msg["collation_hashes_and_periods"] == ((c2.hash, c2.period), )
def shard_chain_without_block_validation(shard_chaindb): # noqa: F811 shard_chaindb = shard_chaindb """ Return a Chain object containing just the genesis block. This Chain does not perform any validation when importing new blocks. The Chain's state includes one funded account which is where the simple transfer contract will be deployed at. """ overrides = { 'import_block': import_block_without_validation, 'validate_block': lambda self, block: None, } klass = Shard.configure( __name__='TestShardChainWithoutBlockValidation', vm_configuration=((constants.GENESIS_BLOCK_NUMBER, ShardingVM), ), **overrides, ) genesis_params = { 'block_number': constants.GENESIS_BLOCK_NUMBER, 'difficulty': constants.GENESIS_DIFFICULTY, 'gas_limit': constants.GENESIS_GAS_LIMIT, 'parent_hash': constants.GENESIS_PARENT_HASH, 'coinbase': constants.GENESIS_COINBASE, 'nonce': constants.GENESIS_NONCE, 'mix_hash': constants.GENESIS_MIX_HASH, 'extra_data': constants.GENESIS_EXTRA_DATA, 'timestamp': 1501851927, 'transaction_root': constants.EMPTY_SHA3, 'receipt_root': constants.EMPTY_SHA3, } genesis_state = { decode_hex(SHARD_CHAIN_CONTRACTS_FIXTURES[i]["deployed_address"]): { 'balance': SHARD_CHAIN_CONTRACTS_FIXTURES[i]["initial_balance"], 'code': b'', 'storage': {}, } for i in range(len(SHARD_CHAIN_CONTRACTS_FIXTURES)) } shard = klass.from_genesis(shard_chaindb, genesis_params, genesis_state) return shard
async def test_collation_requests(request, event_loop): # setup two peers sender, receiver = await get_directly_linked_sharding_peers(request, event_loop) receiver_peer_pool = MockPeerPoolWithConnectedPeers([receiver]) # setup shard db for request receiving node receiver_db = ShardDB(MemoryDB()) receiver_shard = Shard(receiver_db, 0) # create three collations and add two to the shard of the receiver # body is shared to avoid unnecessary chunk root calculation body = zpad_right(b"body", COLLATION_SIZE) chunk_root = calc_chunk_root(body) c1 = Collation(CollationHeader(0, chunk_root, 0, zpad_right(b"proposer1", 20)), body) c2 = Collation(CollationHeader(0, chunk_root, 1, zpad_right(b"proposer2", 20)), body) c3 = Collation(CollationHeader(0, chunk_root, 2, zpad_right(b"proposer3", 20)), body) for collation in [c1, c2]: receiver_shard.add_collation(collation) # start shard syncer receiver_syncer = ShardSyncer(receiver_shard, receiver_peer_pool) asyncio.ensure_future(receiver_syncer.run()) def finalizer(): event_loop.run_until_complete(receiver_syncer.cancel()) request.addfinalizer(finalizer) cancel_token = CancelToken("test") # request single collation received_collations = await asyncio.wait_for( sender.get_collations([c1.hash], cancel_token), timeout=1, ) assert received_collations == set([c1]) # request multiple collations received_collations = await asyncio.wait_for( sender.get_collations([c1.hash, c2.hash], cancel_token), timeout=1, ) assert received_collations == set([c1, c2]) # request no collations received_collations = await asyncio.wait_for( sender.get_collations([], cancel_token), timeout=1, ) assert received_collations == set() # request unknown collation received_collations = await asyncio.wait_for( sender.get_collations([c3.hash], cancel_token), timeout=1, ) assert received_collations == set() # request multiple collations, including unknown one received_collations = await asyncio.wait_for( sender.get_collations([c1.hash, c2.hash, c3.hash], cancel_token), timeout=1, ) assert received_collations == set([c1, c2])
def shard(shard_db): return Shard(shard_db, shard_id=0)
def _make_syncer(self, peer_pool: PeerPool) -> BaseService: shard_db = ShardDB(MemoryDB()) shard = Shard(shard_db, 0) return ShardSyncer(shard, peer_pool, self.cancel_token)