async def test_wallet_send_to_three_peers(self, three_sim_two_wallets): num_blocks = 10 full_nodes, wallets = three_sim_two_wallets wallet_0, wallet_server_0 = wallets[0] full_node_api_0 = full_nodes[0] full_node_api_1 = full_nodes[1] full_node_api_2 = full_nodes[2] full_node_0 = full_node_api_0.full_node full_node_1 = full_node_api_1.full_node full_node_2 = full_node_api_2.full_node server_0 = full_node_0.server server_1 = full_node_1.server server_2 = full_node_2.server ph = await wallet_0.wallet_state_manager.main_wallet.get_new_puzzlehash() # wallet0 <-> sever0 await wallet_server_0.start_client(PeerInfo(self_hostname, uint16(server_0._port)), None) for i in range(0, num_blocks): await full_node_api_0.farm_new_transaction_block(FarmNewBlockProtocol(ph)) all_blocks = await full_node_api_0.get_all_full_blocks() for block in all_blocks: await full_node_1.respond_block(RespondBlock(block)) await full_node_2.respond_block(RespondBlock(block)) funds = sum( [calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks)] ) await time_out_assert(5, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, funds) tx = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(10, 32 * b"0", 0) await wallet_0.wallet_state_manager.main_wallet.push_transaction(tx) await time_out_assert_not_none(5, full_node_0.mempool_manager.get_spendbundle, tx.spend_bundle.name()) # wallet0 <-> sever1 await wallet_server_0.start_client(PeerInfo(self_hostname, uint16(server_1._port)), wallet_0.on_connect) await time_out_assert_not_none(5, full_node_1.mempool_manager.get_spendbundle, tx.spend_bundle.name()) # wallet0 <-> sever2 await wallet_server_0.start_client(PeerInfo(self_hostname, uint16(server_2._port)), wallet_0.on_connect) await time_out_assert_not_none(5, full_node_2.mempool_manager.get_spendbundle, tx.spend_bundle.name())
async def farm_new_block(self, request: FarmNewBlockProtocol): async with self.full_node.blockchain.lock: self.log.info("Farming new block!") current_blocks = await self.get_all_full_blocks() if len(current_blocks) == 0: genesis = self.bt.get_consecutive_blocks(uint8(1))[0] await self.full_node.blockchain.receive_block(genesis) peak = self.full_node.blockchain.get_peak() assert peak is not None curr: BlockRecord = peak while not curr.is_transaction_block: curr = self.full_node.blockchain.block_record(curr.prev_hash) mempool_bundle = await self.full_node.mempool_manager.create_bundle_from_mempool(curr.header_hash) if mempool_bundle is None: spend_bundle = None else: spend_bundle = mempool_bundle[0] current_blocks = await self.get_all_full_blocks() target = request.puzzle_hash more = self.bt.get_consecutive_blocks( 1, transaction_data=spend_bundle, farmer_reward_puzzle_hash=target, pool_reward_puzzle_hash=target, block_list_input=current_blocks, current_time=self.use_current_time, ) rr: RespondBlock = RespondBlock(more[-1]) await self.full_node.respond_block(rr)
async def farm_new_transaction_block(self, request: FarmNewBlockProtocol): await self.lock.acquire() try: self.log.info("Farming new block!") current_blocks = await self.get_all_full_blocks() if len(current_blocks) == 0: genesis = self.bt.get_consecutive_blocks(uint8(1))[0] await self.full_node.blockchain.receive_block(genesis) peak = self.full_node.blockchain.get_peak() assert peak is not None mempool_bundle = await self.full_node.mempool_manager.create_bundle_from_mempool( peak.header_hash) if mempool_bundle is None: spend_bundle = None else: spend_bundle = mempool_bundle[0] current_blocks = await self.get_all_full_blocks() target = request.puzzle_hash more = self.bt.get_consecutive_blocks( 1, transaction_data=spend_bundle, farmer_reward_puzzle_hash=target, pool_reward_puzzle_hash=target, block_list_input=current_blocks, guarantee_transaction_block=True, current_time=self.use_current_time, ) rr = RespondBlock(more[-1]) await self.full_node.respond_block(rr) except Exception as e: self.log.error(f"Error while farming block: {e}") finally: self.lock.release()
async def reorg_from_index_to_new_index(self, request: ReorgProtocol): new_index = request.new_index old_index = request.old_index coinbase_ph = request.puzzle_hash current_blocks = await self.get_all_full_blocks() block_count = new_index - old_index more_blocks = self.bt.get_consecutive_blocks( block_count, farmer_reward_puzzle_hash=coinbase_ph, pool_reward_puzzle_hash=coinbase_ph, block_list_input=current_blocks[:old_index + 1], force_overflow=True, guarantee_transaction_block=True, seed=32 * b"1", ) for block in more_blocks: await self.full_node.respond_block(RespondBlock(block))
async def farm_new_transaction_block(self, request: FarmNewBlockProtocol): async with self.full_node._blockchain_lock_high_priority: self.log.info("Farming new block!") current_blocks = await self.get_all_full_blocks() if len(current_blocks) == 0: genesis = self.bt.get_consecutive_blocks(uint8(1))[0] pre_validation_results: List[ PreValidationResult] = await self.full_node.blockchain.pre_validate_blocks_multiprocessing( [genesis], {}, validate_signatures=True) assert pre_validation_results is not None await self.full_node.blockchain.receive_block( genesis, pre_validation_results[0]) peak = self.full_node.blockchain.get_peak() assert peak is not None curr: BlockRecord = peak while not curr.is_transaction_block: curr = self.full_node.blockchain.block_record(curr.prev_hash) mempool_bundle = await self.full_node.mempool_manager.create_bundle_from_mempool( curr.header_hash) if mempool_bundle is None: spend_bundle = None else: spend_bundle = mempool_bundle[0] current_blocks = await self.get_all_full_blocks() target = request.puzzle_hash more = self.bt.get_consecutive_blocks( 1, time_per_block=self.time_per_block, transaction_data=spend_bundle, farmer_reward_puzzle_hash=target, pool_reward_puzzle_hash=target, block_list_input=current_blocks, guarantee_transaction_block=True, current_time=self.use_current_time, previous_generator=self.full_node.full_node_store. previous_generator, ) rr = RespondBlock(more[-1]) await self.full_node.respond_block(rr)
async def test_change_pools_reorg(self, setup): """This tests Pool A -> escaping -> reorg -> escaping -> Pool B""" full_nodes, wallets, receive_address, client, rpc_cleanup = setup our_ph = receive_address[0] pool_a_ph = receive_address[1] pool_b_ph = await wallets[1].get_new_puzzlehash() full_node_api = full_nodes[0] WAIT_SECS = 30 try: summaries_response = await client.get_wallets() for summary in summaries_response: if WalletType(int(summary["type"])) == WalletType.POOLING_WALLET: assert False async def have_chia(): await self.farm_blocks(full_node_api, our_ph, 1) return (await wallets[0].get_confirmed_balance()) > 0 await time_out_assert(timeout=WAIT_SECS, function=have_chia) creation_tx: TransactionRecord = await client.create_new_pool_wallet( pool_a_ph, "https://pool-a.org", 5, "localhost:5000", "new", "FARMING_TO_POOL" ) await time_out_assert( 10, full_node_api.full_node.mempool_manager.get_spendbundle, creation_tx.spend_bundle, creation_tx.name, ) await self.farm_blocks(full_node_api, our_ph, 6) assert full_node_api.full_node.mempool_manager.get_spendbundle(creation_tx.name) is None summaries_response = await client.get_wallets() wallet_id: Optional[int] = None for summary in summaries_response: if WalletType(int(summary["type"])) == WalletType.POOLING_WALLET: wallet_id = summary["id"] assert wallet_id is not None status: PoolWalletInfo = (await client.pw_status(wallet_id))[0] assert status.current.state == PoolSingletonState.FARMING_TO_POOL.value assert status.target is None async def status_is_farming_to_pool(): await self.farm_blocks(full_node_api, our_ph, 1) pw_status: PoolWalletInfo = (await client.pw_status(wallet_id))[0] return pw_status.current.state == PoolSingletonState.FARMING_TO_POOL.value await time_out_assert(timeout=WAIT_SECS, function=status_is_farming_to_pool) pw_info: PoolWalletInfo = (await client.pw_status(wallet_id))[0] assert pw_info.current.pool_url == "https://pool-a.org" assert pw_info.current.relative_lock_height == 5 original_height = full_node_api.full_node.blockchain.get_peak().height join_pool_tx: TransactionRecord = await client.pw_join_pool( wallet_id, pool_b_ph, "https://pool-b.org", 10, ) assert join_pool_tx is not None await time_out_assert( 10, full_node_api.full_node.mempool_manager.get_spendbundle, join_pool_tx.spend_bundle, join_pool_tx.name, ) await self.farm_blocks(full_node_api, our_ph, 1) async def status_is_leaving_no_blocks(): pw_status: PoolWalletInfo = (await client.pw_status(wallet_id))[0] return pw_status.current.state == PoolSingletonState.LEAVING_POOL.value async def status_is_farming_to_pool_no_blocks(): pw_status: PoolWalletInfo = (await client.pw_status(wallet_id))[0] return pw_status.current.state == PoolSingletonState.FARMING_TO_POOL.value await time_out_assert(timeout=WAIT_SECS, function=status_is_leaving_no_blocks) log.warning(f"Doing reorg: {original_height - 1} {original_height + 2}") current_blocks = await full_node_api.get_all_full_blocks() more_blocks = full_node_api.bt.get_consecutive_blocks( 3, farmer_reward_puzzle_hash=pool_a_ph, pool_reward_puzzle_hash=pool_b_ph, block_list_input=current_blocks[:-1], force_overflow=True, guarantee_transaction_block=True, seed=32 * b"4", transaction_data=join_pool_tx.spend_bundle, ) for block in more_blocks[-3:]: await full_node_api.full_node.respond_block(RespondBlock(block)) await asyncio.sleep(5) await time_out_assert(timeout=WAIT_SECS, function=status_is_leaving_no_blocks) # Eventually, leaves pool await time_out_assert(timeout=WAIT_SECS, function=status_is_farming_to_pool) finally: client.close() await client.await_closed() await rpc_cleanup()