def rl_make_aggregation_puzzle(wallet_puzzle): """ If Wallet A wants to send further funds to Wallet B then they can lock them up using this code Solution will be (my_id wallet_coin_primary_input wallet_coin_amount) """ MOD = load_clvm("../puzzles/rl_aggregation.clvm") return MOD.curry(wallet_puzzle)
def rl_puzzle_for_pk( pubkey: bytes, rate_amount: uint64, interval_time: uint64, origin_id: bytes32, clawback_pk: bytes, ): """ Solution to this puzzle must be in format: (1 my_parent_id, my_puzzlehash, my_amount, outgoing_puzzle_hash, outgoing_amount, min_block_time, parent_parent_id, parent_amount, fee) RATE LIMIT LOGIC: M - chia_per_interval N - interval_blocks V - amount being spent MIN_BLOCK_AGE = V / (M / N) if not (min_block_age * M >= V * N) do X (raise) ASSERT_COIN_BLOCK_AGE_EXCEEDS min_block_age """ MOD = load_clvm("../puzzles/rl.clvm") return MOD.curry(pubkey, rate_amount, interval_time, origin_id, clawback_pk)
from typing import Optional from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 from chia.wallet.puzzles.load_clvm import load_clvm MOD = load_clvm("genesis-by-coin-id-with-0.clvm", package_or_requirement=__name__) 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 genesis_coin_mod.curry(genesis_coin_id) def genesis_coin_id_for_genesis_coin_checker( genesis_coin_checker: Program, ) -> Optional[bytes32]: """ Given a `genesis_coin_checker` program, pull out the genesis coin id. """ r = genesis_coin_checker.uncurry() if r is None: return r f, args = r if f != MOD: return None
from chia.consensus.constants import ConsensusConstants from chia.util.ints import uint64, uint16, uint32 from chia.util.default_root import DEFAULT_ROOT_PATH from chia.rpc.full_node_rpc_client import FullNodeRpcClient from chia.full_node.signage_point import SignagePoint from chia.types.end_of_slot_bundle import EndOfSubSlotBundle from chia.types.blockchain_format.sized_bytes import bytes32 from chia.consensus.pot_iterations import calculate_iterations_quality, calculate_sp_interval_iters from chia.util.lru_cache import LRUCache from chia.wallet.puzzles.load_clvm import load_clvm from chia.wallet.transaction_record import TransactionRecord from error_codes import PoolErr from store import FarmerRecord, PoolStore SINGLETON_MOD = load_clvm("singleton_top_layer.clvm") P2_SINGLETON_MOD = load_clvm("p2_singleton.clvm") POOL_COMMITED_MOD = load_clvm("pool_member_innerpuz.clvm") POOL_ESCAPING_MOD = load_clvm("pool_escaping_innerpuz.clvm") singleton_mod_hash = SINGLETON_MOD.get_tree_hash() @dataclasses.dataclass class SingletonState: pool_url: str pool_puzzle_hash: bytes32 relative_lock_height: uint32 minimum_difficulty: uint64 escaping: bool blockchain_height: uint32 singleton_coin_id: bytes32
import logging from typing import List, Optional, Union, Tuple from chia.types.blockchain_format.program import Program, SerializedProgram from chia.types.generator_types import BlockGenerator, GeneratorArg, GeneratorBlockCacheInterface, CompressorArg from chia.util.ints import uint32, uint64 from chia.wallet.puzzles.load_clvm import load_clvm from chia.wallet.puzzles.rom_bootstrap_generator import get_generator GENERATOR_MOD = get_generator() DECOMPRESS_BLOCK = load_clvm("block_program_zero.clvm", package_or_requirement="chia.wallet.puzzles") DECOMPRESS_PUZZLE = load_clvm("decompress_puzzle.clvm", package_or_requirement="chia.wallet.puzzles") # DECOMPRESS_CSE = load_clvm("decompress_coin_solution_entry.clvm", package_or_requirement="chia.wallet.puzzles") DECOMPRESS_CSE_WITH_PREFIX = load_clvm( "decompress_coin_solution_entry_with_prefix.clvm", package_or_requirement="chia.wallet.puzzles") log = logging.getLogger(__name__) def create_block_generator( generator: SerializedProgram, block_heights_list: List[uint32], generator_block_cache: GeneratorBlockCacheInterface ) -> Optional[BlockGenerator]: """`create_block_generator` will returns None if it fails to look up any referenced block""" generator_arg_list: List[GeneratorArg] = [] for i in block_heights_list: previous_generator = generator_block_cache.get_generator_for_block_height( i)
from clvm_tools import binutils from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.blockchain_format.program import Program from typing import List, Optional, Tuple from blspy import G1Element from chia.types.blockchain_format.coin import Coin from chia.types.coin_solution import CoinSolution from chia.util.ints import uint64 from chia.wallet.puzzles.load_clvm import load_clvm from chia.types.condition_opcodes import ConditionOpcode DID_CORE_MOD = load_clvm("singleton_top_layer.clvm") DID_INNERPUZ_MOD = load_clvm("did_innerpuz.clvm") def create_innerpuz(pubkey: bytes, identities: List[bytes], num_of_backup_ids_needed: uint64) -> Program: backup_ids_hash = Program(Program.to(identities)).get_tree_hash() return DID_INNERPUZ_MOD.curry(DID_CORE_MOD.get_tree_hash(), pubkey, backup_ids_hash, num_of_backup_ids_needed) def create_fullpuz(innerpuz, genesis_puzhash) -> Program: mod_hash = DID_CORE_MOD.get_tree_hash() return DID_CORE_MOD.curry(mod_hash, genesis_puzhash, innerpuz) def get_pubkey_from_innerpuz(innerpuz: Program) -> G1Element: ret = uncurry_innerpuz(innerpuz) if ret is not None: pubkey_program = ret[0]
from typing import Optional from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 from chia.wallet.puzzles.load_clvm import load_clvm MOD = load_clvm("genesis-by-puzzle-hash-with-0.clvm", package_or_requirement=__name__) 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 genesis_coin_mod.curry(genesis_puzzle_hash) def genesis_puzzle_hash_for_genesis_coin_checker( genesis_coin_checker: Program, ) -> Optional[bytes32]: """ Given a `genesis_coin_checker` program, pull out the genesis puzzle hash. """ r = genesis_coin_checker.uncurry() if r is None: return r f, args = r if f != MOD:
compressed_spend_bundle_solution, match_standard_transaction_at_any_index, ) from chia.full_node.generator import run_generator, create_generator_args from chia.types.blockchain_format.program import Program, SerializedProgram from chia.types.generator_types import CompressorArg from chia.types.spend_bundle import SpendBundle from chia.util.byte_types import hexstr_to_bytes from chia.util.ints import uint32 from chia.wallet.puzzles.load_clvm import load_clvm from tests.core.make_block_generator import make_spend_bundle from clvm_tools import binutils TEST_GEN_DESERIALIZE = load_clvm("test_generator_deserialize.clvm", package_or_requirement="chia.wallet.puzzles") DESERIALIZE_MOD = load_clvm("chialisp_deserialisation.clvm", package_or_requirement="chia.wallet.puzzles") DECOMPRESS_PUZZLE = load_clvm("decompress_puzzle.clvm", package_or_requirement="chia.wallet.puzzles") DECOMPRESS_CSE = load_clvm("decompress_coin_solution_entry.clvm", package_or_requirement="chia.wallet.puzzles") DECOMPRESS_CSE_WITH_PREFIX = load_clvm( "decompress_coin_solution_entry_with_prefix.clvm", package_or_requirement="chia.wallet.puzzles") DECOMPRESS_BLOCK = load_clvm("block_program_zero.clvm", package_or_requirement="chia.wallet.puzzles") Nil = Program.from_bytes(b"\x80")
from unittest import TestCase from chia.types.blockchain_format.program import Program, SerializedProgram, INFINITE_COST from chia.wallet.puzzles.load_clvm import load_clvm SHA256TREE_MOD = load_clvm("sha256tree_module.clvm") # TODO: test multiple args class TestSerializedProgram(TestCase): def test_tree_hash(self): p = SHA256TREE_MOD s = SerializedProgram.from_bytes(bytes(SHA256TREE_MOD)) self.assertEqual(s.get_tree_hash(), p.get_tree_hash()) def test_program_execution(self): p_result = SHA256TREE_MOD.run(SHA256TREE_MOD) sp = SerializedProgram.from_bytes(bytes(SHA256TREE_MOD)) cost, sp_result = sp.run_with_cost(INFINITE_COST, sp) self.assertEqual(p_result, sp_result) def test_serialization(self): s0 = SerializedProgram.from_bytes(b"\x00") p0 = Program.from_bytes(b"\x00") print(s0, p0) # TODO: enable when clvm updated for minimal encoding of zero # self.assertEqual(bytes(p0), bytes(s0))
from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.spend_bundle import SpendBundle from chia.util.ints import uint64 from chia.util.byte_types import hexstr_to_bytes from chia.wallet.lineage_proof import LineageProof from chia.wallet.puzzles.load_clvm import load_clvm from chia.wallet.cat_wallet.cat_utils import ( CAT_MOD, construct_cat_puzzle, unsigned_spend_bundle_for_spendable_cats, SpendableCAT, ) from chia.wallet.cat_wallet.cat_info import CATInfo from chia.wallet.transaction_record import TransactionRecord GENESIS_BY_ID_MOD = load_clvm("genesis-by-coin-id-with-0.clvm") GENESIS_BY_PUZHASH_MOD = load_clvm("genesis-by-puzzle-hash-with-0.clvm") EVERYTHING_WITH_SIG_MOD = load_clvm("everything_with_signature.clvm") DELEGATED_LIMITATIONS_MOD = load_clvm("delegated_genesis_checker.clvm") class LimitationsProgram: @staticmethod def match(uncurried_mod: Program, curried_args: Program) -> Tuple[bool, List[Program]]: raise NotImplementedError( "Need to implement 'match' on limitations programs") @staticmethod def construct(args: List[Program]) -> Program: raise NotImplementedError(
from chia.wallet.puzzles.load_clvm import load_clvm P2_SINGLETON_MOD = load_clvm("p2_singleton.clvm") SINGLETON_TOP_LAYER_MOD = load_clvm("singleton_top_layer.clvm") SINGLETON_LAUNCHER = load_clvm("singleton_launcher.clvm")
from typing import List, Tuple, Optional from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.condition_opcodes import ConditionOpcode from chia.types.coin_spend import CoinSpend from chia.wallet.puzzles.load_clvm import load_clvm from chia.wallet.lineage_proof import LineageProof from chia.util.ints import uint64 from chia.util.hash import std_hash SINGLETON_MOD = load_clvm("singleton_top_layer.clvm") SINGLETON_MOD_HASH = SINGLETON_MOD.get_tree_hash() P2_SINGLETON_MOD = load_clvm("p2_singleton.clvm") P2_SINGLETON_OR_DELAYED_MOD = load_clvm("p2_singleton_or_delayed_puzhash.clvm") SINGLETON_LAUNCHER = load_clvm("singleton_launcher.clvm") SINGLETON_LAUNCHER_HASH = SINGLETON_LAUNCHER.get_tree_hash() ESCAPE_VALUE = -113 MELT_CONDITION = [ConditionOpcode.CREATE_COIN, 0, ESCAPE_VALUE] # Given the parent and amount of the launcher coin, return the launcher coin def generate_launcher_coin(coin: Coin, amount: uint64) -> Coin: return Coin(coin.name(), SINGLETON_LAUNCHER_HASH, amount) # Wrap inner puzzles that are not singleton specific to strip away "truths" def adapt_inner_to_singleton(inner_puzzle: Program) -> Program: # (a (q . inner_puzzle) (r 1)) return Program.to([2, (1, inner_puzzle), [6, 1]])
from chia.consensus.coinbase import pool_parent_id from chia.pools.pool_wallet_info import PoolState, LEAVING_POOL, SELF_POOLING from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program, SerializedProgram from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.coin_spend import CoinSpend from chia.wallet.puzzles.load_clvm import load_clvm from chia.wallet.puzzles.singleton_top_layer import puzzle_for_singleton from chia.util.ints import uint32, uint64 log = logging.getLogger(__name__) # "Full" is the outer singleton, with the inner puzzle filled in SINGLETON_MOD = load_clvm("singleton_top_layer.clvm") POOL_WAITING_ROOM_MOD = load_clvm("pool_waitingroom_innerpuz.clvm") POOL_MEMBER_MOD = load_clvm("pool_member_innerpuz.clvm") P2_SINGLETON_MOD = load_clvm("p2_singleton_or_delayed_puzhash.clvm") POOL_OUTER_MOD = SINGLETON_MOD POOL_MEMBER_HASH = POOL_MEMBER_MOD.get_tree_hash() POOL_WAITING_ROOM_HASH = POOL_WAITING_ROOM_MOD.get_tree_hash() P2_SINGLETON_HASH = P2_SINGLETON_MOD.get_tree_hash() POOL_OUTER_MOD_HASH = POOL_OUTER_MOD.get_tree_hash() SINGLETON_LAUNCHER_HASH = SINGLETON_LAUNCHER.get_tree_hash() SINGLETON_MOD_HASH = POOL_OUTER_MOD_HASH SINGLETON_MOD_HASH_HASH = Program.to(SINGLETON_MOD_HASH).get_tree_hash()
from chia.types.blockchain_format.program import Program from chia.util.bech32m import decode_puzzle_hash from chia.consensus.constants import ConsensusConstants from chia.util.ints import uint64, uint16, uint32 from chia.util.default_root import DEFAULT_ROOT_PATH from chia.rpc.full_node_rpc_client import FullNodeRpcClient from chia.full_node.signage_point import SignagePoint from chia.types.end_of_slot_bundle import EndOfSubSlotBundle from chia.types.blockchain_format.sized_bytes import bytes32 from chia.consensus.pot_iterations import calculate_iterations_quality, calculate_sp_interval_iters from chia.util.lru_cache import LRUCache from chia.wallet.puzzles.load_clvm import load_clvm from error_codes import PoolErr from store import FarmerRecord, PoolStore SINGLETON_MOD = load_clvm("singleton_top_layer.clvm") P2_SINGLETON_MOD = load_clvm("p2_singleton.clvm") singleton_mod_hash = SINGLETON_MOD.get_tree_hash() @dataclasses.dataclass class SingletonState: pool_url: str pool_puzzle_hash: bytes32 relative_lock_height: uint32 minimum_difficulty: uint64 maximum_difficulty: uint64 escaping: bool blockchain_height: uint32 singleton_coin_id: bytes32
from chia.wallet.puzzles.load_clvm import load_clvm CC_MOD = load_clvm("cc.clvm", package_or_requirement=__name__) LOCK_INNER_PUZZLE = load_clvm("lock.inner.puzzle.clvm", package_or_requirement=__name__)
from chia.wallet.puzzles.load_clvm import load_clvm from chia.types.blockchain_format.program import Program, INFINITE_COST DID_CORE_MOD = load_clvm("singleton_top_layer.clvm") def test_only_odd_coins(): did_core_hash = DID_CORE_MOD.get_tree_hash() solution = Program.to([ did_core_hash, did_core_hash, 1, [0xDEADBEEF, 0xCAFEF00D, 200], 200, [[51, 0xCAFEF00D, 200]] ]) try: result, cost = DID_CORE_MOD.run_with_cost(INFINITE_COST, solution) except Exception as e: assert e.args == ("clvm raise", ) else: assert False solution = Program.to([ did_core_hash, did_core_hash, 1, [0xDEADBEEF, 0xCAFEF00D, 210], 205, [[51, 0xCAFEF00D, 205]] ]) try: result, cost = DID_CORE_MOD.run_with_cost(INFINITE_COST, solution) except Exception: assert False def test_only_one_odd_coin_created(): did_core_hash = DID_CORE_MOD.get_tree_hash() solution = Program.to([
compress_object_with_puzzles, decompress_object_with_puzzles, lowest_best_version, ) from chia.wallet.cat_wallet.cat_utils import ( CAT_MOD, SpendableCAT, construct_cat_puzzle, match_cat_puzzle, unsigned_spend_bundle_for_spendable_cats, ) from chia.wallet.lineage_proof import LineageProof from chia.wallet.puzzles.load_clvm import load_clvm from chia.wallet.payment import Payment OFFER_MOD = load_clvm("settlement_payments.clvm") ZERO_32 = bytes32([0] * 32) @dataclass(frozen=True) class NotarizedPayment(Payment): nonce: bytes32 = ZERO_32 @classmethod def from_condition_and_nonce(cls, condition: Program, nonce: bytes32) -> "NotarizedPayment": with_opcode: Program = Program.to( (51, condition )) # Gotta do this because the super class is expecting it p = Payment.from_condition(with_opcode) puzzle_hash, amount, memos = tuple(p.as_condition_args())
from chia.types.end_of_slot_bundle import EndOfSubSlotBundle from chia.types.spend_bundle import SpendBundle from chia.util.bech32m import decode_puzzle_hash from chia.util.default_root import DEFAULT_ROOT_PATH from chia.util.ints import uint64, uint16, uint32 from chia.util.lru_cache import LRUCache from chia.wallet.puzzles.load_clvm import load_clvm from chia.wallet.transaction_record import TransactionRecord ### Commented out because it doesn't exist on the chia blockchain yet. Had to add it manually to protocols.py # from chia.protocols.pool_protocol import SubmitPartial from services.pool.chia_patch.protocols.pool_protocol import SubmitPartial from services.pool.error_codes import PoolErr from store import FarmerRecord, PoolStore SINGLETON_MOD = load_clvm("singleton_top_layer.clvm") # TODO(OzChiaPool): fix ### Commented out because these puzzles don't exist # P2_SINGLETON_MOD = load_clvm("p2_singleton.clvm") # POOL_COMMITED_MOD = load_clvm("pool_member_innerpuz.clvm") # POOL_ESCAPING_MOD = load_clvm("pool_escaping_innerpuz.clvm") singleton_mod_hash = SINGLETON_MOD.get_tree_hash() @dataclasses.dataclass class SingletonState: pool_url: str pool_puzzle_hash: bytes32 relative_lock_height: uint32 minimum_difficulty: uint64 escaping: bool
from chia.full_node.generator import run_generator from chia.full_node.mempool_check_conditions import get_name_puzzle_conditions from chia.types.blockchain_format.program import Program, SerializedProgram from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.condition_with_args import ConditionWithArgs from chia.types.name_puzzle_condition import NPC from chia.types.generator_types import BlockGenerator, GeneratorArg from chia.util.clvm import int_to_bytes from chia.util.condition_tools import ConditionOpcode from chia.util.ints import uint32 from chia.wallet.puzzles.load_clvm import load_clvm MAX_COST = int(1e15) COST_PER_BYTE = int(12000) DESERIALIZE_MOD = load_clvm("chialisp_deserialisation.clvm", package_or_requirement="chia.wallet.puzzles") GENERATOR_CODE = """ (mod (deserialize-mod historical-generators) (defun first-block (deserialize-mod historical-generators) (a deserialize-mod (list (f historical-generators)))) (defun second-block (deserialize-mod historical-generators) (a deserialize-mod (r historical-generators))) (defun go (deserialize-mod historical-generators) (c (first-block deserialize-mod historical-generators) (second-block deserialize-mod historical-generators) )) (go deserialize-mod historical-generators) )
from clvm_tools import binutils from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.blockchain_format.program import Program from typing import List, Optional, Tuple from blspy import G1Element from chia.types.blockchain_format.coin import Coin from chia.types.coin_spend import CoinSpend from chia.util.ints import uint64 from chia.wallet.puzzles.load_clvm import load_clvm from chia.types.condition_opcodes import ConditionOpcode SINGLETON_TOP_LAYER_MOD = load_clvm("singleton_top_layer.clvm") LAUNCHER_PUZZLE = load_clvm("singleton_launcher.clvm") DID_INNERPUZ_MOD = load_clvm("did_innerpuz.clvm") SINGLETON_LAUNCHER = load_clvm("singleton_launcher.clvm") def create_innerpuz(pubkey: bytes, identities: List[bytes], num_of_backup_ids_needed: uint64) -> Program: backup_ids_hash = Program(Program.to(identities)).get_tree_hash() # MOD_HASH MY_PUBKEY RECOVERY_DID_LIST_HASH NUM_VERIFICATIONS_REQUIRED return DID_INNERPUZ_MOD.curry(pubkey, backup_ids_hash, num_of_backup_ids_needed) def create_fullpuz(innerpuz: Program, genesis_id: bytes32) -> Program: mod_hash = SINGLETON_TOP_LAYER_MOD.get_tree_hash() # singleton_struct = (MOD_HASH . (LAUNCHER_ID . LAUNCHER_PUZZLE_HASH)) singleton_struct = Program.to( (mod_hash, (genesis_id, LAUNCHER_PUZZLE.get_tree_hash()))) return SINGLETON_TOP_LAYER_MOD.curry(singleton_struct, innerpuz)
from clvm_tools import binutils from chia.types.blockchain_format.program import Program, INFINITE_COST from chia.types.announcement import Announcement from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.condition_tools import parse_sexp_to_conditions from chia.wallet.puzzles.load_clvm import load_clvm SINGLETON_MOD = load_clvm("singleton_top_layer.clvm") LAUNCHER_PUZZLE = load_clvm("singleton_launcher.clvm") P2_SINGLETON_MOD = load_clvm("p2_singleton.clvm") POOL_MEMBER_MOD = load_clvm("pool_member_innerpuz.clvm") POOL_WAITINGROOM_MOD = load_clvm("pool_waitingroom_innerpuz.clvm") LAUNCHER_PUZZLE_HASH = LAUNCHER_PUZZLE.get_tree_hash() SINGLETON_MOD_HASH = SINGLETON_MOD.get_tree_hash() LAUNCHER_ID = Program.to(b"launcher-id").get_tree_hash() POOL_REWARD_PREFIX_MAINNET = bytes32.fromhex( "ccd5bb71183532bff220ba46c268991a00000000000000000000000000000000") def singleton_puzzle(launcher_id: Program, launcher_puzzle_hash: bytes32, inner_puzzle: Program) -> Program: return SINGLETON_MOD.curry( (SINGLETON_MOD_HASH, (launcher_id, launcher_puzzle_hash)), inner_puzzle) def p2_singleton_puzzle(launcher_id: Program, launcher_puzzle_hash: bytes32) -> Program:
from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.spend_bundle import SpendBundle from chia.util.ints import uint64 from chia.util.byte_types import hexstr_to_bytes from chia.wallet.lineage_proof import LineageProof from chia.wallet.puzzles.load_clvm import load_clvm from chia.wallet.cat_wallet.cat_utils import ( CAT_MOD, construct_cat_puzzle, unsigned_spend_bundle_for_spendable_cats, SpendableCAT, ) from chia.wallet.cat_wallet.cat_info import CATInfo from chia.wallet.transaction_record import TransactionRecord GENESIS_BY_ID_MOD = load_clvm("genesis_by_coin_id.clvm") GENESIS_BY_PUZHASH_MOD = load_clvm("genesis_by_puzzle_hash.clvm") EVERYTHING_WITH_SIG_MOD = load_clvm("everything_with_signature.clvm") DELEGATED_LIMITATIONS_MOD = load_clvm("delegated_tail.clvm") class LimitationsProgram: @staticmethod def match(uncurried_mod: Program, curried_args: Program) -> Tuple[bool, List[Program]]: raise NotImplementedError( "Need to implement 'match' on limitations programs") @staticmethod def construct(args: List[Program]) -> Program: raise NotImplementedError(