async def get_puzzle_and_solution(self, request: Dict) -> Optional[Dict]: coin_name: bytes32 = hexstr_to_bytes(request["coin_id"]) height = request["height"] coin_record = await self.service.coin_store.get_coin_record(coin_name) if coin_record is None or not coin_record.spent or coin_record.spent_block_index != height: raise ValueError( f"Invalid height {height}. coin record {coin_record}") header_hash = self.service.blockchain.height_to_hash(height) block: Optional[ FullBlock] = await self.service.block_store.get_full_block( header_hash) if block is None or block.transactions_generator is None: raise ValueError("Invalid block or block generator") block_generator: Optional[ BlockGenerator] = await self.service.blockchain.get_block_generator( block) assert block_generator is not None error, puzzle, solution = get_puzzle_and_solution_for_coin( block_generator, coin_name, self.service.constants.MAX_BLOCK_COST_CLVM) if error is not None: raise ValueError(f"Error: {error}") puzzle_ser: SerializedProgram = SerializedProgram.from_program( Program.to(puzzle)) solution_ser: SerializedProgram = SerializedProgram.from_program( Program.to(solution)) return { "coin_solution": CoinSpend(coin_record.coin, puzzle_ser, solution_ser) }
async def test_strict_mode(self, rust_checker: bool): wallet_tool = bt.get_pool_wallet_tool() ph = wallet_tool.get_new_puzzlehash() num_blocks = 3 blocks = bt.get_consecutive_blocks(num_blocks, [], guarantee_transaction_block=True, pool_reward_puzzle_hash=ph, farmer_reward_puzzle_hash=ph) coinbase = None for coin in blocks[2].get_included_reward_coins(): if coin.puzzle_hash == ph: coinbase = coin break assert coinbase is not None spend_bundle = wallet_tool.generate_signed_transaction( coinbase.amount, BURN_PUZZLE_HASH, coinbase, ) assert spend_bundle is not None pk = bytes.fromhex( "88bc9360319e7c54ab42e19e974288a2d7a817976f7633f4b43f36ce72074e59c4ab8ddac362202f3e366f0aebbb6280" ) puzzle = p2_delegated_puzzle_or_hidden_puzzle.puzzle_for_pk(pk) disassembly = binutils.disassemble(puzzle) program = SerializedProgram.from_bytes( binutils.assemble( f"(q ((0x3d2331635a58c0d49912bc1427d7db51afe3f20a7b4bcaffa17ee250dcbcbfaa {disassembly} 300" f" (() (q . ((65 '00000000000000000000000000000000' 0x0cbba106e000))) ()))))" ).as_bin()) generator = BlockGenerator(program, []) npc_result: NPCResult = get_name_puzzle_conditions( generator, test_constants.MAX_BLOCK_COST_CLVM, cost_per_byte=test_constants.COST_PER_BYTE, safe_mode=True, rust_checker=rust_checker, ) assert npc_result.error is not None npc_result = get_name_puzzle_conditions( generator, test_constants.MAX_BLOCK_COST_CLVM, cost_per_byte=test_constants.COST_PER_BYTE, safe_mode=False, rust_checker=rust_checker, ) assert npc_result.error is None coin_name = npc_result.npc_list[0].coin_name error, puzzle, solution = get_puzzle_and_solution_for_coin( generator, coin_name, test_constants.MAX_BLOCK_COST_CLVM) assert error is None
def test_get_removals_for_single_coin(self): sb: SpendBundle = make_spend_bundle(1) start, end = match_standard_transaction_at_any_index( original_generator) ca = CompressorArg(uint32(0), SerializedProgram.from_bytes(original_generator), start, end) c = compressed_spend_bundle_solution(ca, sb) removal = sb.coin_spends[0].coin.name() error, puzzle, solution = get_puzzle_and_solution_for_coin( c, removal, INFINITE_COST) assert error is None assert bytes(puzzle) == bytes(sb.coin_spends[0].puzzle_reveal) assert bytes(solution) == bytes(sb.coin_spends[0].solution) # Test non compressed generator as well s = simple_solution_generator(sb) error, puzzle, solution = get_puzzle_and_solution_for_coin( s, removal, INFINITE_COST) assert error is None assert bytes(puzzle) == bytes(sb.coin_spends[0].puzzle_reveal) assert bytes(solution) == bytes(sb.coin_spends[0].solution)
async def get_puzzle_and_solution(self, coin_id: bytes32, height: uint32) -> Optional[CoinSpend]: generator = list(filter(lambda block: block.height == height, self.service.blocks))[0].transactions_generator coin_record = await self.service.mempool_manager.coin_store.get_coin_record(coin_id) error, puzzle, solution = get_puzzle_and_solution_for_coin( generator, coin_id, self.service.defaults.MAX_BLOCK_COST_CLVM, ) if error: return None else: puzzle_ser: SerializedProgram = SerializedProgram.from_program(Program.to(puzzle)) solution_ser: SerializedProgram = SerializedProgram.from_program(Program.to(solution)) return CoinSpend(coin_record.coin, puzzle_ser, solution_ser)
async def test_basics(self, rust_checker: bool): wallet_tool = bt.get_pool_wallet_tool() ph = wallet_tool.get_new_puzzlehash() num_blocks = 3 blocks = bt.get_consecutive_blocks(num_blocks, [], guarantee_transaction_block=True, pool_reward_puzzle_hash=ph, farmer_reward_puzzle_hash=ph) coinbase = None for coin in blocks[2].get_included_reward_coins(): if coin.puzzle_hash == ph and coin.amount == 250000000000: coinbase = coin break assert coinbase is not None spend_bundle = wallet_tool.generate_signed_transaction( coinbase.amount, BURN_PUZZLE_HASH, coinbase, ) assert spend_bundle is not None program: BlockGenerator = simple_solution_generator(spend_bundle) npc_result: NPCResult = get_name_puzzle_conditions( program, test_constants.MAX_BLOCK_COST_CLVM, cost_per_byte=test_constants.COST_PER_BYTE, safe_mode=False, rust_checker=rust_checker, ) cost = calculate_cost_of_program(program.program, npc_result, test_constants.COST_PER_BYTE) assert npc_result.error is None assert len(bytes(program.program)) == 433 coin_name = npc_result.npc_list[0].coin_name error, puzzle, solution = get_puzzle_and_solution_for_coin( program, coin_name, test_constants.MAX_BLOCK_COST_CLVM) assert error is None assert npc_result.clvm_cost == 404560 # Create condition + agg_sig_condition + length + cpu_cost assert (cost == ConditionCost.CREATE_COIN.value + ConditionCost.AGG_SIG.value + len(bytes(program.program)) * test_constants.COST_PER_BYTE + 404560 # clvm_cost )
async def get_puzzle_and_solution(self, request: Dict) -> Optional[Dict]: coin_name: bytes32 = bytes32.from_hexstr(request["coin_id"]) height = request["height"] coin_record = await self.service.coin_store.get_coin_record(coin_name) if coin_record is None or not coin_record.spent or coin_record.spent_block_index != height: raise ValueError( f"Invalid height {height}. coin record {coin_record}") header_hash = self.service.blockchain.height_to_hash(height) # TODO: address hint error and remove ignore # error: Argument 1 to "get_full_block" of "BlockStore" has incompatible type "Optional[bytes32]"; # expected "bytes32" [arg-type] block: Optional[ FullBlock] = await self.service.block_store.get_full_block( header_hash) # type: ignore[arg-type] # noqa: E501 if block is None or block.transactions_generator is None: raise ValueError("Invalid block or block generator") block_generator: Optional[ BlockGenerator] = await self.service.blockchain.get_block_generator( block) assert block_generator is not None error, puzzle, solution = get_puzzle_and_solution_for_coin( block_generator, coin_name, self.service.constants.MAX_BLOCK_COST_CLVM) if error is not None: raise ValueError(f"Error: {error}") puzzle_ser: SerializedProgram = SerializedProgram.from_program( Program.to(puzzle)) solution_ser: SerializedProgram = SerializedProgram.from_program( Program.to(solution)) return { "coin_solution": CoinSpend(coin_record.coin, puzzle_ser, solution_ser) }
async def test_basics(self): wallet_tool = bt.get_pool_wallet_tool() ph = wallet_tool.get_new_puzzlehash() num_blocks = 3 blocks = bt.get_consecutive_blocks(num_blocks, [], guarantee_transaction_block=True, pool_reward_puzzle_hash=ph, farmer_reward_puzzle_hash=ph) coinbase = None for coin in blocks[2].get_included_reward_coins(): if coin.puzzle_hash == ph: coinbase = coin break assert coinbase is not None spend_bundle = wallet_tool.generate_signed_transaction( coinbase.amount, BURN_PUZZLE_HASH, coinbase, ) assert spend_bundle is not None program = best_solution_program(spend_bundle) result: CostResult = calculate_cost_of_program( program, test_constants.COST_PER_BYTE) clvm_cost = result.cost error, npc_list, cost = get_name_puzzle_conditions(program, False) assert error is None coin_name = npc_list[0].coin_name error, puzzle, solution = get_puzzle_and_solution_for_coin( program, coin_name) assert error is None # Create condition + agg_sig_condition + length + cpu_cost assert (clvm_cost == ConditionCost.CREATE_COIN.value + ConditionCost.AGG_SIG.value + len(bytes(program)) * test_constants.COST_PER_BYTE + cost)