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_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) 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_invalid_block_age(self, two_nodes): reward_ph = WALLET_A.get_new_puzzlehash() blocks = bt.get_consecutive_blocks( 3, guarantee_transaction_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_block( full_node_protocol.RespondBlock(block)) await time_out_assert(60, node_height_at_least, True, full_node_1, 2) cvp = ConditionVarPair(ConditionOpcode.ASSERT_HEIGHT_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
def get_name_puzzle_conditions(block_program: SerializedProgram, safe_mode: bool): # TODO: allow generator mod to take something (future) # TODO: write more tests block_program_args = SerializedProgram.from_bytes(b"\x80") try: if safe_mode: cost, result = GENERATOR_MOD.run_safe_with_cost( block_program, block_program_args) else: cost, result = GENERATOR_MOD.run_with_cost(block_program, block_program_args) npc_list = [] opcodes = set(item.value for item in ConditionOpcode) for res in result.as_iter(): conditions_list = [] name = std_hash( bytes(res.first().first().as_atom() + res.first().rest().first().as_atom() + res.first().rest().rest().first().as_atom())) puzzle_hash = bytes32(res.first().rest().first().as_atom()) for cond in res.rest().first().as_iter(): if cond.first().as_atom() in opcodes: opcode = ConditionOpcode(cond.first().as_atom()) elif not safe_mode: opcode = ConditionOpcode.UNKNOWN else: return "Unknown operator in safe mode.", None, None if len(list(cond.as_iter())) > 1: cond_var_list = [] for cond_1 in cond.rest().as_iter(): cond_var_list.append(cond_1.as_atom()) cvl = ConditionVarPair(opcode, cond_var_list) else: cvl = ConditionVarPair(opcode, []) conditions_list.append(cvl) conditions_dict = conditions_by_opcode(conditions_list) if conditions_dict is None: conditions_dict = {} npc_list.append( NPC(name, puzzle_hash, [(a, b) for a, b in conditions_dict.items()])) return None, npc_list, uint64(cost) except Exception: tb = traceback.format_exc() return tb, None, 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_transaction_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_block( full_node_protocol.RespondBlock(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.RESERVE_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
def parse_sexp_to_condition( sexp: Program, ) -> Tuple[Optional[Err], Optional[ConditionVarPair]]: """ Takes a ChiaLisp sexp and returns a ConditionVarPair. If it fails, returns an Error """ if not sexp.listp(): return Err.INVALID_CONDITION, None items = sexp.as_python() if not isinstance(items[0], bytes): return Err.INVALID_CONDITION, None try: opcode = ConditionOpcode(items[0]) except ValueError: opcode = ConditionOpcode.UNKNOWN if len(items) == 3: return None, ConditionVarPair(opcode, [items[1], items[2]]) return None, ConditionVarPair(opcode, [items[1]])
def generate_unsigned_transaction( self, amount: uint64, new_puzzle_hash: bytes32, coin: Coin, condition_dic: Dict[ConditionOpcode, List[ConditionVarPair]], fee: int = 0, secret_key: Optional[PrivateKey] = None, ) -> List[CoinSolution]: spends = [] spend_value = coin.amount puzzle_hash = coin.puzzle_hash if secret_key is None: secret_key = self.get_private_key_for_puzzle_hash(puzzle_hash) pubkey = secret_key.get_g1() puzzle = puzzle_for_pk(bytes(pubkey)) if ConditionOpcode.CREATE_COIN not in condition_dic: condition_dic[ConditionOpcode.CREATE_COIN] = [] output = ConditionVarPair( ConditionOpcode.CREATE_COIN, [new_puzzle_hash, int_to_bytes(amount)]) condition_dic[output.opcode].append(output) amount_total = sum( int_from_bytes(cvp.vars[1]) for cvp in condition_dic[ConditionOpcode.CREATE_COIN]) change = spend_value - amount_total - fee if change > 0: change_puzzle_hash = self.get_new_puzzlehash() change_output = ConditionVarPair( ConditionOpcode.CREATE_COIN, [change_puzzle_hash, int_to_bytes(change)]) condition_dic[output.opcode].append(change_output) solution = self.make_solution(condition_dic) else: solution = self.make_solution(condition_dic) spends.append(CoinSolution(coin, puzzle, solution)) return spends
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_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) time_now = uint64(int(time() * 1000)) time_now_plus_3 = time_now + 3000 cvp = ConditionVarPair(ConditionOpcode.ASSERT_SECONDS_NOW_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_invalid_my_parent(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_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) coin = list(blocks[-1].get_included_reward_coins())[0] coin_2 = list(blocks[-2].get_included_reward_coins())[0] cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_PARENT_ID, [coin_2.parent_coin_info]) 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_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_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.RESERVE_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
AggSig has assigned cost of 20vBytes, simple CLVM program is benchmarked against it. """ wallet_tool = WalletTool() benchmark_all_operators() secret_key: PrivateKey = AugSchemeMPL.key_gen(bytes([2] * 32)) puzzles = [] solutions = [] private_keys = [] public_keys = [] for i in range(0, 1000): private_key: PrivateKey = master_sk_to_wallet_sk(secret_key, uint32(i)) public_key = private_key.public_key() solution = wallet_tool.make_solution({ ConditionOpcode.ASSERT_MY_COIN_ID: [ ConditionVarPair(ConditionOpcode.ASSERT_MY_COIN_ID, [token_bytes()]) ] }) puzzle = puzzle_for_pk(bytes(public_key)) puzzles.append(puzzle) solutions.append(solution) private_keys.append(private_key) public_keys.append(public_key) # Run Puzzle 1000 times puzzle_start = time.time() clvm_cost = 0 for i in range(0, 1000): cost_run, sexp = puzzles[i].run_with_cost(solutions[i]) clvm_cost += cost_run
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_transaction_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_block( full_node_protocol.RespondBlock(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.RESERVE_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_transaction_block=True, ) res, err, _ = await full_node_1.blockchain.receive_block( invalid_new_blocks[-1]) assert res == ReceiveBlockResult.INVALID_BLOCK assert err == Err.RESERVE_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_transaction_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_transaction_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_block( full_node_protocol.RespondBlock(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_transaction_block.timestamp + 30) block1_cvp = ConditionVarPair( ConditionOpcode.ASSERT_SECONDS_NOW_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_block=20, guarantee_transaction_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_SECONDS_NOW_EXCEEDS_FAILED valid_new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, transaction_data=block1_spend_bundle, guarantee_transaction_block=True, time_per_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_transaction_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_block( full_node_protocol.RespondBlock(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_HEIGHT_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_transaction_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_HEIGHT_AGE_EXCEEDS_FAILED new_blocks = bt.get_consecutive_blocks( 1, blocks, farmer_reward_puzzle_hash=coinbase_puzzlehash, guarantee_transaction_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_transaction_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_transaction_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_block( full_node_protocol.RespondBlock(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_transaction_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_transaction_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
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_transaction_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_block( full_node_protocol.RespondBlock(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_transaction_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_transaction_block=True, ) res, err, _ = await full_node_1.blockchain.receive_block(new_blocks[-1] ) assert res == ReceiveBlockResult.NEW_PEAK assert err is None