async def test_subscribe_for_hint_long_sync(self, wallet_two_node_simulator): num_blocks = 4 full_nodes, wallets = wallet_two_node_simulator full_node_api = full_nodes[0] full_node_api_1 = full_nodes[1] wallet_node, server_2 = wallets[0] fn_server = full_node_api.full_node.server fn_server_1 = full_node_api_1.full_node.server wsm: WalletStateManager = wallet_node.wallet_state_manager await server_2.start_client( PeerInfo(self_hostname, uint16(fn_server._port)), None) incoming_queue, peer_id = await add_dummy_connection( fn_server, 12312, NodeType.WALLET) incoming_queue_1, peer_id_1 = await add_dummy_connection( fn_server_1, 12313, NodeType.WALLET) wt: WalletTool = bt.get_pool_wallet_tool() ph = wt.get_new_puzzlehash() for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph)) await asyncio.sleep(6) coins = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hashes( False, [ph]) coin_spent = coins[0].coin hint_puzzle_hash = 32 * b"\2" amount = 1 amount_bin = int_to_bytes(1) hint = 32 * b"\5" fake_wallet_peer = fn_server.all_connections[peer_id] fake_wallet_peer_1 = fn_server_1.all_connections[peer_id_1] msg = wallet_protocol.RegisterForPhUpdates([hint], 0) msg_response = await full_node_api.register_interest_in_puzzle_hash( msg, fake_wallet_peer) msg_response_1 = await full_node_api_1.register_interest_in_puzzle_hash( msg, fake_wallet_peer_1) assert msg_response.type == ProtocolMessageTypes.respond_to_ph_update.value data_response: RespondToPhUpdates = RespondToCoinUpdates.from_bytes( msg_response.data) assert len(data_response.coin_states) == 0 condition_dict = { ConditionOpcode.CREATE_COIN: [ ConditionWithArgs(ConditionOpcode.CREATE_COIN, [hint_puzzle_hash, amount_bin, hint]) ] } tx: SpendBundle = wt.generate_signed_transaction( 10, wt.get_new_puzzlehash(), coin_spent, condition_dic=condition_dict, ) await full_node_api.respond_transaction(RespondTransaction(tx), fake_wallet_peer) await time_out_assert(15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx.name()) # Create more blocks than recent "short_sync_blocks_behind_threshold" so that node enters batch for i in range(0, 100): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph)) node1_height = full_node_api_1.full_node.blockchain.get_peak_height() assert node1_height is None await fn_server_1.start_client( PeerInfo(self_hostname, uint16(fn_server._port)), None) node0_height = full_node_api.full_node.blockchain.get_peak_height() await time_out_assert( 15, full_node_api_1.full_node.blockchain.get_peak_height, node0_height) all_messages = await self.get_all_messages_in_queue(incoming_queue) all_messages_1 = await self.get_all_messages_in_queue(incoming_queue_1) def check_messages_for_hint(messages): notified_state = None for message in messages: if message.type == ProtocolMessageTypes.coin_state_update.value: data_response: CoinStateUpdate = CoinStateUpdate.from_bytes( message.data) notified_state = data_response break assert notified_state is not None assert notified_state.items[0].coin == Coin( coin_spent.name(), hint_puzzle_hash, amount) check_messages_for_hint(all_messages) check_messages_for_hint(all_messages_1)
async def test_subscribe_for_ph(self, wallet_node_simulator): num_blocks = 4 full_nodes, wallets = wallet_node_simulator full_node_api = full_nodes[0] wallet_node, server_2 = wallets[0] fn_server = full_node_api.full_node.server wsm: WalletStateManager = wallet_node.wallet_state_manager await server_2.start_client( PeerInfo(self_hostname, uint16(fn_server._port)), None) incoming_queue, peer_id = await add_dummy_connection( fn_server, 12312, NodeType.WALLET) zero_ph = 32 * b"\0" junk_ph = 32 * b"\a" fake_wallet_peer = fn_server.all_connections[peer_id] msg = wallet_protocol.RegisterForPhUpdates([zero_ph], 0) msg_response = await full_node_api.register_interest_in_puzzle_hash( msg, fake_wallet_peer) assert msg_response.type == ProtocolMessageTypes.respond_to_ph_update.value data_response: RespondToPhUpdates = RespondToCoinUpdates.from_bytes( msg_response.data) assert data_response.coin_states == [] # Farm few more with reward for i in range(0, num_blocks): if i == num_blocks - 1: await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(zero_ph)) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(junk_ph)) else: await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(zero_ph)) msg = wallet_protocol.RegisterForPhUpdates([zero_ph], 0) msg_response = await full_node_api.register_interest_in_puzzle_hash( msg, fake_wallet_peer) assert msg_response.type == ProtocolMessageTypes.respond_to_ph_update.value data_response: RespondToPhUpdates = RespondToCoinUpdates.from_bytes( msg_response.data) assert len(data_response.coin_states ) == 2 * num_blocks # 2 per height farmer / pool reward # Farm more rewards to check the incoming queue for the updates for i in range(0, num_blocks): if i == num_blocks - 1: await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(zero_ph)) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(junk_ph)) else: await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(zero_ph)) all_messages = await self.get_all_messages_in_queue(incoming_queue) zero_coin = await full_node_api.full_node.coin_store.get_coin_states_by_puzzle_hashes( True, [zero_ph]) all_zero_coin = set(zero_coin) notified_zero_coins = set() for message in all_messages: if message.type == ProtocolMessageTypes.coin_state_update.value: data_response: CoinStateUpdate = CoinStateUpdate.from_bytes( message.data) for coin_state in data_response.items: notified_zero_coins.add(coin_state) assert len(data_response.items ) == 2 # 2 per height farmer / pool reward assert all_zero_coin == notified_zero_coins # Test subscribing to more coins one_ph = 32 * b"\1" msg = wallet_protocol.RegisterForPhUpdates([one_ph], 0) msg_response = await full_node_api.register_interest_in_puzzle_hash( msg, fake_wallet_peer) peak = full_node_api.full_node.blockchain.get_peak() for i in range(0, num_blocks): if i == num_blocks - 1: await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(zero_ph)) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(junk_ph)) else: await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(zero_ph)) for i in range(0, num_blocks): if i == num_blocks - 1: await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(one_ph)) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(junk_ph)) else: await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(one_ph)) zero_coins = await full_node_api.full_node.coin_store.get_coin_states_by_puzzle_hashes( True, [zero_ph], peak.height + 1) one_coins = await full_node_api.full_node.coin_store.get_coin_states_by_puzzle_hashes( True, [one_ph]) all_coins = set(zero_coins) all_coins.update(one_coins) all_messages = await self.get_all_messages_in_queue(incoming_queue) notified_all_coins = set() for message in all_messages: if message.type == ProtocolMessageTypes.coin_state_update.value: data_response: CoinStateUpdate = CoinStateUpdate.from_bytes( message.data) for coin_state in data_response.items: notified_all_coins.add(coin_state) assert len(data_response.items ) == 2 # 2 per height farmer / pool reward assert all_coins == notified_all_coins wsm: WalletStateManager = wallet_node.wallet_state_manager wallet: Wallet = wsm.wallets[1] puzzle_hash = await wallet.get_new_puzzlehash() for i in range(0, num_blocks): if i == num_blocks - 1: await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hash)) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(junk_ph)) else: await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hash)) funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks + 1) ]) fn_amount = sum(cr.coin.amount for cr in await full_node_api.full_node.coin_store. get_coin_records_by_puzzle_hash(False, puzzle_hash)) await time_out_assert(15, wallet.get_confirmed_balance, funds) assert funds == fn_amount msg_1 = wallet_protocol.RegisterForPhUpdates([puzzle_hash], 0) msg_response_1 = await full_node_api.register_interest_in_puzzle_hash( msg_1, fake_wallet_peer) assert msg_response_1.type == ProtocolMessageTypes.respond_to_ph_update.value data_response_1: RespondToPhUpdates = RespondToCoinUpdates.from_bytes( msg_response_1.data) assert len(data_response_1.coin_states ) == 2 * num_blocks # 2 per height farmer / pool reward tx_record = await wallet.generate_signed_transaction( uint64(10), puzzle_hash, uint64(0)) assert len(tx_record.spend_bundle.removals()) == 1 spent_coin = tx_record.spend_bundle.removals()[0] assert spent_coin.puzzle_hash == puzzle_hash await wallet.push_transaction(tx_record) await time_out_assert(15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hash)) # Let's make sure the wallet can handle a non ephemeral launcher from chia.wallet.puzzles.singleton_top_layer import SINGLETON_LAUNCHER_HASH tx_record = await wallet.generate_signed_transaction( uint64(10), SINGLETON_LAUNCHER_HASH, uint64(0)) await wallet.push_transaction(tx_record) await time_out_assert(15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(SINGLETON_LAUNCHER_HASH)) # Send a transaction to make sure the wallet is still running tx_record = await wallet.generate_signed_transaction( uint64(10), junk_ph, uint64(0)) await wallet.push_transaction(tx_record) await time_out_assert(15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hash)) all_messages = await self.get_all_messages_in_queue(incoming_queue) notified_state = None for message in all_messages: if message.type == ProtocolMessageTypes.coin_state_update.value: data_response: CoinStateUpdate = CoinStateUpdate.from_bytes( message.data) for coin_state in data_response.items: if coin_state.coin.name() == spent_coin.name(): notified_state = coin_state assert notified_state is not None assert notified_state.coin == spent_coin assert notified_state.spent_height is not None
async def test_subscribe_for_coin_id(self, wallet_node_simulator): num_blocks = 4 full_nodes, wallets = wallet_node_simulator full_node_api = full_nodes[0] wallet_node, server_2 = wallets[0] fn_server = full_node_api.full_node.server wsm: WalletStateManager = wallet_node.wallet_state_manager standard_wallet: Wallet = wsm.wallets[1] puzzle_hash = await standard_wallet.get_new_puzzlehash() await server_2.start_client( PeerInfo(self_hostname, uint16(fn_server._port)), None) incoming_queue, peer_id = await add_dummy_connection( fn_server, 12312, NodeType.WALLET) fake_wallet_peer = fn_server.all_connections[peer_id] # Farm to create a coin that we'll track for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hash)) funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks) ]) await time_out_assert(15, standard_wallet.get_confirmed_balance, funds) my_coins: List[ CoinRecord] = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hash( True, puzzle_hash) coin_to_spend = my_coins[0].coin msg = wallet_protocol.RegisterForCoinUpdates([coin_to_spend.name()], 0) msg_response = await full_node_api.register_interest_in_coin( msg, fake_wallet_peer) assert msg_response is not None assert msg_response.type == ProtocolMessageTypes.respond_to_coin_update.value data_response: RespondToCoinUpdates = RespondToCoinUpdates.from_bytes( msg_response.data) assert data_response.coin_states[0].coin == coin_to_spend coins = set() coins.add(coin_to_spend) tx_record = await standard_wallet.generate_signed_transaction( uint64(10), puzzle_hash, uint64(0), coins=coins) await standard_wallet.push_transaction(tx_record) await time_out_assert(15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()) # Farm transaction for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hash)) all_messages = await self.get_all_messages_in_queue(incoming_queue) notified_coins = set() for message in all_messages: if message.type == ProtocolMessageTypes.coin_state_update.value: data_response: CoinStateUpdate = CoinStateUpdate.from_bytes( message.data) for coin_state in data_response.items: notified_coins.add(coin_state.coin) assert coin_state.spent_height is not None assert notified_coins == coins # Test getting notification for coin that is about to be created tx_record = await standard_wallet.generate_signed_transaction( uint64(10), puzzle_hash, uint64(0)) tx_record.spend_bundle.additions() added_target: Optional[Coin] = None for coin in tx_record.spend_bundle.additions(): if coin.puzzle_hash == puzzle_hash: added_target = coin assert added_target is not None msg = wallet_protocol.RegisterForCoinUpdates([added_target.name()], 0) msg_response = await full_node_api.register_interest_in_coin( msg, fake_wallet_peer) assert msg_response is not None assert msg_response.type == ProtocolMessageTypes.respond_to_coin_update.value data_response: RespondToCoinUpdates = RespondToCoinUpdates.from_bytes( msg_response.data) assert len(data_response.coin_states) == 0 await standard_wallet.push_transaction(tx_record) await time_out_assert(15, tx_in_pool, True, full_node_api.full_node.mempool_manager, tx_record.spend_bundle.name()) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hash)) all_messages = await self.get_all_messages_in_queue(incoming_queue) notified_state = None for message in all_messages: if message.type == ProtocolMessageTypes.coin_state_update.value: data_response: CoinStateUpdate = CoinStateUpdate.from_bytes( message.data) for coin_state in data_response.items: if coin_state.coin.name() == added_target.name(): notified_state = coin_state assert notified_state is not None assert notified_state.coin == added_target assert notified_state.spent_height is None