async def test_blocks_load(self, two_nodes): num_blocks = 50 full_node_1, full_node_2, server_1, server_2 = two_nodes blocks = bt.get_consecutive_blocks(num_blocks) peer = await connect_and_get_peer(server_1, server_2) await full_node_1.respond_sub_block( full_node_protocol.RespondSubBlock(blocks[0]), peer) await server_2.start_client( PeerInfo(self_hostname, uint16(server_1._port)), None) async def num_connections(): return len(server_2.get_connections()) await time_out_assert(10, num_connections, 1) start_unf = time.time() for i in range(1, num_blocks): await time_out_assert(5, node_height_at_least, True, full_node_2, i - 2) msg = Message("respond_sub_block", full_node_protocol.RespondSubBlock(blocks[i])) await server_1.send_to_all([msg], NodeType.FULL_NODE) print( f"Time taken to process {num_blocks} is {time.time() - start_unf}") assert time.time() - start_unf < 100
async def test_long_sync_wallet(self, wallet_node, default_1000_blocks): full_node_api, wallet_node, full_node_server, wallet_server = wallet_node for block in default_1000_blocks: await full_node_api.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) await wallet_server.start_client( PeerInfo(self_hostname, uint16(full_node_server._port)), None) # The second node should eventually catch up to the first one, and have the # same tip at height num_blocks - 1. await time_out_assert(600, wallet_height_at_least, True, wallet_node, len(default_1000_blocks) - 1) # Tests a reorg with the wallet num_blocks = 30 blocks_reorg = bt.get_consecutive_blocks( num_blocks, block_list_input=default_1000_blocks[:-5]) for i in range(1, len(blocks_reorg)): await full_node_api.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(blocks_reorg[i])) await time_out_assert(600, wallet_height_at_least, True, wallet_node, len(default_1000_blocks) + num_blocks - 5 - 1)
async def test_validate_blockchain_spend_reorg_since_genesis( self, two_nodes): num_blocks = 10 wallet_a = WALLET_A coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0] receiver_1_puzzlehash = WALLET_A_PUZZLE_HASHES[1] blocks = bt.get_consecutive_blocks( num_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_block=True) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes for block in blocks: await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) spend_block = blocks[-1] 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_1_puzzlehash, spend_coin) new_blocks = bt.get_consecutive_blocks( 1, blocks, seed=b"", farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=spend_bundle) await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(new_blocks[-1])) # Spends a coin in a genesis reorg, that was already spent new_blocks = bt.get_consecutive_blocks( 12, [], seed=b"reorg since genesis", farmer_reward_puzzle_hash=coinbase_puzzlehash, ) for block in new_blocks: await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) new_blocks = bt.get_consecutive_blocks( 1, new_blocks, seed=b"reorg since genesis", farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=spend_bundle, ) await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(new_blocks[-1]))
async def test_wallet_reorg_get_coinbase(self, wallet_node_simulator, default_400_blocks): 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 = wallet_node.wallet_state_manager 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) # Insert 400 blocks for block in default_400_blocks: await full_node_api.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) # Reorg blocks that carry reward num_blocks_reorg = 30 blocks_reorg = bt.get_consecutive_blocks( num_blocks_reorg, block_list_input=default_400_blocks[:-5]) for block in blocks_reorg[:-5]: await full_node_api.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) async def get_tx_count(wallet_id): txs = await wsm.get_all_transactions(wallet_id) return len(txs) await time_out_assert(10, get_tx_count, 0, 1) num_blocks_reorg_1 = 40 blocks_reorg_1 = bt.get_consecutive_blocks( 1, pool_reward_puzzle_hash=ph, farmer_reward_puzzle_hash=ph, block_list_input=blocks_reorg[:-30]) blocks_reorg_2 = bt.get_consecutive_blocks( num_blocks_reorg_1, block_list_input=blocks_reorg_1) for block in blocks_reorg_2[-41:]: await full_node_api.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) # Confirm we have the funds funds = calculate_pool_reward(uint32( len(blocks_reorg_1))) + calculate_base_farmer_reward( uint32(len(blocks_reorg_1))) await time_out_assert(10, get_tx_count, 2, 1) await time_out_assert(10, wallet.get_confirmed_balance, funds)
async def test_validate_blockchain_spend_reorg_cb_coin(self, two_nodes): num_blocks = 15 wallet_a = WALLET_A coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0] receiver_1_puzzlehash = WALLET_A_PUZZLE_HASHES[1] blocks = bt.get_consecutive_blocks( num_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes for block in blocks: await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) # Spends a coinbase created in reorg new_blocks = bt.get_consecutive_blocks( 5, blocks[:6], seed=b"reorg cb coin", farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_block=True, ) for block in new_blocks: await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) spend_block = new_blocks[-1] 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_1_puzzlehash, spend_coin) new_blocks = bt.get_consecutive_blocks( 1, new_blocks, seed=b"reorg cb coin", farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=spend_bundle, guarantee_block=True, ) await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(new_blocks[-1])) coins_created = [] for coin in new_blocks[-1].additions(): if coin.puzzle_hash == receiver_1_puzzlehash: coins_created.append(coin) assert len(coins_created) == 1
async def test_wallet_reorg_sync(self, wallet_node_simulator, default_400_blocks): 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() 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_sub_block( full_node_protocol.RespondSubBlock(block)) # Farm few more with reward for i in range(0, num_blocks): await full_node_api.farm_new_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_sub_block( full_node_protocol.RespondSubBlock(block)) await time_out_assert(5, get_tx_count, 0, 1) await time_out_assert(5, wallet.get_confirmed_balance, 0)
async def test_assert_fee_condition_wrong_fee(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( 3, 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) cvp = ConditionVarPair(ConditionOpcode.ASSERT_FEE, [int_to_bytes(10)]) dic = {cvp.opcode: [cvp]} spend_bundle1 = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0], dic, uint64(9)) 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): reward_ph = WALLET_A.get_new_puzzlehash() blocks = bt.get_consecutive_blocks( 3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) full_node_1, full_node_2, server_1, server_2 = two_nodes 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_2, 2) spend_bundle = generate_test_spend_bundle(list(blocks[-1].get_included_reward_coins())[0]) assert spend_bundle is not None tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle) await full_node_1.respond_transaction(tx, peer) await time_out_assert( 10, full_node_1.full_node.mempool_manager.get_spendbundle, spend_bundle, spend_bundle.name(), )
async def test_agg_sig_condition(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( 3, block_list_input=blocks, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) 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) # this code has been changed to use generate_test_spend_bundle # not quite sure why all the gymnastics are being performed coin = list(blocks[-1].get_included_reward_coins())[0] spend_bundle_0 = generate_test_spend_bundle(coin) unsigned: List[CoinSolution] = spend_bundle_0.coin_solutions assert len(unsigned) == 1 coin_solution = unsigned[0] err, con, cost = conditions_for_solution(coin_solution.solution) assert con is not None
async def test_invalid_block_age(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() blocks = bt.get_consecutive_blocks( 3, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) full_node_1, full_node_2, server_1, server_2 = two_nodes 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, 2) cvp = ConditionVarPair(ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS, [uint64(5).to_bytes(4, "big")]) dic = {cvp.opcode: [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 None
async def test_stealing_fee(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( 5, block_list_input=blocks, guarantee_block=True, farmer_reward_puzzle_hash=reward_ph, pool_reward_puzzle_hash=reward_ph, ) full_node_1, full_node_2, server_1, server_2 = two_nodes 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_height + 5) receiver_puzzlehash = BURN_PUZZLE_HASH cvp = ConditionVarPair(ConditionOpcode.ASSERT_FEE, [int_to_bytes(10)]) dic = {cvp.opcode: [cvp]} fee = 9 coin_1 = list(blocks[-2].get_included_reward_coins())[0] coin_2 = None for coin in list(blocks[-1].get_included_reward_coins()): if coin.amount == coin_1.amount: coin_2 = coin spend_bundle1 = generate_test_spend_bundle(coin_1, dic, uint64(fee)) steal_fee_spendbundle = WALLET_A.generate_signed_transaction( coin_1.amount + fee - 4, receiver_puzzlehash, coin_2) 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) 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_close_height_but_big_reorg(self, three_nodes): blocks_a = bt.get_consecutive_blocks(50) blocks_b = bt.get_consecutive_blocks(51, seed=b"B") blocks_c = bt.get_consecutive_blocks(90, seed=b"C") full_node_1, full_node_2, full_node_3 = three_nodes server_1 = full_node_1.full_node.server server_2 = full_node_2.full_node.server server_3 = full_node_3.full_node.server for block in blocks_a: await full_node_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) for block in blocks_b: await full_node_2.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) for block in blocks_c: await full_node_3.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) await server_2.start_client( PeerInfo(self_hostname, uint16(server_1._port)), on_connect=full_node_2.full_node.on_connect, ) await time_out_assert(60, node_height_exactly, True, full_node_1, 50) await time_out_assert(60, node_height_exactly, True, full_node_2, 50) await time_out_assert(60, node_height_exactly, True, full_node_3, 89) await server_3.start_client( PeerInfo(self_hostname, uint16(server_1._port)), on_connect=full_node_3.full_node.on_connect, ) await server_3.start_client( PeerInfo(self_hostname, uint16(server_2._port)), on_connect=full_node_3.full_node.on_connect, ) await time_out_assert(60, node_height_exactly, True, full_node_1, 89) await time_out_assert(60, node_height_exactly, True, full_node_2, 89) await time_out_assert(60, node_height_exactly, True, full_node_3, 89)
async def test_invalid_announcement_consumed_two(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 if len(blocks) > 0 else -1 blocks = bt.get_consecutive_blocks( 3, 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_height + 3) coin_1 = list(blocks[-2].get_included_reward_coins())[0] coin_2 = list(blocks[-1].get_included_reward_coins())[0] announce = Announcement(coin_1.name(), bytes("test", "utf-8")) cvp = ConditionVarPair(ConditionOpcode.ASSERT_ANNOUNCEMENT, [announce.name()]) dic = {cvp.opcode: [cvp]} cvp2 = ConditionVarPair( ConditionOpcode.CREATE_ANNOUNCEMENT, [bytes("test", "utf-8")], ) dic2 = {cvp.opcode: [cvp2]} spend_bundle1 = generate_test_spend_bundle(coin_1, dic) spend_bundle2 = generate_test_spend_bundle(coin_2, dic2) bundle = SpendBundle.aggregate([spend_bundle1, spend_bundle2]) 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( bundle.name()) assert mempool_bundle is None
async def test_backtrack_sync_2(self, two_nodes): blocks = bt.get_consecutive_blocks(1, skip_slots=3) blocks = bt.get_consecutive_blocks(8, blocks, skip_slots=0) full_node_1, full_node_2, server_1, server_2 = two_nodes # 3 blocks to node_1 in different sub slots for block in blocks: await full_node_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) await server_2.start_client( PeerInfo(self_hostname, uint16(server_1._port)), on_connect=full_node_2.full_node.on_connect, ) await time_out_assert(60, node_height_exactly, True, full_node_2, 8)
async def test_batch_sync(self, two_nodes): # Must be below "sync_block_behind_threshold" in the config num_blocks = 20 num_blocks_2 = 9 blocks = bt.get_consecutive_blocks(num_blocks) blocks_2 = bt.get_consecutive_blocks(num_blocks_2, seed=b"123") full_node_1, full_node_2, server_1, server_2 = two_nodes # 12 blocks to node_1 for block in blocks: await full_node_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) # 9 different blocks to node_2 for block in blocks_2: await full_node_2.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) await server_2.start_client( PeerInfo(self_hostname, uint16(server_1._port)), on_connect=full_node_2.full_node.on_connect, ) await time_out_assert(60, node_height_exactly, True, full_node_2, num_blocks - 1)
async def test_assert_time_exceeds_both_cases(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 if len(blocks) > 0 else -1 blocks = bt.get_consecutive_blocks( 3, 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_height + 3) time_now = uint64(int(time() * 1000)) time_now_plus_3 = time_now + 3000 cvp = ConditionVarPair(ConditionOpcode.ASSERT_TIME_EXCEEDS, [time_now_plus_3.to_bytes(8, "big")]) dic = {cvp.opcode: [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) # Sleep so that 3 sec passes await asyncio.sleep(3) tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle1) await full_node_1.respond_transaction(tx2, peer) sb1 = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle1.name()) assert sb1 is spend_bundle1
async def test_sync_from_zero(self, two_nodes, default_400_blocks): # Must be larger than "sync_block_behind_threshold" in the config num_blocks = len(default_400_blocks) blocks = default_400_blocks full_node_1, full_node_2, server_1, server_2 = two_nodes for block in blocks: await full_node_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) await server_2.start_client( PeerInfo(self_hostname, uint16(server_1._port)), None) # The second node should eventually catch up to the first one, and have the # same tip at height num_blocks - 1 (or at least num_blocks - 3, in case we sync to below the tip) await time_out_assert(60, node_height_at_least, True, full_node_2, num_blocks - 1)
async def test_double_spend_with_higher_fee(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_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_height + 3) spend_bundle1 = generate_test_spend_bundle( list(blocks[-1].get_included_reward_coins())[0]) 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) spend_bundle2 = generate_test_spend_bundle(list( blocks[-1].get_included_reward_coins())[0], fee=uint64(1)) assert spend_bundle2 is not None tx2: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle2) await full_node_1.respond_transaction(tx2, peer) sb1 = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle1.name()) sb2 = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle2.name()) assert sb1 is None assert sb2 == spend_bundle2
async def test_validate_blockchain_duplicate_output(self, two_nodes): num_blocks = 3 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_block=True) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes full_node_1 = full_node_api_1.full_node for block in blocks: await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) 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) spend_bundle_double = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin) block_spendbundle = SpendBundle.aggregate( [spend_bundle, spend_bundle_double]) new_blocks = bt.get_consecutive_blocks( 1, block_list_input=blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=block_spendbundle, guarantee_block=True, ) next_block = new_blocks[-1] res, err, _ = await full_node_1.blockchain.receive_block(next_block) assert res == ReceiveBlockResult.INVALID_BLOCK assert err == Err.DUPLICATE_OUTPUT
async def test_double_spend_same_bundle(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_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_height + 3) coin = list(blocks[-1].get_included_reward_coins())[0] spend_bundle1 = generate_test_spend_bundle(coin) assert spend_bundle1 is not None spend_bundle2 = generate_test_spend_bundle( coin, new_puzzle_hash=BURN_PUZZLE_HASH_2, ) assert spend_bundle2 is not None spend_bundle_combined = SpendBundle.aggregate( [spend_bundle1, spend_bundle2]) tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction( spend_bundle_combined) await full_node_1.respond_transaction(tx, peer) sb = full_node_1.full_node.mempool_manager.get_spendbundle( spend_bundle_combined.name()) assert sb is None
async def test_invalid_my_id(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 if len(blocks) > 0 else -1 blocks = bt.get_consecutive_blocks( 3, 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_height + 3) coin = list(blocks[-1].get_included_reward_coins())[0] coin_2 = list(blocks[-2].get_included_reward_coins())[0] cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID, [coin_2.name()]) dic = {cvp.opcode: [cvp]} spend_bundle1 = generate_test_spend_bundle(coin, 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 None
async def test_correct_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 + 4) 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) spend_bundle2 = generate_test_spend_bundle(coin_2) bundle = SpendBundle.aggregate([spend_bundle1, spend_bundle2]) tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(bundle) await full_node_1.respond_transaction(tx1, peer) mempool_bundle = full_node_1.full_node.mempool_manager.get_spendbundle(bundle.name()) assert mempool_bundle is bundle
async def test1(self, two_nodes): num_blocks = 5 test_rpc_port = uint16(21522) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes def stop_node_cb(): full_node_api_1._close() server_1.close_all() full_node_rpc_api = FullNodeRpcApi(full_node_api_1.full_node) config = bt.config hostname = config["self_hostname"] daemon_port = config["daemon_port"] rpc_cleanup = await start_rpc_server( full_node_rpc_api, hostname, daemon_port, test_rpc_port, stop_node_cb, bt.root_path, config, connect_to_daemon=False, ) try: client = await FullNodeRpcClient.create(self_hostname, test_rpc_port, bt.root_path, config) state = await client.get_blockchain_state() assert state["peak"] is None assert not state["sync"]["sync_mode"] assert state["difficulty"] > 0 assert state["sub_slot_iters"] > 0 blocks = bt.get_consecutive_blocks(num_blocks) blocks = bt.get_consecutive_blocks(1, block_list_input=blocks, guarantee_block=True) assert len(await client.get_unfinished_sub_block_headers()) == 0 assert len((await client.get_sub_block_records(0, 100))) == 0 for block in blocks: if is_overflow_sub_block( test_constants, block.reward_chain_sub_block.signage_point_index): finished_ss = block.finished_sub_slots[:-1] else: finished_ss = block.finished_sub_slots unf = UnfinishedBlock( finished_ss, block.reward_chain_sub_block.get_unfinished(), block.challenge_chain_sp_proof, block.reward_chain_sp_proof, block.foliage_sub_block, block.foliage_block, block.transactions_info, block.transactions_generator, ) await full_node_api_1.full_node.respond_unfinished_sub_block( full_node_protocol.RespondUnfinishedSubBlock(unf), None) await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block), None) assert len(await client.get_unfinished_sub_block_headers()) > 0 assert len(await client.get_all_block(0, 2)) == 2 state = await client.get_blockchain_state() block = await client.get_sub_block(state["peak"].header_hash) assert block == blocks[-1] assert (await client.get_sub_block(bytes([1] * 32))) is None assert (await client.get_sub_block_record_by_sub_height(2) ).header_hash == blocks[2].header_hash assert len( (await client.get_sub_block_records(0, 100))) == num_blocks + 1 assert (await client.get_sub_block_record_by_sub_height(100)) is None ph = list(blocks[-1].get_included_reward_coins())[0].puzzle_hash coins = await client.get_unspent_coins(ph) assert len(coins) >= 1 additions, removals = await client.get_additions_and_removals( blocks[-1].header_hash) assert len(additions) >= 2 and len(removals) == 0 assert len(await client.get_connections()) == 0 await client.open_connection(self_hostname, server_2._port) async def num_connections(): return len(await client.get_connections()) await time_out_assert(10, num_connections, 1) connections = await client.get_connections() await client.close_connection(connections[0]["node_id"]) await time_out_assert(10, num_connections, 0) finally: # Checks that the RPC manages to stop the node client.close() await client.await_closed() await rpc_cleanup()
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_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_sub_block( full_node_protocol.RespondSubBlock(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_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_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_sub_block( full_node_protocol.RespondSubBlock(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 = 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_block=True, ) next_block = new_blocks[-1] await full_node_1.respond_sub_block( full_node_protocol.RespondSubBlock(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_assert_my_coin_id(self, two_nodes): num_blocks = 10 wallet_a = WALLET_A coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0] receiver_puzzlehash = BURN_PUZZLE_HASH # Farm blocks blocks = bt.get_consecutive_blocks( num_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_block=True) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes full_node_1 = full_node_api_1.full_node for block in blocks: await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) # Coinbase that gets spent spend_block = blocks[2] bad_block = blocks[3] spend_coin = None bad_spend_coin = None for coin in list(spend_block.get_included_reward_coins()): if coin.puzzle_hash == coinbase_puzzlehash: spend_coin = coin for coin in list(bad_block.get_included_reward_coins()): if coin.puzzle_hash == coinbase_puzzlehash: bad_spend_coin = coin valid_cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID, [spend_coin.name()]) valid_dic = {valid_cvp.opcode: [valid_cvp]} bad_cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID, [bad_spend_coin.name()]) bad_dic = {bad_cvp.opcode: [bad_cvp]} bad_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin, bad_dic) valid_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin, valid_dic) assert bad_spend_bundle is not None assert valid_spend_bundle is not None # Invalid block bundle # Create another block that includes our transaction invalid_new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=bad_spend_bundle, guarantee_block=True, ) # Try to validate that block res, err, _ = await full_node_1.blockchain.receive_block( invalid_new_blocks[-1]) assert res == ReceiveBlockResult.INVALID_BLOCK assert err == Err.ASSERT_MY_COIN_ID_FAILED # Valid block bundle # Create another block that includes our transaction new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=valid_spend_bundle, guarantee_block=True, ) res, err, _ = await full_node_1.blockchain.receive_block(new_blocks[-1] ) assert res == ReceiveBlockResult.NEW_PEAK assert err is None
async def test_assert_fee_condition(self, two_nodes): num_blocks = 10 wallet_a = WALLET_A coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0] receiver_puzzlehash = BURN_PUZZLE_HASH # Farm blocks blocks = bt.get_consecutive_blocks( num_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_block=True) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes full_node_1 = full_node_api_1.full_node for block in blocks: await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) # Coinbase that gets spent block1 = blocks[2] spend_coin_block_1 = None for coin in list(block1.get_included_reward_coins()): if coin.puzzle_hash == coinbase_puzzlehash: spend_coin_block_1 = coin # This condition requires fee to be 10 mojo cvp_fee = ConditionVarPair(ConditionOpcode.ASSERT_FEE, [int_to_bytes(10)]) # This spend bundle has 9 mojo as fee block1_dic_bad = {cvp_fee.opcode: [cvp_fee]} block1_dic_good = {cvp_fee.opcode: [cvp_fee]} block1_spend_bundle_bad = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin_block_1, block1_dic_bad, fee=9) block1_spend_bundle_good = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin_block_1, block1_dic_good, fee=10) log.warning(block1_spend_bundle_good.additions()) log.warning(f"Spend bundle fees: {block1_spend_bundle_good.fees()}") invalid_new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=block1_spend_bundle_bad, guarantee_block=True, ) res, err, _ = await full_node_1.blockchain.receive_block( invalid_new_blocks[-1]) assert res == ReceiveBlockResult.INVALID_BLOCK assert err == Err.ASSERT_FEE_CONDITION_FAILED valid_new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=block1_spend_bundle_good, guarantee_block=True, ) res, err, _ = await full_node_1.blockchain.receive_block( valid_new_blocks[-1]) assert err is None assert res == ReceiveBlockResult.NEW_PEAK
async def test_assert_time_exceeds(self, two_nodes): num_blocks = 10 wallet_a = WALLET_A coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0] receiver_puzzlehash = BURN_PUZZLE_HASH # Farm blocks blocks = bt.get_consecutive_blocks( num_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_block=True) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes full_node_1 = full_node_api_1.full_node for block in blocks: await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) # Coinbase that gets spent block1 = blocks[2] spend_coin_block_1 = None for coin in list(block1.get_included_reward_coins()): if coin.puzzle_hash == coinbase_puzzlehash: spend_coin_block_1 = coin # This condition requires block1 coinbase to be spent after 30 seconds from now current_time_plus3 = uint64(blocks[-1].foliage_block.timestamp + 30) block1_cvp = ConditionVarPair(ConditionOpcode.ASSERT_TIME_EXCEEDS, [int_to_bytes(current_time_plus3)]) block1_dic = {block1_cvp.opcode: [block1_cvp]} block1_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin_block_1, block1_dic) # program that will be sent to early assert block1_spend_bundle is not None invalid_new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=block1_spend_bundle, time_per_sub_block=20, guarantee_block=True, ) # Try to validate that block before 3 sec res, err, _ = await full_node_1.blockchain.receive_block( invalid_new_blocks[-1]) assert res == ReceiveBlockResult.INVALID_BLOCK assert err == Err.ASSERT_TIME_EXCEEDS_FAILED valid_new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=block1_spend_bundle, guarantee_block=True, time_per_sub_block=31, ) res, err, _ = await full_node_1.blockchain.receive_block( valid_new_blocks[-1]) assert err is None assert res == ReceiveBlockResult.NEW_PEAK
async def test_assert_block_age_exceeds(self, two_nodes): num_blocks = 11 wallet_a = WALLET_A coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0] receiver_puzzlehash = BURN_PUZZLE_HASH # Farm blocks blocks = bt.get_consecutive_blocks( num_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_block=True) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes full_node_1 = full_node_api_1.full_node for block in blocks: await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) # Coinbase that gets spent block1 = blocks[2] spend_coin_block_1 = None for coin in list(block1.get_included_reward_coins()): if coin.puzzle_hash == coinbase_puzzlehash: spend_coin_block_1 = coin # This condition requires block1 coinbase to be spent after index 11 # This condition requires block1 coinbase to be spent more than 10 block after it was farmed # block index has to be greater than (2 + 9 = 11) block1_cvp = ConditionVarPair(ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS, [int_to_bytes(9)]) block1_dic = {block1_cvp.opcode: [block1_cvp]} block1_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin_block_1, block1_dic) # program that will be sent too early assert block1_spend_bundle is not None invalid_new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=block1_spend_bundle, guarantee_block=True, ) # Try to validate that block at index 11 res, err, _ = await full_node_1.blockchain.receive_block( invalid_new_blocks[-1]) assert res == ReceiveBlockResult.INVALID_BLOCK assert err == Err.ASSERT_BLOCK_AGE_EXCEEDS_FAILED new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_block=True, ) res, _, _ = await full_node_1.blockchain.receive_block(new_blocks[-1]) assert res == ReceiveBlockResult.NEW_PEAK # At index 12, it can be spent new_blocks = bt.get_consecutive_blocks( 1, new_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=block1_spend_bundle, guarantee_block=True, ) res, err, _ = await full_node_1.blockchain.receive_block(new_blocks[-1] ) assert err is None assert res == ReceiveBlockResult.NEW_PEAK
async def test_assert_announcement_consumed(self, two_nodes): num_blocks = 10 wallet_a = WALLET_A coinbase_puzzlehash = WALLET_A_PUZZLE_HASHES[0] receiver_puzzlehash = BURN_PUZZLE_HASH # Farm blocks blocks = bt.get_consecutive_blocks( num_blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_block=True) full_node_api_1, full_node_api_2, server_1, server_2 = two_nodes full_node_1 = full_node_api_1.full_node for block in blocks: await full_node_api_1.full_node.respond_sub_block( full_node_protocol.RespondSubBlock(block)) # Coinbase that gets spent block1 = blocks[2] block2 = blocks[3] spend_coin_block_1 = None spend_coin_block_2 = None for coin in list(block1.get_included_reward_coins()): if coin.puzzle_hash == coinbase_puzzlehash: spend_coin_block_1 = coin for coin in list(block2.get_included_reward_coins()): if coin.puzzle_hash == coinbase_puzzlehash: spend_coin_block_2 = coin # This condition requires block2 coinbase to be spent block1_cvp = ConditionVarPair( ConditionOpcode.ASSERT_ANNOUNCEMENT, [ Announcement(spend_coin_block_2.name(), bytes("test", "utf-8")).name() ], ) block1_dic = {block1_cvp.opcode: [block1_cvp]} block1_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin_block_1, block1_dic) # This condition requires block1 coinbase to be spent block2_cvp = ConditionVarPair( ConditionOpcode.CREATE_ANNOUNCEMENT, [bytes("test", "utf-8")], ) block2_dic = {block2_cvp.opcode: [block2_cvp]} block2_spend_bundle = wallet_a.generate_signed_transaction( 1000, receiver_puzzlehash, spend_coin_block_2, block2_dic) # Invalid block bundle assert block1_spend_bundle is not None # Create another block that includes our transaction invalid_new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=block1_spend_bundle, guarantee_block=True, ) # Try to validate that block res, err, _ = await full_node_1.blockchain.receive_block( invalid_new_blocks[-1]) assert res == ReceiveBlockResult.INVALID_BLOCK assert err == Err.ASSERT_ANNOUNCE_CONSUMED_FAILED # bundle_together contains both transactions bundle_together = SpendBundle.aggregate( [block1_spend_bundle, block2_spend_bundle]) # Create another block that includes our transaction new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=bundle_together, guarantee_block=True, ) # Try to validate newly created block res, err, _ = await full_node_1.blockchain.receive_block(new_blocks[-1] ) assert res == ReceiveBlockResult.NEW_PEAK assert err is None