async def test_wallet_coinbase_reorg(self, wallet_node): num_blocks = 5 full_nodes, wallets = wallet_node full_node_api = full_nodes[0] fn_server = full_node_api.full_node.server wallet_node, server_2 = wallets[0] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client( PeerInfo(self_hostname, uint16(fn_server._port)), None) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph)) 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.get_confirmed_balance, funds) await full_node_api.reorg_from_index_to_new_index( ReorgProtocol(uint32(2), uint32(num_blocks + 6), 32 * b"0")) funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks - 2) ]) await time_out_assert(5, wallet.get_confirmed_balance, funds)
async def farm_block(self, request): raw_puzzle_hash = decode_puzzle_hash(request["address"]) request = FarmNewBlockProtocol(raw_puzzle_hash) msg = make_msg(ProtocolMessageTypes.farm_new_block, request) await self.service.server.send_to_all([msg], NodeType.FULL_NODE) return {}
async def test_address_sliding_window(self, wallet_node_100_pk): full_nodes, wallets = wallet_node_100_pk full_node_api = full_nodes[0] server_1: ChiaServer = full_node_api.full_node.server wallet_node, server_2 = wallets[0] wallet = wallet_node.wallet_state_manager.main_wallet await server_2.start_client( PeerInfo(self_hostname, uint16(server_1._port)), None) puzzle_hashes = [] for i in range(211): pubkey = master_sk_to_wallet_sk( wallet_node.wallet_state_manager.private_key, i).get_g1() puzzle: Program = wallet.puzzle_for_pk(bytes(pubkey)) puzzle_hash: bytes32 = puzzle.get_tree_hash() puzzle_hashes.append(puzzle_hash) # TODO: fix after merging new wallet. These 210 and 114 should be found await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hashes[0])) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hashes[210])) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hashes[114])) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) await time_out_assert(5, wallet.get_confirmed_balance, 2 * 10**12) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hashes[50])) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) await time_out_assert(5, wallet.get_confirmed_balance, 4 * 10**12) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hashes[113])) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hashes[209])) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) await time_out_assert(5, wallet.get_confirmed_balance, 8 * 10**12)
async def test_wallet_coinbase(self, wallet_node): num_blocks = 10 full_nodes, wallets = wallet_node full_node_api = full_nodes[0] server_1: ChiaServer = full_node_api.full_node.server wallet_node, server_2 = wallets[0] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo(self_hostname, uint16(server_1._port)), None) for i in range(0, num_blocks): await full_node_api.farm_new_block(FarmNewBlockProtocol(ph)) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks + 2) ] ) async def check_tx_are_pool_farm_rewards(): wsm: WalletStateManager = wallet_node.wallet_state_manager all_txs = await wsm.get_all_transactions(1) expected_count = (num_blocks + 1) * 2 if len(all_txs) != expected_count: return False pool_rewards = 0 farm_rewards = 0 for tx in all_txs: if tx.type == TransactionType.COINBASE_REWARD: pool_rewards += 1 elif tx.type == TransactionType.FEE_REWARD: farm_rewards += 1 if pool_rewards != expected_count / 2: return False if farm_rewards != expected_count / 2: return False return True await time_out_assert(10, check_tx_are_pool_farm_rewards, True) await time_out_assert(5, wallet.get_confirmed_balance, funds)
async def wallets_prefarm(two_wallet_nodes, trusted): """ Sets up the node with 10 blocks, and returns a payer and payee wallet. """ farm_blocks = 10 buffer = 4 full_nodes, wallets = two_wallet_nodes full_node_api = full_nodes[0] full_node_server = full_node_api.server wallet_node_0, wallet_server_0 = wallets[0] wallet_node_1, wallet_server_1 = wallets[1] wallet_0 = wallet_node_0.wallet_state_manager.main_wallet wallet_1 = wallet_node_1.wallet_state_manager.main_wallet ph0 = await wallet_0.get_new_puzzlehash() ph1 = await wallet_1.get_new_puzzlehash() if trusted: wallet_node_0.config["trusted_peers"] = { full_node_server.node_id.hex(): full_node_server.node_id.hex() } wallet_node_1.config["trusted_peers"] = { full_node_server.node_id.hex(): full_node_server.node_id.hex() } else: wallet_node_0.config["trusted_peers"] = {} wallet_node_1.config["trusted_peers"] = {} await wallet_server_0.start_client( PeerInfo("localhost", uint16(full_node_server._port)), None) await wallet_server_1.start_client( PeerInfo("localhost", uint16(full_node_server._port)), None) for i in range(0, farm_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph0)) for i in range(0, farm_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph1)) for i in range(0, buffer): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(token_bytes())) return wallet_node_0, wallet_node_1, full_node_api
async def test_did_recovery_with_empty_set(self, two_wallet_nodes): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1 = full_nodes[0] server_1 = full_node_1.server wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None) await server_3.start_client(PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks - 1) ] ) await time_out_assert(15, wallet.get_confirmed_balance, funds) async with wallet_node.wallet_state_manager.lock: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(101) ) for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, did_wallet.get_confirmed_balance, 101) await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101) coins = await did_wallet.select_coins(1) coin = coins.pop() info = Program.to([]) pubkey = (await did_wallet.wallet_state_manager.get_unused_derivation_record(did_wallet.wallet_info.id)).pubkey spend_bundle = await did_wallet.recovery_spend( coin, ph, info, pubkey, SpendBundle([], AugSchemeMPL.aggregate([])) ) additions = spend_bundle.additions() assert additions == []
async def test_wallet_reorg_sync(self, wallet_node_simulator, default_400_blocks, trusted): num_blocks = 5 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 wallet = wsm.main_wallet ph = await wallet.get_new_puzzlehash() if trusted: wallet_node.config["trusted_peers"] = { fn_server.node_id.hex(): fn_server.node_id.hex() } else: wallet_node.config["trusted_peers"] = {} await server_2.start_client( PeerInfo(self_hostname, uint16(fn_server._port)), None) # Insert 400 blocks for block in default_400_blocks: await full_node_api.full_node.respond_block( full_node_protocol.RespondBlock(block)) # Farm few more with reward for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph)) # Confirm we have the funds 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.get_confirmed_balance, funds) async def get_tx_count(wallet_id): txs = await wsm.get_all_transactions(wallet_id) return len(txs) await time_out_assert(5, get_tx_count, 2 * (num_blocks - 1), 1) # Reorg blocks that carry reward num_blocks = 30 blocks_reorg = bt.get_consecutive_blocks( num_blocks, block_list_input=default_400_blocks[:-5]) for block in blocks_reorg[-30:]: await full_node_api.full_node.respond_block( full_node_protocol.RespondBlock(block)) await time_out_assert(5, get_tx_count, 0, 1) await time_out_assert(5, wallet.get_confirmed_balance, 0)
async def test_wallet_make_transaction(self, two_wallet_nodes): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_api = full_nodes[0] server_1 = full_node_api.full_node.server wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo(self_hostname, uint16(server_1._port)), None) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) 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.get_confirmed_balance, funds) await time_out_assert(5, wallet.get_unconfirmed_balance, funds) tx = await wallet.generate_signed_transaction( 10, await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash(), 0, ) await wallet.push_transaction(tx) await time_out_assert(5, wallet.get_confirmed_balance, funds) await time_out_assert(5, wallet.get_unconfirmed_balance, funds - 10) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) new_funds = sum( [ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, (2 * num_blocks)) ] ) await time_out_assert(5, wallet.get_confirmed_balance, new_funds - 10) await time_out_assert(5, wallet.get_unconfirmed_balance, new_funds - 10)
async def test_cc_trade_cancel_secure(self, wallets_prefarm): # Wallet A Wallet B # CCWallet id 2: 50 CCWallet id 2: 50 # CCWallet id 3: 50 CCWallet id 3: 50 # CCWallet id 4: 40 CCWallet id 4: 60 # Wallet A will create offer, cancel it by spending coins back to self wallet_node_a, wallet_node_b, full_node = wallets_prefarm wallet_a = wallet_node_a.wallet_state_manager.main_wallet trade_manager_a: TradeManager = wallet_node_a.wallet_state_manager.trade_manager file = "test_offer_file.offer" file_path = Path(file) if file_path.exists(): file_path.unlink() spendable_chia = await wallet_a.get_spendable_balance() offer_dict = {1: 10, 2: -30, 3: 30} success, trade_offer, error = await trade_manager_a.create_offer_for_ids( offer_dict, file) await asyncio.sleep(1) spendable_chia_after = await wallet_a.get_spendable_balance() locked_coin = await trade_manager_a.get_locked_coins(wallet_a.id()) locked_sum = 0 for name, record in locked_coin.items(): locked_sum += record.coin.amount assert spendable_chia == spendable_chia_after + locked_sum assert success is True assert trade_offer is not None # Cancel offer 1 by spending coins that were offered await trade_manager_a.cancel_pending_offer_safely(trade_offer.trade_id) await asyncio.sleep(1) for i in range(0, buffer_blocks): await full_node.farm_new_transaction_block( FarmNewBlockProtocol(token_bytes())) await time_out_assert(15, wallet_a.get_spendable_balance, spendable_chia) # Spendable should be the same as it was before making offer 1 async def get_status(): assert trade_offer is not None trade_a = await trade_manager_a.get_trade_by_id( trade_offer.trade_id) assert trade_a is not None return trade_a.status await time_out_assert(15, get_status, TradeStatus.CANCELED.value)
async def test_colour_creation(self, two_wallet_nodes): num_blocks = 3 full_nodes, wallets = two_wallet_nodes full_node_api = full_nodes[0] full_node_server = full_node_api.server wallet_node, server_2 = wallets[0] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(full_node_server._port)), None) for i in range(1, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph)) funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks - 1) ]) await time_out_assert(15, wallet.get_confirmed_balance, funds) cc_wallet: CCWallet = await CCWallet.create_new_cc( wallet_node.wallet_state_manager, wallet, uint64(100)) tx_queue: List[ TransactionRecord] = await wallet_node.wallet_state_manager.tx_store.get_not_sent( ) tx_record = tx_queue[0] 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(1, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) await time_out_assert(15, cc_wallet.get_confirmed_balance, 100) await time_out_assert(15, cc_wallet.get_unconfirmed_balance, 100)
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 test_wallet_coinbase(self, wallet_node): num_blocks = 5 full_nodes, wallets = wallet_node full_node_api = full_nodes[0] full_node_server = full_node_api.server wallet_node, server_2 = wallets[0] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client( PeerInfo(self_hostname, uint16(full_node_server._port)), None) for i in range(num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph)) funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks) ]) # funds += calculate_base_farmer_reward(0) await asyncio.sleep(2) print(await wallet.get_confirmed_balance(), funds) await time_out_assert(10, wallet.get_confirmed_balance, funds)
async def test_create_new_pool_wallet(self, one_wallet_node): full_nodes, wallets = one_wallet_node full_node_api = full_nodes[0] full_node_server = full_node_api.server wallet_node_0, wallet_server_0 = wallets[0] wsm: WalletStateManager = wallet_node_0.wallet_state_manager wallet_0 = wallet_node_0.wallet_state_manager.main_wallet ph = await wallet_0.get_new_puzzlehash() await wallet_server_0.start_client( PeerInfo(self_hostname, uint16(full_node_server._port)), None) for i in range(3): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph)) all_blocks: List[FullBlock] = await full_node_api.get_all_full_blocks() h: uint32 = all_blocks[-1].height await asyncio.sleep(3) owner_sk: PrivateKey = master_sk_to_singleton_owner_sk( wsm.private_key, 3) initial_state = PoolState(1, FARMING_TO_POOL, ph, owner_sk.get_g1(), "pool.com", uint32(10)) tx_record, _, _ = await PoolWallet.create_new_pool_wallet_transaction( wsm, wallet_0, initial_state) launcher_spend: CoinSolution = tx_record.spend_bundle.coin_solutions[1] async with wsm.db_wrapper.lock: pw = await PoolWallet.create(wsm, wallet_0, launcher_spend.coin.name(), tx_record.spend_bundle.coin_solutions, h, True) log.warning(await pw.get_current_state())
async def test_wallet_create_hit_max_send_amount(self, two_wallet_nodes, trusted): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() if trusted: wallet_node.config["trusted_peers"] = { full_node_1.full_node.server.node_id.hex(): full_node_1.full_node.server.node_id.hex() } wallet_node_2.config["trusted_peers"] = { full_node_1.full_node.server.node_id.hex(): full_node_1.full_node.server.node_id.hex() } else: wallet_node.config["trusted_peers"] = {} wallet_node_2.config["trusted_peers"] = {} await server_2.start_client( PeerInfo(self_hostname, uint16(full_node_1.full_node.server._port)), None) for i in range(0, num_blocks): await full_node_1.farm_new_transaction_block( FarmNewBlockProtocol(ph)) 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.get_confirmed_balance, funds) primaries = [] for i in range(0, 600): primaries.append({"puzzlehash": ph, "amount": 100000000 + i}) tx_split_coins = await wallet.generate_signed_transaction( 1, ph, 0, primaries=primaries) await wallet.push_transaction(tx_split_coins) await time_out_assert(15, tx_in_pool, True, full_node_1.full_node.mempool_manager, tx_split_coins.spend_bundle.name()) for i in range(0, num_blocks): await full_node_1.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks + 1) ]) await time_out_assert(90, wallet.get_confirmed_balance, funds) max_sent_amount = await wallet.get_max_send_amount() # 1) Generate transaction that is under the limit under_limit_tx = None try: under_limit_tx = await wallet.generate_signed_transaction( max_sent_amount - 1, ph, 0, ) except ValueError: assert ValueError assert under_limit_tx is not None # 2) Generate transaction that is equal to limit at_limit_tx = None try: at_limit_tx = await wallet.generate_signed_transaction( max_sent_amount, ph, 0, ) except ValueError: assert ValueError assert at_limit_tx is not None # 3) Generate transaction that is greater than limit above_limit_tx = None try: above_limit_tx = await wallet.generate_signed_transaction( max_sent_amount + 1, ph, 0, ) except ValueError: pass assert above_limit_tx is None
async def test_wallet_make_transaction_with_fee(self, two_wallet_nodes, trusted): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() if trusted: wallet_node.config["trusted_peers"] = { full_node_1.full_node.server.node_id.hex(): full_node_1.full_node.server.node_id.hex() } wallet_node_2.config["trusted_peers"] = { full_node_1.full_node.server.node_id.hex(): full_node_1.full_node.server.node_id.hex() } else: wallet_node.config["trusted_peers"] = {} wallet_node_2.config["trusted_peers"] = {} await server_2.start_client( PeerInfo(self_hostname, uint16(full_node_1.full_node.server._port)), None) for i in range(0, num_blocks): await full_node_1.farm_new_transaction_block( FarmNewBlockProtocol(ph)) 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.get_confirmed_balance, funds) await time_out_assert(5, wallet.get_unconfirmed_balance, funds) assert await wallet.get_confirmed_balance() == funds assert await wallet.get_unconfirmed_balance() == funds tx_amount = 3200000000000 tx_fee = 10 tx = await wallet.generate_signed_transaction( tx_amount, await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash( ), tx_fee, ) fees = tx.spend_bundle.fees() assert fees == tx_fee await wallet.push_transaction(tx) await time_out_assert( 5, full_node_1.full_node.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name) await time_out_assert(5, wallet.get_confirmed_balance, funds) await time_out_assert(5, wallet.get_unconfirmed_balance, funds - tx_amount - tx_fee) for i in range(0, num_blocks): await full_node_1.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) new_funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks + 1) ]) await time_out_assert(5, wallet.get_confirmed_balance, new_funds - tx_amount - tx_fee) await time_out_assert(5, wallet.get_unconfirmed_balance, new_funds - tx_amount - tx_fee)
async def test_wallet_make_transaction_hop(self, two_wallet_nodes_five_freeze, trusted): num_blocks = 10 full_nodes, wallets = two_wallet_nodes_five_freeze full_node_api_0 = full_nodes[0] full_node_0 = full_node_api_0.full_node server_0 = full_node_0.server wallet_node_0, wallet_0_server = wallets[0] wallet_node_1, wallet_1_server = wallets[1] wallet_0 = wallet_node_0.wallet_state_manager.main_wallet wallet_1 = wallet_node_1.wallet_state_manager.main_wallet ph = await wallet_0.get_new_puzzlehash() if trusted: wallet_node_0.config["trusted_peers"] = { server_0.node_id.hex(): server_0.node_id.hex() } wallet_node_1.config["trusted_peers"] = { server_0.node_id.hex(): server_0.node_id.hex() } else: wallet_node_0.config["trusted_peers"] = {} wallet_node_1.config["trusted_peers"] = {} await wallet_0_server.start_client( PeerInfo(self_hostname, uint16(server_0._port)), None) await wallet_1_server.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)) 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.get_confirmed_balance, funds) await time_out_assert(5, wallet_0.get_unconfirmed_balance, funds) assert await wallet_0.get_confirmed_balance() == funds assert await wallet_0.get_unconfirmed_balance() == funds tx = await wallet_0.generate_signed_transaction( 10, await wallet_node_1.wallet_state_manager.main_wallet.get_new_puzzlehash( ), 0, ) await wallet_0.push_transaction(tx) await time_out_assert(5, full_node_0.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name) # Full node height 11, wallet height 9 await time_out_assert(5, wallet_0.get_confirmed_balance, funds) await time_out_assert(5, wallet_0.get_unconfirmed_balance, funds - 10) for i in range(0, 4): await full_node_api_0.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) # here it's num_blocks + 1 because our last reward is included in the first block that we just farmed new_funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks + 1) ]) # Full node height 17, wallet height 15 await time_out_assert(5, wallet_0.get_confirmed_balance, new_funds - 10) await time_out_assert(5, wallet_0.get_unconfirmed_balance, new_funds - 10) await time_out_assert(5, wallet_1.get_confirmed_balance, 10) tx = await wallet_1.generate_signed_transaction( 5, await wallet_0.get_new_puzzlehash(), 0) await wallet_1.push_transaction(tx) await time_out_assert(5, full_node_0.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name) for i in range(0, 4): await full_node_api_0.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) await wallet_0.get_confirmed_balance() await wallet_0.get_unconfirmed_balance() await wallet_1.get_confirmed_balance() await time_out_assert(5, wallet_0.get_confirmed_balance, new_funds - 5) await time_out_assert(5, wallet_0.get_unconfirmed_balance, new_funds - 5) await time_out_assert(5, wallet_1.get_confirmed_balance, 5)
async def test_create_rl_coin(self, three_wallet_nodes): num_blocks = 4 full_nodes, wallets = three_wallet_nodes full_node_api = full_nodes[0] full_node_server = full_node_api.server wallet_node, server_2 = wallets[0] wallet_node_1, wallet_server_1 = wallets[1] wallet_node_2, wallet_server_2 = wallets[2] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None) await wallet_server_1.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None) await wallet_server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None) await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) for i in range(0, num_blocks + 1): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"\0")) fund_owners_initial_balance = await wallet.get_confirmed_balance() api_user = WalletRpcApi(wallet_node_1) val = await api_user.create_new_wallet( {"wallet_type": "rl_wallet", "rl_type": "user", "host": f"{self_hostname}:5000"} ) assert isinstance(val, dict) if "success" in val: assert val["success"] assert val["id"] assert val["type"] == WalletType.RATE_LIMITED.value user_wallet_id = val["id"] pubkey = val["pubkey"] api_admin = WalletRpcApi(wallet_node) val = await api_admin.create_new_wallet( { "wallet_type": "rl_wallet", "rl_type": "admin", "interval": 2, "limit": 10, "pubkey": pubkey, "amount": 100, "fee": 1, "host": f"{self_hostname}:5000", } ) assert isinstance(val, dict) if "success" in val: assert val["success"] assert val["id"] assert val["type"] == WalletType.RATE_LIMITED.value assert val["origin"] assert val["pubkey"] admin_wallet_id = val["id"] admin_pubkey = val["pubkey"] origin: Coin = val["origin"] await api_user.rl_set_user_info( { "wallet_id": user_wallet_id, "interval": 2, "limit": 10, "origin": { "parent_coin_info": origin.parent_coin_info.hex(), "puzzle_hash": origin.puzzle_hash.hex(), "amount": origin.amount, }, "admin_pubkey": admin_pubkey, } ) assert (await api_user.get_wallet_balance({"wallet_id": user_wallet_id}))["wallet_balance"][ "confirmed_wallet_balance" ] == 0 for i in range(0, 2 * num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"\0")) assert await wallet.get_confirmed_balance() == fund_owners_initial_balance - 101 async def check_balance(api, wallet_id): balance_response = await api.get_wallet_balance({"wallet_id": wallet_id}) balance = balance_response["wallet_balance"]["confirmed_wallet_balance"] return balance await time_out_assert(15, check_balance, 100, api_user, user_wallet_id) receiving_wallet = wallet_node_2.wallet_state_manager.main_wallet address = encode_puzzle_hash(await receiving_wallet.get_new_puzzlehash(), "xch") assert await receiving_wallet.get_spendable_balance() == 0 val = await api_user.send_transaction({"wallet_id": user_wallet_id, "amount": 3, "fee": 2, "address": address}) assert "transaction_id" in val async def is_transaction_in_mempool(api, tx_id: bytes32) -> bool: try: val = await api.get_transaction({"wallet_id": user_wallet_id, "transaction_id": tx_id.hex()}) except ValueError: return False for _, mis, _ in val["transaction"].sent_to: if ( MempoolInclusionStatus(mis) == MempoolInclusionStatus.SUCCESS or MempoolInclusionStatus(mis) == MempoolInclusionStatus.PENDING ): return True return False await time_out_assert(15, is_transaction_in_mempool, True, api_user, val["transaction_id"]) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"\0")) await time_out_assert(15, check_balance, 95, api_user, user_wallet_id) await time_out_assert(15, receiving_wallet.get_spendable_balance, 3) val = await api_admin.add_rate_limited_funds({"wallet_id": admin_wallet_id, "amount": 100, "fee": 7}) assert val["status"] == "SUCCESS" for i in range(0, 50): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"\0")) await time_out_assert(15, check_balance, 195, api_user, user_wallet_id) # test spending puzzle_hash = encode_puzzle_hash(await receiving_wallet.get_new_puzzlehash(), "xch") val = await api_user.send_transaction( { "wallet_id": user_wallet_id, "amount": 105, "fee": 0, "address": puzzle_hash, } ) await time_out_assert(15, is_transaction_in_mempool, True, api_user, val["transaction_id"]) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"\0")) await time_out_assert(15, check_balance, 90, api_user, user_wallet_id) await time_out_assert(15, receiving_wallet.get_spendable_balance, 108) val = await api_admin.send_clawback_transaction({"wallet_id": admin_wallet_id, "fee": 11}) await time_out_assert(15, is_transaction_in_mempool, True, api_admin, val["transaction_id"]) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(32 * b"\0")) await time_out_assert(15, check_balance, 0, api_user, user_wallet_id) await time_out_assert(15, check_balance, 0, api_admin, user_wallet_id) final_balance = await wallet.get_confirmed_balance() assert final_balance == fund_owners_initial_balance - 129
async def test_creation_from_backup_file(self, three_wallet_nodes): num_blocks = 5 full_nodes, wallets = three_wallet_nodes full_node_api = full_nodes[0] full_node_server = full_node_api.server wallet_node_0, server_0 = wallets[0] wallet_node_1, server_1 = wallets[1] wallet_node_2, server_2 = wallets[2] wallet_0 = wallet_node_0.wallet_state_manager.main_wallet wallet_1 = wallet_node_1.wallet_state_manager.main_wallet wallet_2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet_0.get_new_puzzlehash() ph1 = await wallet_1.get_new_puzzlehash() ph2 = await wallet_2.get_new_puzzlehash() await server_0.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None) await server_1.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None) await server_2.start_client(PeerInfo("localhost", uint16(full_node_server._port)), None) for i in range(1, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks - 1) ] ) await time_out_assert(10, wallet_0.get_unconfirmed_balance, funds) await time_out_assert(10, wallet_0.get_confirmed_balance, funds) for i in range(1, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph1)) for i in range(1, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph2)) # Wallet1 sets up DIDWallet1 without any backup set async with wallet_node_0.wallet_state_manager.lock: did_wallet_0: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_0.wallet_state_manager, wallet_0, uint64(101) ) for i in range(1, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, did_wallet_0.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_0.get_unconfirmed_balance, 101) await time_out_assert(15, did_wallet_0.get_pending_change_balance, 0) # Wallet1 sets up DIDWallet_1 with DIDWallet_0 as backup backup_ids = [bytes.fromhex(did_wallet_0.get_my_DID())] async with wallet_node_1.wallet_state_manager.lock: did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_1.wallet_state_manager, wallet_1, uint64(201), backup_ids ) for i in range(1, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, did_wallet_1.get_confirmed_balance, 201) await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 201) await time_out_assert(15, did_wallet_1.get_pending_change_balance, 0) filename = "test.backup" did_wallet_1.create_backup(filename) # Wallet2 recovers DIDWallet2 to a new set of keys async with wallet_node_2.wallet_state_manager.lock: did_wallet_2 = await DIDWallet.create_new_did_wallet_from_recovery( wallet_node_2.wallet_state_manager, wallet_2, filename ) coins = await did_wallet_1.select_coins(1) coin = coins.copy().pop() assert did_wallet_2.did_info.temp_coin == coin newpuzhash = await did_wallet_2.get_new_inner_hash() pubkey = bytes( (await did_wallet_2.wallet_state_manager.get_unused_derivation_record(did_wallet_2.wallet_info.id)).pubkey ) message_spend_bundle = await did_wallet_0.create_attestment( did_wallet_2.did_info.temp_coin.name(), newpuzhash, pubkey, "test.attest" ) print(f"pubkey: {pubkey}") for i in range(1, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) ( test_info_list, test_message_spend_bundle, ) = await did_wallet_2.load_attest_files_for_recovery_spend(["test.attest"]) assert message_spend_bundle == test_message_spend_bundle await did_wallet_2.recovery_spend( did_wallet_2.did_info.temp_coin, newpuzhash, test_info_list, pubkey, test_message_spend_bundle, ) print(f"pubkey: {did_wallet_2}") for i in range(1, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) await time_out_assert(45, did_wallet_2.get_confirmed_balance, 201) await time_out_assert(45, did_wallet_2.get_unconfirmed_balance, 201) some_ph = 32 * b"\2" await did_wallet_2.create_exit_spend(some_ph) for i in range(1, num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) async def get_coins_with_ph(): coins = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hash(True, some_ph) if len(coins) == 1: return True return False await time_out_assert(15, get_coins_with_ph, True) await time_out_assert(45, did_wallet_2.get_confirmed_balance, 0) await time_out_assert(45, did_wallet_2.get_unconfirmed_balance, 0)
async def test_did_attest_after_recovery(self, two_wallet_nodes): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1 = full_nodes[0] server_1 = full_node_1.server wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet wallet2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None) await server_3.start_client(PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks - 1) ] ) await time_out_assert(15, wallet.get_confirmed_balance, funds) async with wallet_node.wallet_state_manager.lock: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(101) ) ph2 = await wallet2.get_new_puzzlehash() for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph2)) await time_out_assert(15, did_wallet.get_confirmed_balance, 101) await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101) recovery_list = [bytes.fromhex(did_wallet.get_my_DID())] async with wallet_node_2.wallet_state_manager.lock: did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_2.wallet_state_manager, wallet2, uint64(101), recovery_list ) ph = await wallet.get_new_puzzlehash() for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, did_wallet_2.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_2.get_unconfirmed_balance, 101) assert did_wallet_2.did_info.backup_ids == recovery_list # Update coin with new ID info recovery_list = [bytes.fromhex(did_wallet_2.get_my_DID())] await did_wallet.update_recovery_list(recovery_list, uint64(1)) assert did_wallet.did_info.backup_ids == recovery_list await did_wallet.create_update_spend() for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph2)) await time_out_assert(15, did_wallet.get_confirmed_balance, 101) await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101) # DID Wallet 2 recovers into DID Wallet 3 with new innerpuz filename = "test.backup" did_wallet_2.create_backup(filename) async with wallet_node.wallet_state_manager.lock: did_wallet_3 = await DIDWallet.create_new_did_wallet_from_recovery( wallet_node.wallet_state_manager, wallet, filename, ) new_ph = await did_wallet_3.get_new_inner_hash() coins = await did_wallet_2.select_coins(1) coin = coins.pop() pubkey = ( await did_wallet_3.wallet_state_manager.get_unused_derivation_record(did_wallet_3.wallet_info.id) ).pubkey message_spend_bundle = await did_wallet.create_attestment(coin.name(), new_ph, pubkey, "test.attest") for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph2)) ( info, message_spend_bundle, ) = await did_wallet_3.load_attest_files_for_recovery_spend(["test.attest"]) await did_wallet_3.recovery_spend(coin, new_ph, info, pubkey, message_spend_bundle) for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, did_wallet_3.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_3.get_unconfirmed_balance, 101) # DID Wallet 1 recovery spends into DID Wallet 4 filename = "test.backup" did_wallet.create_backup(filename) async with wallet_node_2.wallet_state_manager.lock: did_wallet_4 = await DIDWallet.create_new_did_wallet_from_recovery( wallet_node_2.wallet_state_manager, wallet2, filename, ) coins = await did_wallet.select_coins(1) coin = coins.pop() new_ph = await did_wallet_4.get_new_inner_hash() pubkey = ( await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_4.wallet_info.id) ).pubkey await did_wallet_3.create_attestment(coin.name(), new_ph, pubkey, "test.attest") for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph2)) ( test_info_list, test_message_spend_bundle, ) = await did_wallet_4.load_attest_files_for_recovery_spend(["test.attest"]) spend_bundle = await did_wallet_4.recovery_spend( coin, new_ph, test_info_list, pubkey, test_message_spend_bundle ) await time_out_assert_not_none(15, full_node_1.full_node.mempool_manager.get_spendbundle, spend_bundle.name()) for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, did_wallet_4.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_4.get_unconfirmed_balance, 101) await time_out_assert(15, did_wallet.get_confirmed_balance, 0) await time_out_assert(15, did_wallet.get_unconfirmed_balance, 0)
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
async def test_did_recovery_with_multiple_backup_dids(self, two_wallet_nodes): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1 = full_nodes[0] server_1 = full_node_1.server wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet wallet2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() await server_2.start_client(PeerInfo("localhost", uint16(server_1._port)), None) await server_3.start_client(PeerInfo("localhost", uint16(server_1._port)), None) for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph)) funds = sum( [ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks - 1) ] ) await time_out_assert(15, wallet.get_confirmed_balance, funds) async with wallet_node.wallet_state_manager.lock: did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(101) ) ph = await wallet2.get_new_puzzlehash() for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, did_wallet.get_confirmed_balance, 101) await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101) recovery_list = [bytes.fromhex(did_wallet.get_my_DID())] async with wallet_node_2.wallet_state_manager.lock: did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_2.wallet_state_manager, wallet2, uint64(101), recovery_list ) for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph)) await time_out_assert(15, did_wallet_2.get_confirmed_balance, 101) await time_out_assert(15, did_wallet_2.get_unconfirmed_balance, 101) assert did_wallet_2.did_info.backup_ids == recovery_list recovery_list.append(bytes.fromhex(did_wallet_2.get_my_DID())) async with wallet_node_2.wallet_state_manager.lock: did_wallet_3: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_2.wallet_state_manager, wallet2, uint64(201), recovery_list ) ph2 = await wallet.get_new_puzzlehash() for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph2)) assert did_wallet_3.did_info.backup_ids == recovery_list await time_out_assert(15, did_wallet_3.get_confirmed_balance, 201) await time_out_assert(15, did_wallet_3.get_unconfirmed_balance, 201) coins = await did_wallet_3.select_coins(1) coin = coins.pop() filename = "test.backup" did_wallet_3.create_backup(filename) async with wallet_node.wallet_state_manager.lock: did_wallet_4 = await DIDWallet.create_new_did_wallet_from_recovery( wallet_node.wallet_state_manager, wallet, filename, ) pubkey = ( await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_2.wallet_info.id) ).pubkey new_ph = await did_wallet_4.get_new_inner_hash() message_spend_bundle = await did_wallet.create_attestment(coin.name(), new_ph, pubkey, "test1.attest") message_spend_bundle2 = await did_wallet_2.create_attestment(coin.name(), new_ph, pubkey, "test2.attest") message_spend_bundle = message_spend_bundle.aggregate([message_spend_bundle, message_spend_bundle2]) ( test_info_list, test_message_spend_bundle, ) = await did_wallet_4.load_attest_files_for_recovery_spend(["test1.attest", "test2.attest"]) assert message_spend_bundle == test_message_spend_bundle for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph2)) await did_wallet_4.recovery_spend(coin, new_ph, test_info_list, pubkey, message_spend_bundle) for i in range(1, num_blocks): await full_node_1.farm_new_transaction_block(FarmNewBlockProtocol(ph2)) await time_out_assert(15, did_wallet_4.get_confirmed_balance, 201) await time_out_assert(15, did_wallet_4.get_unconfirmed_balance, 201) await time_out_assert(15, did_wallet_3.get_confirmed_balance, 0) await time_out_assert(15, did_wallet_3.get_unconfirmed_balance, 0)
async def farm_blocks(self, full_node_api, ph: bytes32, num_blocks: int): for i in range(num_blocks): await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph)) return num_blocks
async def test_wallet_make_transaction(self, two_wallet_nodes): test_rpc_port = uint16(21529) test_rpc_port_node = uint16(21530) num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_api = full_nodes[0] full_node_server = full_node_api.full_node.server wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet wallet_2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() ph_2 = await wallet_2.get_new_puzzlehash() await server_2.start_client( PeerInfo("localhost", uint16(full_node_server._port)), None) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph)) initial_funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks) ]) initial_funds_eventually = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks + 1) ]) wallet_rpc_api = WalletRpcApi(wallet_node) config = bt.config hostname = config["self_hostname"] daemon_port = config["daemon_port"] def stop_node_cb(): pass full_node_rpc_api = FullNodeRpcApi(full_node_api.full_node) rpc_cleanup_node = await start_rpc_server( full_node_rpc_api, hostname, daemon_port, test_rpc_port_node, stop_node_cb, bt.root_path, config, connect_to_daemon=False, ) rpc_cleanup = await start_rpc_server( wallet_rpc_api, hostname, daemon_port, test_rpc_port, stop_node_cb, bt.root_path, config, connect_to_daemon=False, ) await time_out_assert(5, wallet.get_confirmed_balance, initial_funds) await time_out_assert(5, wallet.get_unconfirmed_balance, initial_funds) client = await WalletRpcClient.create(self_hostname, test_rpc_port, bt.root_path, config) await validate_get_routes(client, wallet_rpc_api) client_node = await FullNodeRpcClient.create(self_hostname, test_rpc_port_node, bt.root_path, config) try: addr = encode_puzzle_hash( await wallet_node_2.wallet_state_manager.main_wallet. get_new_puzzlehash(), "xch") tx_amount = 15600000 try: await client.send_transaction("1", 100000000000000001, addr) raise Exception("Should not create high value tx") except ValueError: pass # Tests sending a basic transaction tx = await client.send_transaction("1", tx_amount, addr) transaction_id = tx.name async def tx_in_mempool(): tx = await client.get_transaction("1", transaction_id) return tx.is_in_mempool() await time_out_assert(5, tx_in_mempool, True) await time_out_assert(5, wallet.get_unconfirmed_balance, initial_funds - tx_amount) assert ( await client.get_wallet_balance("1") )["unconfirmed_wallet_balance"] == initial_funds - tx_amount assert (await client.get_wallet_balance("1") )["confirmed_wallet_balance"] == initial_funds for i in range(0, 5): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph_2)) async def eventual_balance(): return ( await client.get_wallet_balance("1"))["confirmed_wallet_balance"] await time_out_assert(5, eventual_balance, initial_funds_eventually - tx_amount) # Tests offline signing ph_3 = await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash( ) ph_4 = await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash( ) ph_5 = await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash( ) # Test basic transaction to one output signed_tx_amount = 888000 tx_res: TransactionRecord = await client.create_signed_transaction( [{ "amount": signed_tx_amount, "puzzle_hash": ph_3 }]) assert tx_res.fee_amount == 0 assert tx_res.amount == signed_tx_amount assert len(tx_res.additions) == 2 # The output and the change assert any([ addition.amount == signed_tx_amount for addition in tx_res.additions ]) push_res = await client_node.push_tx(tx_res.spend_bundle) assert push_res["success"] assert ( await client.get_wallet_balance("1") )["confirmed_wallet_balance"] == initial_funds_eventually - tx_amount for i in range(0, 5): await client.farm_block(encode_puzzle_hash(ph_2, "xch")) await asyncio.sleep(0.5) await time_out_assert( 5, eventual_balance, initial_funds_eventually - tx_amount - signed_tx_amount) # Test transaction to two outputs, from a specified coin, with a fee coin_to_spend = None for addition in tx_res.additions: if addition.amount != signed_tx_amount: coin_to_spend = addition assert coin_to_spend is not None tx_res = await client.create_signed_transaction( [{ "amount": 444, "puzzle_hash": ph_4 }, { "amount": 999, "puzzle_hash": ph_5 }], coins=[coin_to_spend], fee=100, ) assert tx_res.fee_amount == 100 assert tx_res.amount == 444 + 999 assert len(tx_res.additions) == 3 # The outputs and the change assert any( [addition.amount == 444 for addition in tx_res.additions]) assert any( [addition.amount == 999 for addition in tx_res.additions]) assert sum([rem.amount for rem in tx_res.removals]) - sum( [ad.amount for ad in tx_res.additions]) == 100 push_res = await client_node.push_tx(tx_res.spend_bundle) assert push_res["success"] for i in range(0, 5): await client.farm_block(encode_puzzle_hash(ph_2, "xch")) await asyncio.sleep(0.5) new_balance = initial_funds_eventually - tx_amount - signed_tx_amount - 444 - 999 - 100 await time_out_assert(5, eventual_balance, new_balance) send_tx_res: TransactionRecord = await client.send_transaction_multi( "1", [{ "amount": 555, "puzzle_hash": ph_4 }, { "amount": 666, "puzzle_hash": ph_5 }], fee=200) assert send_tx_res is not None assert send_tx_res.fee_amount == 200 assert send_tx_res.amount == 555 + 666 assert len( send_tx_res.additions) == 3 # The outputs and the change assert any( [addition.amount == 555 for addition in send_tx_res.additions]) assert any( [addition.amount == 666 for addition in send_tx_res.additions]) assert (sum([rem.amount for rem in send_tx_res.removals]) - sum([ad.amount for ad in send_tx_res.additions]) == 200) await asyncio.sleep(3) for i in range(0, 5): await client.farm_block(encode_puzzle_hash(ph_2, "xch")) await asyncio.sleep(0.5) new_balance = new_balance - 555 - 666 - 200 await time_out_assert(5, eventual_balance, new_balance) address = await client.get_next_address("1", True) assert len(address) > 10 transactions = await client.get_transactions("1") assert len(transactions) > 1 all_transactions = await client.get_transactions("1") # Test transaction pagination some_transactions = await client.get_transactions("1", 0, 5) some_transactions_2 = await client.get_transactions("1", 5, 10) assert some_transactions == all_transactions[0:5] assert some_transactions_2 == all_transactions[5:10] # Testing sorts # Test the default sort (CONFIRMED_AT_HEIGHT) assert all_transactions == sorted( all_transactions, key=attrgetter("confirmed_at_height")) all_transactions = await client.get_transactions("1", reverse=True) assert all_transactions == sorted( all_transactions, key=attrgetter("confirmed_at_height"), reverse=True) # Test RELEVANCE await client.send_transaction("1", 1, encode_puzzle_hash(ph_2, "xch") ) # Create a pending tx all_transactions = await client.get_transactions( "1", sort_key=SortKey.RELEVANCE) sorted_transactions = sorted(all_transactions, key=attrgetter("created_at_time"), reverse=True) sorted_transactions = sorted(sorted_transactions, key=attrgetter("confirmed_at_height"), reverse=True) sorted_transactions = sorted(sorted_transactions, key=attrgetter("confirmed")) assert all_transactions == sorted_transactions all_transactions = await client.get_transactions( "1", sort_key=SortKey.RELEVANCE, reverse=True) sorted_transactions = sorted(all_transactions, key=attrgetter("created_at_time")) sorted_transactions = sorted(sorted_transactions, key=attrgetter("confirmed_at_height")) sorted_transactions = sorted(sorted_transactions, key=attrgetter("confirmed"), reverse=True) assert all_transactions == sorted_transactions pks = await client.get_public_keys() assert len(pks) == 1 assert (await client.get_height_info()) > 0 created_tx = await client.send_transaction("1", tx_amount, addr) async def tx_in_mempool_2(): tx = await client.get_transaction("1", created_tx.name) return tx.is_in_mempool() await time_out_assert(5, tx_in_mempool_2, True) assert len(await wallet.wallet_state_manager.tx_store. get_unconfirmed_for_wallet(1)) == 2 await client.delete_unconfirmed_transactions("1") assert len(await wallet.wallet_state_manager.tx_store. get_unconfirmed_for_wallet(1)) == 0 sk_dict = await client.get_private_key(pks[0]) assert sk_dict["fingerprint"] == pks[0] assert sk_dict["sk"] is not None assert sk_dict["pk"] is not None assert sk_dict["seed"] is not None mnemonic = await client.generate_mnemonic() assert len(mnemonic) == 24 await client.add_key(mnemonic) pks = await client.get_public_keys() assert len(pks) == 2 await client.log_in_and_skip(pks[1]) sk_dict = await client.get_private_key(pks[1]) assert sk_dict["fingerprint"] == pks[1] fingerprint = await client.get_logged_in_fingerprint() assert fingerprint == pks[1] # Add in reward addresses into farmer and pool for testing delete key checks # set farmer to first private key sk = await wallet_node.get_key_for_fingerprint(pks[0]) test_ph = create_puzzlehash_for_pk( master_sk_to_wallet_sk(sk, uint32(0)).get_g1()) test_config = load_config(wallet_node.root_path, "config.yaml") test_config["farmer"]["xch_target_address"] = encode_puzzle_hash( test_ph, "txch") # set pool to second private key sk = await wallet_node.get_key_for_fingerprint(pks[1]) test_ph = create_puzzlehash_for_pk( master_sk_to_wallet_sk(sk, uint32(0)).get_g1()) test_config["pool"]["xch_target_address"] = encode_puzzle_hash( test_ph, "txch") save_config(wallet_node.root_path, "config.yaml", test_config) # Check first key sk_dict = await client.check_delete_key(pks[0]) assert sk_dict["fingerprint"] == pks[0] assert sk_dict["used_for_farmer_rewards"] is True assert sk_dict["used_for_pool_rewards"] is False # Check second key sk_dict = await client.check_delete_key(pks[1]) assert sk_dict["fingerprint"] == pks[1] assert sk_dict["used_for_farmer_rewards"] is False assert sk_dict["used_for_pool_rewards"] is True # Check unknown key sk_dict = await client.check_delete_key(123456) assert sk_dict["fingerprint"] == 123456 assert sk_dict["used_for_farmer_rewards"] is False assert sk_dict["used_for_pool_rewards"] is False await client.delete_key(pks[0]) await client.log_in_and_skip(pks[1]) assert len(await client.get_public_keys()) == 1 assert not (await client.get_sync_status()) wallets = await client.get_wallets() assert len(wallets) == 1 balance = await client.get_wallet_balance(wallets[0]["id"]) assert balance["unconfirmed_wallet_balance"] == 0 test_wallet_backup_path = Path("test_wallet_backup_file") await client.create_backup(test_wallet_backup_path) assert test_wallet_backup_path.exists() test_wallet_backup_path.unlink() try: await client.send_transaction(wallets[0]["id"], 100, addr) raise Exception("Should not create tx if no balance") except ValueError: pass await client.delete_all_keys() assert len(await client.get_public_keys()) == 0 finally: # Checks that the RPC manages to stop the node client.close() client_node.close() await client.await_closed() await client_node.await_closed() await rpc_cleanup() await rpc_cleanup_node()
async def test_subscribe_for_coin_id_reorg(self, wallet_node_simulator): num_blocks = 4 long_blocks = 20 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] zero_ph = 32 * b"\0" # 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(zero_ph)) for i in range(0, long_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(zero_ph)) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(puzzle_hash)) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(zero_ph)) expected_height = uint32(long_blocks + 2 * num_blocks + 1) await time_out_assert( 15, full_node_api.full_node.blockchain.get_peak_height, expected_height) coin_records = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hash( True, puzzle_hash) assert len(coin_records) > 0 for coin_rec in coin_records: msg = wallet_protocol.RegisterForCoinUpdates([coin_rec.name], 0) msg_response = await full_node_api.register_interest_in_coin( msg, fake_wallet_peer) assert msg_response is not None fork_height = expected_height - num_blocks - 5 req = ReorgProtocol(fork_height, expected_height + 5, zero_ph) await full_node_api.reorg_from_index_to_new_index(req) coin_records = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hash( True, puzzle_hash) assert coin_records == [] all_messages = await self.get_all_messages_in_queue(incoming_queue) coin_update_messages = [] for message in all_messages: if message.type == ProtocolMessageTypes.coin_state_update.value: data_response: CoinStateUpdate = CoinStateUpdate.from_bytes( message.data) coin_update_messages.append(data_response) assert len(coin_update_messages) == 1 update = coin_update_messages[0] coin_states = update.items assert len(coin_states) == 2 first_coin = coin_states[0] assert first_coin.spent_height is None assert first_coin.created_height is None second_coin = coin_states[1] assert second_coin.spent_height is None assert second_coin.created_height is None
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_wallet_prevent_fee_theft(self, two_wallet_nodes, trusted): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_1 = full_nodes[0] wallet_node, server_2 = wallets[0] wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() if trusted: wallet_node.config["trusted_peers"] = { full_node_1.full_node.server.node_id.hex(): full_node_1.full_node.server.node_id.hex() } wallet_node_2.config["trusted_peers"] = { full_node_1.full_node.server.node_id.hex(): full_node_1.full_node.server.node_id.hex() } else: wallet_node.config["trusted_peers"] = {} wallet_node_2.config["trusted_peers"] = {} await server_2.start_client( PeerInfo(self_hostname, uint16(full_node_1.full_node.server._port)), None) for i in range(0, num_blocks): await full_node_1.farm_new_transaction_block( FarmNewBlockProtocol(ph)) 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.get_confirmed_balance, funds) await time_out_assert(5, wallet.get_unconfirmed_balance, funds) assert await wallet.get_confirmed_balance() == funds assert await wallet.get_unconfirmed_balance() == funds tx_amount = 3200000000000 tx_fee = 300000000000 tx = await wallet.generate_signed_transaction( tx_amount, await wallet_node_2.wallet_state_manager.main_wallet.get_new_puzzlehash( ), tx_fee, ) # extract coin_spend from generated spend_bundle for cs in tx.spend_bundle.coin_spends: if cs.additions() == []: stolen_cs = cs # get a legit signature stolen_sb = await wallet.sign_transaction([stolen_cs]) now = uint64(int(time.time())) add_list = list(stolen_sb.additions()) rem_list = list(stolen_sb.removals()) name = stolen_sb.name() stolen_tx = TransactionRecord( confirmed_at_height=uint32(0), created_at_time=now, to_puzzle_hash=32 * b"0", amount=0, fee_amount=stolen_cs.coin.amount, confirmed=False, sent=uint32(0), spend_bundle=stolen_sb, additions=add_list, removals=rem_list, wallet_id=wallet.id(), sent_to=[], trade_id=None, type=uint32(TransactionType.OUTGOING_TX.value), name=name, memos=list(compute_memos(stolen_sb).items()), ) await wallet.push_transaction(stolen_tx) await time_out_assert(5, wallet.get_confirmed_balance, funds) await time_out_assert(5, wallet.get_unconfirmed_balance, funds - stolen_cs.coin.amount) for i in range(0, num_blocks): await full_node_1.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) # Funds have not decreased because stolen_tx was rejected outstanding_coinbase_rewards = 2000000000000 await time_out_assert(20, wallet.get_confirmed_balance, funds + outstanding_coinbase_rewards)
async def test_mempool_tx_sync(self, three_nodes_two_wallets): num_blocks = 5 full_nodes, wallets = three_nodes_two_wallets wallet_0, wallet_server_0 = wallets[0] full_node_api_0 = full_nodes[0] server_0 = full_node_api_0.server full_node_api_1 = full_nodes[1] server_1 = full_node_api_1.server full_node_api_2 = full_nodes[2] server_2 = full_node_api_2.server ph = await wallet_0.wallet_state_manager.main_wallet.get_new_puzzlehash( ) # wallet0 <-> sever0 <-> server1 await wallet_server_0.start_client( PeerInfo(self_hostname, uint16(server_0._port)), None) await server_0.start_client( PeerInfo(self_hostname, uint16(server_1._port)), None) for i in range(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_api_2.full_node.respond_block( full_node_protocol.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( 10, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, funds) tx = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction( 10, token_bytes(), 0) await wallet_0.wallet_state_manager.main_wallet.push_transaction(tx) await time_out_assert( 10, full_node_api_0.full_node.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name, ) await time_out_assert( 10, full_node_api_1.full_node.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name, ) await time_out_assert( 10, full_node_api_2.full_node.mempool_manager.get_spendbundle, None, tx.name, ) # make a final connection. # wallet0 <-> sever0 <-> server1 <-> server2 await server_1.start_client( PeerInfo(self_hostname, uint16(server_2._port)), None) await time_out_assert( 10, full_node_api_0.full_node.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name, ) await time_out_assert( 10, full_node_api_1.full_node.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name, ) await time_out_assert( 10, full_node_api_2.full_node.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name, )
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_wallet_tx_reorg(self, two_wallet_nodes, trusted): num_blocks = 5 full_nodes, wallets = two_wallet_nodes full_node_api = full_nodes[0] fn_server = full_node_api.full_node.server wallet_node, server_2 = wallets[0] wallet_node: WalletNode = wallet_node wallet_node_2, server_3 = wallets[1] wallet = wallet_node.wallet_state_manager.main_wallet wallet_2 = wallet_node_2.wallet_state_manager.main_wallet ph = await wallet.get_new_puzzlehash() ph2 = await wallet_2.get_new_puzzlehash() if trusted: wallet_node.config["trusted_peers"] = { fn_server.node_id.hex(): fn_server.node_id.hex() } wallet_node_2.config["trusted_peers"] = { fn_server.node_id.hex(): fn_server.node_id.hex() } else: wallet_node.config["trusted_peers"] = {} wallet_node_2.config["trusted_peers"] = {} await server_2.start_client( PeerInfo(self_hostname, uint16(fn_server._port)), None) await server_3.start_client( PeerInfo(self_hostname, uint16(fn_server._port)), None) for i in range(0, num_blocks): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph)) funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks) ]) # Waits a few seconds to receive rewards all_blocks = await full_node_api.get_all_full_blocks() # Ensure that we use a coin that we will not reorg out coin = list(all_blocks[-3].get_included_reward_coins())[0] await asyncio.sleep(5) tx = await wallet.generate_signed_transaction(1000, ph2, coins={coin}) await wallet.push_transaction(tx) await full_node_api.full_node.respond_transaction( tx.spend_bundle, tx.name) await time_out_assert( 5, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name) await time_out_assert(5, wallet.get_confirmed_balance, funds) for i in range(0, 2): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) await time_out_assert(5, wallet_2.get_confirmed_balance, 1000) await time_out_assert( 5, wallet_node.wallet_state_manager.blockchain.get_peak_height, 7) peak_height = full_node_api.full_node.blockchain.get_peak().height print(peak_height) # Perform a reorg, which will revert the transaction in the full node and wallet, and cause wallet to resubmit await full_node_api.reorg_from_index_to_new_index( ReorgProtocol(uint32(peak_height - 3), uint32(peak_height + 3), 32 * b"0")) funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, peak_height - 2) ]) await time_out_assert( 7, full_node_api.full_node.blockchain.get_peak_height, peak_height + 3) await time_out_assert( 7, wallet_node.wallet_state_manager.blockchain.get_peak_height, peak_height + 3) # Farm a few blocks so we can confirm the resubmitted transaction for i in range(0, num_blocks): await asyncio.sleep(1) await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(32 * b"0")) # By this point, the transaction should be confirmed await time_out_assert(15, wallet.get_confirmed_balance, funds - 1000) unconfirmed = await wallet_node.wallet_state_manager.tx_store.get_unconfirmed_for_wallet( int(wallet.id())) assert len(unconfirmed) == 0 tx_record = await wallet_node.wallet_state_manager.tx_store.get_transaction_record( tx.name) removed = tx_record.removals[0] added = tx_record.additions[0] added_1 = tx_record.additions[1] wallet_coin_record_rem = await wallet_node.wallet_state_manager.coin_store.get_coin_record( removed.name()) assert wallet_coin_record_rem.spent coin_record_full_node = await full_node_api.full_node.coin_store.get_coin_record( removed.name()) assert coin_record_full_node.spent add_1_coin_record_full_node = await full_node_api.full_node.coin_store.get_coin_record( added.name()) assert add_1_coin_record_full_node is not None assert add_1_coin_record_full_node.confirmed_block_index > 0 add_2_coin_record_full_node = await full_node_api.full_node.coin_store.get_coin_record( added_1.name()) assert add_2_coin_record_full_node is not None assert add_2_coin_record_full_node.confirmed_block_index > 0
async def test_tx_propagation(self, three_nodes_two_wallets): num_blocks = 5 full_nodes, wallets = three_nodes_two_wallets wallet_0, wallet_server_0 = wallets[0] wallet_1, wallet_server_1 = wallets[1] full_node_api_0 = full_nodes[0] server_0 = full_node_api_0.server full_node_api_1 = full_nodes[1] server_1 = full_node_api_1.server full_node_api_2 = full_nodes[2] server_2 = full_node_api_2.server ph = await wallet_0.wallet_state_manager.main_wallet.get_new_puzzlehash( ) ph1 = await wallet_1.wallet_state_manager.main_wallet.get_new_puzzlehash( ) # # wallet0 <-> sever0 <-> server1 <-> server2 <-> wallet1 # await wallet_server_0.start_client( PeerInfo(self_hostname, uint16(server_0._port)), None) await server_0.start_client( PeerInfo(self_hostname, uint16(server_1._port)), None) await server_1.start_client( PeerInfo(self_hostname, uint16(server_2._port)), None) await wallet_server_1.start_client( PeerInfo(self_hostname, uint16(server_2._port)), None) for i in range(num_blocks): await full_node_api_0.farm_new_transaction_block( FarmNewBlockProtocol(ph)) funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks) ]) await time_out_assert( 10, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, funds) async def peak_height(fna: FullNodeAPI): peak: Optional[BlockRecord] = fna.full_node.blockchain.get_peak() if peak is None: return -1 peak_height = peak.height return peak_height await time_out_assert(10, peak_height, num_blocks, full_node_api_1) await time_out_assert(10, peak_height, num_blocks, full_node_api_2) tx = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction( 10, ph1, 0) await wallet_0.wallet_state_manager.main_wallet.push_transaction(tx) await time_out_assert( 10, full_node_api_0.full_node.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name, ) await time_out_assert( 10, full_node_api_1.full_node.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name, ) await time_out_assert( 10, full_node_api_2.full_node.mempool_manager.get_spendbundle, tx.spend_bundle, tx.name, ) # Farm another block for i in range(1, 8): await full_node_api_1.farm_new_transaction_block( FarmNewBlockProtocol(token_bytes())) funds = sum([ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks + 1) ]) print(f"Funds: {funds}") await time_out_assert( 10, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, (funds - 10), ) await time_out_assert( 15, wallet_1.wallet_state_manager.main_wallet.get_confirmed_balance, 10)