From 431ab0bf70e288655150768c5abba56c8e677424 Mon Sep 17 00:00:00 2001 From: Richard Kiss Date: Tue, 15 Sep 2020 17:11:37 -0700 Subject: [PATCH] Use `Program` instead of `src.util.clvm`. --- src/full_node/mempool_check_conditions.py | 8 +++--- src/types/program.py | 25 ++++++++++++++----- src/util/condition_tools.py | 8 +++--- src/wallet/cc_wallet/cc_utils.py | 2 +- src/wallet/cc_wallet/cc_wallet.py | 7 +++--- src/wallet/cc_wallet/debug_spend_bundle.py | 6 ++--- .../puzzles/genesis_by_coin_id_with_0.py | 15 ++--------- .../puzzles/genesis_by_puzzle_hash_with_0.py | 16 ++---------- tests/util/benchmark_cost.py | 5 ++-- 9 files changed, 39 insertions(+), 53 deletions(-) diff --git a/src/full_node/mempool_check_conditions.py b/src/full_node/mempool_check_conditions.py index 66f6d4b02f57..c6a28d78d002 100644 --- a/src/full_node/mempool_check_conditions.py +++ b/src/full_node/mempool_check_conditions.py @@ -7,7 +7,7 @@ from src.types.coin_record import CoinRecord from src.types.name_puzzle_condition import NPC from src.full_node.mempool import Mempool from src.types.sized_bytes import bytes32 -from src.util.clvm import EvalError, int_from_bytes, run_program +from src.util.clvm import int_from_bytes from src.util.condition_tools import ConditionOpcode, conditions_dict_for_solution from src.util.errors import Err import time @@ -96,9 +96,9 @@ def get_name_puzzle_conditions( """ cost_sum = 0 try: - cost_run, sexp = run_program(block_program, []) + cost_run, sexp = block_program.run_with_cost([]) cost_sum += cost_run - except EvalError: + except Program.EvalError: return Err.INVALID_COIN_SOLUTION, [], uint64(0) npc_list = [] @@ -121,7 +121,7 @@ def get_name_puzzle_conditions( cost_sum += cost_run if error: return error, [], uint64(cost_sum) - except EvalError: + except Program.EvalError: return Err.INVALID_COIN_SOLUTION, [], uint64(cost_sum) if conditions_dict is None: conditions_dict = {} diff --git a/src/types/program.py b/src/types/program.py index 5e6d782f97c8..1ac5b9308f8b 100644 --- a/src/types/program.py +++ b/src/types/program.py @@ -1,15 +1,17 @@ import io -from typing import Any, List, Set +from typing import Any, List, Optional, Set, Tuple from src.types.sized_bytes import bytes32 from src.util.clvm import run_program, sexp_from_stream, sexp_to_stream -from clvm import SExp from src.util.hash import std_hash -from clvm_tools.curry import curry +from clvm import SExp +from clvm.EvalError import EvalError +from clvm.casts import int_from_bytes +from clvm_tools.curry import curry, uncurry -class Program(SExp): # type: ignore # noqa +class Program(SExp): """ A thin wrapper around s-expression data intended to be invoked with "eval". """ @@ -61,14 +63,25 @@ class Program(SExp): # type: ignore # noqa """ return self._tree_hash(set(args)) - def run(self, args) -> "Program": + def run_with_cost(self, args) -> Tuple[int, "Program"]: prog_args = Program.to(args) - cost, r = run_program(self, prog_args) + return run_program(self, prog_args) + + def run(self, args) -> "Program": + cost, r = self.run_with_cost(args) return Program.to(r) def curry(self, *args) -> "Program": cost, r = curry(self, list(args)) return Program.to(r) + def uncurry(self) -> Optional[Tuple["Program", "Program"]]: + return uncurry(self) + + def as_int(self) -> int: + return int_from_bytes(self.as_atom()) + def __deepcopy__(self, memo): return type(self).from_bytes(bytes(self)) + + EvalError = EvalError diff --git a/src/util/condition_tools.py b/src/util/condition_tools.py index 3bf07b93a16c..81e217d4f503 100644 --- a/src/util/condition_tools.py +++ b/src/util/condition_tools.py @@ -7,7 +7,7 @@ from src.types.condition_opcodes import ConditionOpcode from src.types.coin import Coin from src.types.program import Program from src.types.sized_bytes import bytes32 -from src.util.clvm import EvalError, int_from_bytes, run_program +from src.util.clvm import int_from_bytes from src.util.ints import uint64 from src.util.errors import Err, ConsensusError @@ -121,15 +121,15 @@ def conditions_dict_for_solution( def conditions_for_solution( - solution_program, run_program=run_program + solution_program, ) -> Tuple[Optional[Err], Optional[List[ConditionVarPair]], uint64]: # get the standard script for a puzzle hash and feed in the solution args = Program.to(solution_program) try: puzzle_sexp = args.first() solution_sexp = args.rest().first() - cost, r = run_program(puzzle_sexp, solution_sexp) + cost, r = puzzle_sexp.run_with_cost(solution_sexp) error, result = parse_sexp_to_conditions(r) return error, result, cost - except EvalError: + except Program.EvalError: return Err.SEXP_ERROR, None, uint64(0) diff --git a/src/wallet/cc_wallet/cc_utils.py b/src/wallet/cc_wallet/cc_utils.py index 86a3de93025e..3479e8d214f9 100644 --- a/src/wallet/cc_wallet/cc_utils.py +++ b/src/wallet/cc_wallet/cc_utils.py @@ -224,7 +224,7 @@ def uncurry_cc(puzzle: Program) -> Optional[Tuple[Program, Program, Program]]: Take a puzzle and return `None` if it's not a `CC_MOD` cc, or a triple of `mod_hash, genesis_coin_checker, inner_puzzle` if it is. """ - r = uncurry(puzzle) + r = puzzle.uncurry() if r is None: return r inner_f, args = r diff --git a/src/wallet/cc_wallet/cc_wallet.py b/src/wallet/cc_wallet/cc_wallet.py index de398ba4999b..aa666488913d 100644 --- a/src/wallet/cc_wallet/cc_wallet.py +++ b/src/wallet/cc_wallet/cc_wallet.py @@ -11,7 +11,6 @@ from src.types.program import Program from src.types.spend_bundle import SpendBundle from src.types.sized_bytes import bytes32 from src.util.byte_types import hexstr_to_bytes -from src.util.clvm import EvalError, run_program from src.util.condition_tools import ( conditions_dict_for_solution, pkm_pairs_for_conditions_dict, @@ -296,9 +295,9 @@ class CCWallet: """ cost_sum = 0 try: - cost_run, sexp = run_program(block_program, []) + cost_run, sexp = block_program.run_with_cost([]) cost_sum += cost_run - except EvalError: + except Program.EvalError: return False for name_solution in sexp.as_iter(): @@ -319,7 +318,7 @@ class CCWallet: cost_sum += cost_run if error: return False - except EvalError: + except Program.EvalError: return False if conditions_dict is None: diff --git a/src/wallet/cc_wallet/debug_spend_bundle.py b/src/wallet/cc_wallet/debug_spend_bundle.py index c13d9b956068..e81b746d3c4a 100644 --- a/src/wallet/cc_wallet/debug_spend_bundle.py +++ b/src/wallet/cc_wallet/debug_spend_bundle.py @@ -4,8 +4,6 @@ from clvm import KEYWORD_FROM_ATOM from clvm_tools.binutils import disassemble as bu_disassemble -from stages.stage_0 import run_program - from src.types.coin import Coin from src.types.condition_opcodes import ConditionOpcode from src.types.program import Program @@ -53,7 +51,7 @@ def debug_spend_bundle(spend_bundle: SpendBundle) -> None: print("=" * 80) for coin_solution in spend_bundle.coin_solutions: - coin, solution_pair = coin_solution.coin, coin_solution.solution + coin, solution_pair = coin_solution.coin, Program.to(coin_solution.solution) puzzle_reveal = solution_pair.first() solution = solution_pair.rest().first() @@ -70,7 +68,7 @@ def debug_spend_bundle(spend_bundle: SpendBundle) -> None: print(f"*** error {error}") else: print() - cost, r = run_program(puzzle_reveal, solution) + r = puzzle_reveal.run(solution) print(disassemble(r)) print() if conditions and len(conditions) > 0: diff --git a/src/wallet/puzzles/genesis_by_coin_id_with_0.py b/src/wallet/puzzles/genesis_by_coin_id_with_0.py index d7a365c7e8b0..44dc9d12b2b9 100644 --- a/src/wallet/puzzles/genesis_by_coin_id_with_0.py +++ b/src/wallet/puzzles/genesis_by_coin_id_with_0.py @@ -1,7 +1,5 @@ from typing import Optional -from clvm_tools.curry import curry as ct_curry, uncurry - from src.types.coin import Coin from src.types.program import Program from src.types.sized_bytes import bytes32 @@ -11,22 +9,13 @@ from src.wallet.puzzles.load_clvm import load_clvm MOD = load_clvm("genesis-by-coin-id-with-0.clvm", package_or_requirement=__name__) -def curry(*args, **kwargs): - """ - The clvm_tools version of curry returns `cost, program` for now. - Eventually it will just return `program`. This placeholder awaits that day. - """ - cost, prog = ct_curry(*args, **kwargs) - return Program.to(prog) - - def create_genesis_or_zero_coin_checker(genesis_coin_id: bytes32) -> Program: """ Given a specific genesis coin id, create a `genesis_coin_mod` that allows both that coin id to issue a cc, or anyone to create a cc with amount 0. """ genesis_coin_mod = MOD - return curry(genesis_coin_mod, [genesis_coin_id]) + return genesis_coin_mod.curry(genesis_coin_id) def genesis_coin_id_for_genesis_coin_checker( @@ -35,7 +24,7 @@ def genesis_coin_id_for_genesis_coin_checker( """ Given a `genesis_coin_checker` program, pull out the genesis coin id. """ - r = uncurry(genesis_coin_checker) + r = genesis_coin_checker.uncurry() if r is None: return r f, args = r diff --git a/src/wallet/puzzles/genesis_by_puzzle_hash_with_0.py b/src/wallet/puzzles/genesis_by_puzzle_hash_with_0.py index c5c8fe70b802..78b6f8b86c8b 100644 --- a/src/wallet/puzzles/genesis_by_puzzle_hash_with_0.py +++ b/src/wallet/puzzles/genesis_by_puzzle_hash_with_0.py @@ -1,7 +1,5 @@ from typing import Optional -from clvm_tools.curry import curry as ct_curry, uncurry - from src.types.coin import Coin from src.types.program import Program from src.types.sized_bytes import bytes32 @@ -11,22 +9,13 @@ from src.wallet.puzzles.load_clvm import load_clvm MOD = load_clvm("genesis-by-puzzle-hash-with-0.clvm", package_or_requirement=__name__) -def curry(*args, **kwargs): - """ - The clvm_tools version of curry returns `cost, program` for now. - Eventually it will just return `program`. This placeholder awaits that day. - """ - cost, prog = ct_curry(*args, **kwargs) - return Program.to(prog) - - def create_genesis_puzzle_or_zero_coin_checker(genesis_puzzle_hash: bytes32) -> Program: """ Given a specific genesis coin id, create a `genesis_coin_mod` that allows both that coin id to issue a cc, or anyone to create a cc with amount 0. """ genesis_coin_mod = MOD - return curry(genesis_coin_mod, [genesis_puzzle_hash]) + return genesis_coin_mod.curry(genesis_puzzle_hash) def genesis_puzzle_hash_for_genesis_coin_checker( @@ -35,7 +24,7 @@ def genesis_puzzle_hash_for_genesis_coin_checker( """ Given a `genesis_coin_checker` program, pull out the genesis puzzle hash. """ - r = uncurry(genesis_coin_checker) + r = genesis_coin_checker.uncurry() if r is None: return r f, args = r @@ -53,7 +42,6 @@ def lineage_proof_for_zero(parent_coin: Coin) -> Program: def lineage_proof_for_coin(parent_coin: Coin) -> Program: - breakpoint() if parent_coin.amount == 0: return lineage_proof_for_zero(parent_coin) return lineage_proof_for_genesis_puzzle(parent_coin) diff --git a/tests/util/benchmark_cost.py b/tests/util/benchmark_cost.py index a5926f77462f..54693205477b 100644 --- a/tests/util/benchmark_cost.py +++ b/tests/util/benchmark_cost.py @@ -8,7 +8,6 @@ from src.types.condition_opcodes import ConditionOpcode from src.types.condition_var_pair import ConditionVarPair from src.types.program import Program from src.wallet.puzzles.p2_delegated_puzzle import puzzle_for_pk -from src.util.clvm import run_program from src.util.wallet_tools import WalletTool from src.util.ints import uint32 from src.wallet.derive_keys import master_sk_to_wallet_sk @@ -42,7 +41,7 @@ def run_and_return_cost_time(chialisp): clvm_loop_solution = f"(1000 {chialisp})" solution_program = Program(binutils.assemble(clvm_loop_solution)) - cost, sexp = run_program(loop_program, solution_program) + cost, sexp = loop_program.run_with_cost(solution_program) end = time.time() total_time = end - start @@ -156,7 +155,7 @@ if __name__ == "__main__": puzzle_start = time.time() clvm_cost = 0 for i in range(0, 1000): - cost_run, sexp = run_program(puzzles[i], solutions[i]) + cost_run, sexp = puzzles[i].run_with_cost(solutions[i]) clvm_cost += cost_run puzzle_end = time.time()