async def test_sending_collations(request, event_loop): sender, receiver = await get_directly_linked_peers( request, event_loop, ShardingPeer, None, ShardingPeer, None, ) c1 = Collation(CollationHeader(0, b"\x11" * 32, 2, b"\x33" * 20), b"\x44" * COLLATION_SIZE) c2 = Collation(CollationHeader(1, b"\x11" * 32, 2, b"\x33" * 20), b"\x44" * COLLATION_SIZE) c3 = Collation(CollationHeader(2, b"\x11" * 32, 2, b"\x33" * 20), b"\x44" * COLLATION_SIZE) sender.sub_proto.send_collations([c1]) received_c1 = await asyncio.wait_for( receiver.incoming_collation_queue.get(), timeout=1) assert received_c1 == c1 assert receiver.known_collation_hashes == set([c1.hash]) sender.sub_proto.send_collations([c2, c3]) received_c2 = await asyncio.wait_for( receiver.incoming_collation_queue.get(), timeout=1) received_c3 = await asyncio.wait_for( receiver.incoming_collation_queue.get(), timeout=1) assert set([received_c2, received_c3]) == set([c2, c3]) assert receiver.known_collation_hashes == set([c1.hash, c2.hash, c3.hash])
def test_body_fields(collation_header): assert len(CollationHeader.fields) == 4 # if not this test is outdated collation = Collation(header=collation_header, body=b"") assert collation.shard_id == collation_header.shard_id assert collation.chunk_root == collation_header.chunk_root assert collation.period == collation_header.period assert collation.proposer_address == collation_header.proposer_address
def random_collation(shard_id, period): body = zpad_right(int_to_big_endian(random.getrandbits(8 * 32)), COLLATION_SIZE) header = CollationHeader( shard_id=shard_id, period=period, chunk_root=calc_chunk_root(body), proposer_address=b"\xff" * 20, ) return Collation(header, body)
def propose(self) -> Collation: """Broadcast a new collation to the network, add it to the local shard, and return it.""" # create collation for current period period = self.get_current_period() body = zpad_right(str(self).encode("utf-8"), COLLATION_SIZE) header = CollationHeader(self.shard.shard_id, calc_chunk_root(body), period, b"\x11" * 20) collation = Collation(header, body) self.logger.debug("Proposing collation {}".format(collation)) # add collation to local chain self.shard.add_collation(collation) # broadcast collation for peer in self.peer_pool.peers: cast(ShardingPeer, peer).send_collations([collation]) return collation
def generate_collations(): explicit_params = {} for period in itertools.count(): default_params = { "shard_id": 0, "period": period, "body": zpad_right(b"body%d" % period, COLLATION_SIZE), "proposer_address": zpad_right(b"proposer%d" % period, 20), } # only calculate chunk root if it wouldn't be replaced anyway if "chunk_root" not in explicit_params: default_params["chunk_root"] = calc_chunk_root(default_params["body"]) params = merge(default_params, explicit_params) header = CollationHeader( shard_id=params["shard_id"], chunk_root=params["chunk_root"], period=params["period"], proposer_address=params["proposer_address"], ) collation = Collation(header, params["body"]) explicit_params = (yield collation) or {}
def collation(collation_header): body = b"\x00" * COLLATION_SIZE return Collation(collation_header, body)
def get_collation(self, shard_id: int, period: int) -> Collation: header = self.get_header(shard_id, period) body = self.get_body(shard_id, period) return Collation(header, body)
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 get_collation_by_hash(self, collation_hash: Hash32) -> Collation: header = self.get_header_by_hash(collation_hash) body = self.get_body_by_chunk_root(header.chunk_root) return Collation(header, body)
def collation(header, body): return Collation(header, body)