async def batch_broadcast_xshard_tx_list( self, block_hash_to_xshard_list_and_prev_root_height: Dict[bytes, Tuple[List, int]], source_branch: Branch, ): branch_to_add_xshard_tx_list_request_list = dict() for ( block_hash, x_shard_list_and_prev_root_height, ) in block_hash_to_xshard_list_and_prev_root_height.items(): xshard_tx_list = x_shard_list_and_prev_root_height[0] prev_root_height = x_shard_list_and_prev_root_height[1] branch_to_add_xshard_tx_list_request = self.__get_branch_to_add_xshard_tx_list_request( block_hash, xshard_tx_list, prev_root_height) for branch, request in branch_to_add_xshard_tx_list_request.items( ): if branch == source_branch or not is_neighbor( branch, source_branch, len( self.env.quark_chain_config. get_initialized_full_shard_ids_before_root_height( prev_root_height)), ): check( len(request.tx_list.tx_list) == 0, "there shouldn't be xshard list for non-neighbor shard ({} -> {})" .format(source_branch.value, branch.value), ) continue branch_to_add_xshard_tx_list_request_list.setdefault( branch, []).append(request) rpc_futures = [] for branch, request_list in branch_to_add_xshard_tx_list_request_list.items( ): if branch in self.shards: for request in request_list: self.shards[ branch].state.add_cross_shard_tx_list_by_minor_block_hash( request.minor_block_hash, request.tx_list) batch_request = BatchAddXshardTxListRequest(request_list) for ( slave_conn ) in self.slave_connection_manager.get_connections_by_full_shard_id( branch.get_full_shard_id()): future = slave_conn.write_rpc_request( ClusterOp.BATCH_ADD_XSHARD_TX_LIST_REQUEST, batch_request) rpc_futures.append(future) responses = await asyncio.gather(*rpc_futures) check(all([response.error_code == 0 for _, response, _ in responses]))
async def broadcast_xshard_tx_list(self, block, xshard_tx_list, prev_root_height): """ Broadcast x-shard transactions to their recipient shards """ block_hash = block.header.get_hash() branch_to_add_xshard_tx_list_request = self.__get_branch_to_add_xshard_tx_list_request( block_hash, xshard_tx_list, prev_root_height ) rpc_futures = [] for branch, request in branch_to_add_xshard_tx_list_request.items(): if branch == block.header.branch or not is_neighbor( block.header.branch, branch, len( self.env.quark_chain_config.get_initialized_full_shard_ids_before_root_height( prev_root_height ) ), ): check( len(request.tx_list.tx_list) == 0, "there shouldn't be xshard list for non-neighbor shard ({} -> {})".format( block.header.branch.value, branch.value ), ) continue if branch in self.shards: self.shards[branch].state.add_cross_shard_tx_list_by_minor_block_hash( block_hash, request.tx_list ) for ( slave_conn ) in self.slave_connection_manager.get_connections_by_full_shard_id( branch.get_full_shard_id() ): future = slave_conn.write_rpc_request( ClusterOp.ADD_XSHARD_TX_LIST_REQUEST, request ) rpc_futures.append(future) responses = await asyncio.gather(*rpc_futures) check(all([response.error_code == 0 for _, response, _ in responses]))
def test_is_neighbor_same_chain_id(self): b1 = Branch(2 << 16 | 2 | 1) b2 = Branch(2 << 16 | 2 | 0) self.assertTrue(is_neighbor(b1, b2, 33))
def test_not_neighbor_diff_chain_id_and_diff_shard_id(self): b1 = Branch(1 << 16 | 2 | 0) b2 = Branch(3 << 16 | 2 | 1) self.assertFalse(is_neighbor(b1, b2, 33))
def test_is_neighbor_small_shard_size(self): b1 = Branch(1 << 16 | 2 | 0) b2 = Branch(3 << 16 | 2 | 1) self.assertTrue(is_neighbor(b1, b2, 32))
def test_is_neighbor_same_shard_id(self): b1 = Branch(1 << 16 | 2 | 1) b2 = Branch(3 << 16 | 2 | 1) self.assertTrue(is_neighbor(b1, b2, 33))
def test_is_neighbor_small_shard_size(self): b1 = Branch.create(32, 0) b2 = Branch.create(32, 7) self.assertTrue(is_neighbor(b1, b2))
def test_raise_same_shard_id(self): b1 = Branch.create(64, 5) b2 = Branch.create(64, 5) with self.assertRaises(AssertionError): is_neighbor(b1, b2)
def test_raise_different_shard_size(self): b1 = Branch.create(64, 4) b2 = Branch.create(32, 5) with self.assertRaises(AssertionError): is_neighbor(b1, b2)
def test_not_neighbor_two_bit_difference(self): b1 = Branch.create(64, 4) b2 = Branch.create(64, 7) self.assertFalse(is_neighbor(b1, b2))
def test_is_neighbor_one_bit_difference(self): b1 = Branch.create(64, 5) b2 = Branch.create(64, 7) self.assertTrue(is_neighbor(b1, b2))