async def test_correct_block_index(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = await full_node_1.get_all_full_blocks() start_height = blocks[-1].height blocks = bt.get_consecutive_blocks( 3, block_list_input=blocks, guarantee_transaction_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) peer = await connect_and_get_peer(server_1, server_2) for block in blocks: await full_node_1.full_node.respond_block( full_node_protocol.RespondBlock(block)) await time_out_assert(60, node_height_at_least, True, full_node_1, start_height + 3) cvp = ConditionVarPair(ConditionOpcode.ASSERT_HEIGHT_NOW_EXCEEDS, [uint64(1).to_bytes(4, "big")]) dic = {ConditionOpcode.ASSERT_HEIGHT_NOW_EXCEEDS: [cvp]} spend_bundle1 = generate_test_spend_bundle( list(blocks[-1].get_included_reward_coins())[0], dic) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1) await full_node_1.respond_transaction(tx1, peer) sb1 = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle1.name()) assert sb1 is spend_bundle1
async def test_correct_my_id(self, two_nodes): num_blocks = 2 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash) full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] for b in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(b)): pass cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID, block.header.data.coinbase.name(), None) dic = {cvp.opcode: [cvp]} spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.header.data.coinbase, dic) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1) async for _ in full_node_1.respond_transaction(tx1): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name()) assert sb1 is spend_bundle1
async def test_correct_block_index(self, two_nodes): num_blocks = 2 wallet_a = bt.get_pool_wallet_tool() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"") full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass cvp = ConditionVarPair( ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS, uint64(1).to_bytes(4, "big"), None, ) dic = {ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS: [cvp]} spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.get_coinbase(), dic) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle1)) async for _ in full_node_1.respond_transaction(tx1): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" sb1 = full_node_1.mempool_manager.get_spendbundle(spend_bundle1.name()) assert sb1 is spend_bundle1
async def test_invalid_coin_consumed(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = await full_node_1.get_all_full_blocks() start_sub_height = blocks[-1].sub_block_height blocks = bt.get_consecutive_blocks( 4, block_list_input=blocks, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) peer = await connect_and_get_peer(server_1, server_2) for block in blocks: await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(block)) await time_out_assert(60, node_height_at_least, True, full_node_1, start_sub_height + 3) for b in blocks: await full_node_1.full_node.respond_sub_block(full_node_protocol.RespondSubBlock(b)) coin_1 = list(blocks[-2].get_included_reward_coins())[0] coin_2 = list(blocks[-1].get_included_reward_coins())[0] cvp = ConditionVarPair(ConditionOpcode.ASSERT_COIN_CONSUMED, [coin_2.name()]) dic = {cvp.opcode: [cvp]} spend_bundle1 = generate_test_spend_bundle(coin_1, dic) assert spend_bundle1 is not None tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1) await full_node_1.respond_transaction(tx1, peer) mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name()) assert mempool_bundle is None
async def test_basic_mempool(self, two_nodes): num_blocks = 2 blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"") full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block) ): pass spend_bundle = generate_test_spend_bundle(block.get_coinbase()) assert spend_bundle is not None tx: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle) ) async for _ in full_node_1.respond_transaction(tx): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name()) assert sb is spend_bundle
async def test_stealing_fee(self, two_nodes): num_blocks = 2 wallet_a = bt.get_pool_wallet_tool() wallet_receiver = bt.get_farmer_wallet_tool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"") blocks = bt.get_consecutive_blocks(test_constants, num_blocks, blocks, 10, b"") full_node_1, full_node_2, server_1, server_2 = two_nodes block = blocks[1] wallet_2_block = blocks[3] for b in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(b)): pass cvp = ConditionVarPair( ConditionOpcode.ASSERT_FEE, int_to_bytes(10), None, ) dic = {cvp.opcode: [cvp]} fee = 9 spend_bundle1 = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, block.get_coinbase(), dic, fee) wallet_2_fees = wallet_2_block.get_fees_coin() steal_fee_spendbundle = wallet_receiver.generate_signed_transaction( wallet_2_fees.amount + fee - 4, receiver_puzzlehash, wallet_2_fees) assert spend_bundle1 is not None assert steal_fee_spendbundle is not None combined = SpendBundle.aggregate( [spend_bundle1, steal_fee_spendbundle]) assert combined.fees() == 4 tx1: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle1)) outbound_messages: List[OutboundMessage] = [] async for outbound in full_node_1.respond_transaction(tx1): outbound_messages.append(outbound) new_transaction = False for msg in outbound_messages: if msg.message.function == "new_transaction": new_transaction = True assert new_transaction is False mempool_bundle = full_node_1.mempool_manager.get_spendbundle( spend_bundle1.name()) assert mempool_bundle is None
async def test_invalid_filter(self, two_nodes): num_blocks = 10 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash) full_node_1, full_node_2, server_1, server_2 = two_nodes for block in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass spent_block = blocks[1] spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spent_block.get_coinbase()) assert spend_bundle is not None tx: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle)) async for _ in full_node_1.respond_transaction(tx): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name()) assert sb is spend_bundle last_block = blocks[10] next_spendbundle = await full_node_1.mempool_manager.create_bundle_for_tip( last_block.header) assert next_spendbundle is not None program = best_solution_program(next_spendbundle) aggsig = next_spendbundle.aggregated_signature dic_h = {11: (program, aggsig)} new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h) next_block = new_blocks[11] bad_header = HeaderData( next_block.header.data.height, next_block.header.data.prev_header_hash, next_block.header.data.timestamp, bytes32(bytes([3] * 32)), next_block.header.data.proof_of_space_hash, next_block.header.data.weight, next_block.header.data.total_iters, next_block.header.data.additions_root, next_block.header.data.removals_root, next_block.header.data.farmer_rewards_puzzle_hash, next_block.header.data.total_transaction_fees, next_block.header.data.pool_target, next_block.header.data.aggregated_signature, next_block.header.data.cost, next_block.header.data.extension_data, next_block.header.data.generator_hash, ) bad_block = FullBlock( next_block.proof_of_space, next_block.proof_of_time, Header( bad_header, bt.get_plot_signature( bad_header, next_block.proof_of_space.plot_public_key), ), next_block.transactions_generator, next_block.transactions_filter, ) result, removed, error_code = await full_node_1.blockchain.receive_block( bad_block) assert result == ReceiveBlockResult.INVALID_BLOCK assert error_code == Err.INVALID_TRANSACTIONS_FILTER_HASH result, removed, error_code = await full_node_1.blockchain.receive_block( next_block) assert result == ReceiveBlockResult.ADDED_TO_HEAD
async def test_basic_blockchain_tx(self, two_nodes): num_blocks = 10 wallet_a = WalletTool() coinbase_puzzlehash = wallet_a.get_new_puzzlehash() wallet_receiver = WalletTool() receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10, b"", coinbase_puzzlehash) full_node_1, full_node_2, server_1, server_2 = two_nodes for block in blocks: async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(block)): pass spent_block = blocks[1] spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spent_block.get_coinbase()) assert spend_bundle is not None tx: full_node_protocol.RespondTransaction = ( full_node_protocol.RespondTransaction(spend_bundle)) async for _ in full_node_1.respond_transaction(tx): outbound: OutboundMessage = _ # Maybe transaction means that it's accepted in mempool assert outbound.message.function == "new_transaction" sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name()) assert sb is spend_bundle last_block = blocks[10] next_spendbundle = await full_node_1.mempool_manager.create_bundle_for_tip( last_block.header) assert next_spendbundle is not None program = best_solution_program(next_spendbundle) aggsig = next_spendbundle.aggregated_signature dic_h = {11: (program, aggsig)} new_blocks = bt.get_consecutive_blocks(test_constants, 1, blocks, 10, b"", coinbase_puzzlehash, dic_h) next_block = new_blocks[11] async for _ in full_node_1.respond_block( full_node_protocol.RespondBlock(next_block)): pass tips = full_node_1.blockchain.get_current_tips() assert next_block.header in tips added_coins = next_spendbundle.additions() # Two coins are added, main spend and change assert len(added_coins) == 2 for coin in added_coins: unspent = await full_node_1.coin_store.get_coin_record( coin.name(), next_block.header) assert unspent is not None full_tips = await full_node_1.blockchain.get_full_tips() in_full_tips = False farmed_block: Optional[FullBlock] = None for tip in full_tips: if tip.header == next_block.header: in_full_tips = True farmed_block = tip assert in_full_tips assert farmed_block is not None assert farmed_block.transactions_generator == program
async def test_transaction_freeze(self, wallet_node_30_freeze): num_blocks = 5 full_nodes, wallets = wallet_node_30_freeze full_node_api: FullNodeSimulator = 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() incoming_queue, node_id = await add_dummy_connection( full_node_server, 12312) 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) tx: TransactionRecord = await wallet.generate_signed_transaction( 100, ph, 0) spend = wallet_protocol.SendTransaction(tx.spend_bundle) response = await full_node_api.send_transaction(spend) assert wallet_protocol.TransactionAck.from_bytes( response.data).status == MempoolInclusionStatus.FAILED new_spend = full_node_protocol.NewTransaction(tx.spend_bundle.name(), 1, 0) response = await full_node_api.new_transaction(new_spend) assert response is None peer = full_node_server.all_connections[node_id] new_spend = full_node_protocol.RespondTransaction(tx.spend_bundle) response = await full_node_api.respond_transaction(new_spend, peer=peer) assert response is None for i in range(26): await full_node_api.farm_new_transaction_block( FarmNewBlockProtocol(ph)) new_spend = full_node_protocol.NewTransaction(tx.spend_bundle.name(), 1, 0) response = await full_node_api.new_transaction(new_spend) assert response is not None assert ProtocolMessageTypes( response.type) == ProtocolMessageTypes.request_transaction tx: TransactionRecord = await wallet.generate_signed_transaction( 100, ph, 0) spend = wallet_protocol.SendTransaction(tx.spend_bundle) response = await full_node_api.send_transaction(spend) assert response is not None assert wallet_protocol.TransactionAck.from_bytes( response.data).status == MempoolInclusionStatus.SUCCESS assert ProtocolMessageTypes( response.type) == ProtocolMessageTypes.transaction_ack
async def test_basic_blockchain_tx(self, two_nodes): num_blocks = 10 wallet_a = WALLET_A coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0] receiver_puzzlehash = BURN_PUZZLE_HASH blocks = bt.get_consecutive_blocks( num_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_transaction_block=True) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes peer = await connect_and_get_peer(server_1, server_2) full_node_1 = full_node_api_1.full_node for block in blocks: await full_node_api_1.full_node.respond_block( full_node_protocol.RespondBlock(block), None) spend_block = blocks[2] spend_coin = None for coin in list(spend_block.get_included_reward_coins()): if coin.puzzle_hash == coinbase_puzzlehash: spend_coin = coin spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin) assert spend_bundle is not None tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle) await full_node_api_1.respond_transaction(tx, peer) sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name()) assert sb is spend_bundle last_block = blocks[-1] next_spendbundle, additions, removals = await full_node_1.mempool_manager.create_bundle_from_mempool( last_block.header_hash) assert next_spendbundle is not None new_blocks = bt.get_consecutive_blocks( 1, block_list_input=blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=next_spendbundle, guarantee_transaction_block=True, ) next_block = new_blocks[-1] await full_node_1.respond_block( full_node_protocol.RespondBlock(next_block)) assert next_block.header_hash == full_node_1.blockchain.get_peak( ).header_hash added_coins = next_spendbundle.additions() # Two coins are added, main spend and change assert len(added_coins) == 2 for coin in added_coins: unspent = await full_node_1.coin_store.get_coin_record(coin.name()) assert unspent is not None assert not unspent.spent assert not unspent.coinbase
async def test_new_transaction(self, two_nodes, wallet_blocks_five): full_node_1, full_node_2, server_1, server_2 = two_nodes wallet_a, wallet_receiver, blocks = wallet_blocks_five conditions_dict: Dict = {ConditionOpcode.CREATE_COIN: []} # Mempool has capacity of 100, make 110 unspents that we can use puzzle_hashes = [] for _ in range(110): receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() puzzle_hashes.append(receiver_puzzlehash) output = ConditionVarPair( ConditionOpcode.CREATE_COIN, receiver_puzzlehash, int_to_bytes(1000) ) conditions_dict[ConditionOpcode.CREATE_COIN].append(output) spend_bundle = wallet_a.generate_signed_transaction( 100, receiver_puzzlehash, blocks[1].get_coinbase(), condition_dic=conditions_dict, ) assert spend_bundle is not None new_transaction = fnp.NewTransaction( spend_bundle.get_hash(), uint64(100), uint64(100) ) # Not seen msgs = [x async for x in full_node_1.new_transaction(new_transaction)] assert len(msgs) == 1 assert msgs[0].message.data == fnp.RequestTransaction(spend_bundle.get_hash()) respond_transaction_2 = fnp.RespondTransaction(spend_bundle) [x async for x in full_node_1.respond_transaction(respond_transaction_2)] program = best_solution_program(spend_bundle) aggsig = spend_bundle.aggregated_signature dic_h = {5: (program, aggsig)} blocks_new = bt.get_consecutive_blocks( test_constants, 3, blocks[:-1], 10, transaction_data_at_height=dic_h, ) # Already seen msgs = [x async for x in full_node_1.new_transaction(new_transaction)] assert len(msgs) == 0 # Farm one block for block in blocks_new: [_ async for _ in full_node_1.respond_block(fnp.RespondBlock(block))] spend_bundles = [] total_fee = 0 # Fill mempool for puzzle_hash in puzzle_hashes: coin_record = ( await full_node_1.coin_store.get_coin_records_by_puzzle_hash( puzzle_hash, blocks_new[-3].header ) )[0] receiver_puzzlehash = wallet_receiver.get_new_puzzlehash() fee = random.randint(2, 499) spend_bundle = wallet_receiver.generate_signed_transaction( 500, receiver_puzzlehash, coin_record.coin, fee=fee ) respond_transaction = fnp.RespondTransaction(spend_bundle) res = [ x async for x in full_node_1.respond_transaction(respond_transaction) ] # Added to mempool if len(res) > 0: total_fee += fee spend_bundles.append(spend_bundle) # Mempool is full new_transaction = fnp.NewTransaction( token_bytes(32), uint64(1000000), uint64(1) ) msgs = [x async for x in full_node_1.new_transaction(new_transaction)] assert len(msgs) == 0 agg = SpendBundle.aggregate(spend_bundles) program = best_solution_program(agg) aggsig = agg.aggregated_signature dic_h = {8: (program, aggsig)} blocks_new = bt.get_consecutive_blocks( test_constants, 1, blocks_new, 10, transaction_data_at_height=dic_h, fees=uint64(total_fee), ) # Farm one block to clear mempool [_ async for _ in full_node_1.respond_block(fnp.RespondBlock(blocks_new[-1]))]