Example #1
0
def match_cat_puzzle(puzzle: Program) -> Tuple[bool, Iterator[Program]]:
    """
    Given a puzzle test if it's a CAT and, if it is, return the curried arguments
    """
    mod, curried_args = puzzle.uncurry()
    if mod == CAT_MOD:
        return True, curried_args.as_iter()
    else:
        return False, iter(())
def create_compressed_generator(
    original_generator: CompressorArg,
    compressed_cse_list: List[List[Union[List[uint64], List[Union[bytes, None,
                                                                  Program]]]]],
) -> BlockGenerator:
    """
    Bind the generator block program template to a particular reference block,
    template bytes offsets, and SpendBundle.
    """
    start = original_generator.start
    end = original_generator.end
    program = DECOMPRESS_BLOCK.curry(DECOMPRESS_PUZZLE,
                                     DECOMPRESS_CSE_WITH_PREFIX,
                                     Program.to(start), Program.to(end),
                                     compressed_cse_list)
    generator_arg = GeneratorArg(original_generator.block_height,
                                 original_generator.generator)
    return BlockGenerator(program, [generator_arg])
Example #3
0
def match_limitations_program(
    limitations_program: Program
) -> Tuple[Optional[LimitationsProgram], List[Program]]:
    uncurried_mod, curried_args = limitations_program.uncurry()
    for key, lp in ALL_LIMITATIONS_PROGRAMS.items():
        matched, args = lp.match(uncurried_mod, curried_args)
        if matched:
            return lp, args
    return None, []
Example #4
0
def get_innerpuzzle_from_puzzle(puzzle: Program) -> Optional[Program]:
    r = puzzle.uncurry()
    if r is None:
        return None
    inner_f, args = r
    if not is_did_core(inner_f):
        return None
    mod_hash, genesis_id, inner_puzzle = list(args.as_iter())
    return inner_puzzle
Example #5
0
    def make_solution(
        self, condition_dic: Dict[ConditionOpcode,
                                  List[ConditionWithArgs]]) -> Program:
        ret = []

        for con_list in condition_dic.values():
            for cvp in con_list:
                ret.append([cvp.opcode.value] + cvp.vars)
        return solution_for_conditions(Program.to(ret))
    def test_make_generator_args(self):
        generator_ref_list = [gen1]
        gen_args = create_generator_args(generator_ref_list)
        gen_args_as_program = Program.from_bytes(bytes(gen_args))

        # First Argument to the block generator is the first template generator
        arg2 = gen_args_as_program.first()
        print(arg2)
        assert arg2 == bytes(gen1)
Example #7
0
def get_output_amount_for_puzzle_and_solution(puzzle: Program,
                                              solution: Program) -> int:
    error, conditions, cost = conditions_dict_for_solution(
        puzzle, solution, INFINITE_COST)
    total = 0
    if conditions:
        for _ in conditions.get(ConditionOpcode.CREATE_COIN, []):
            total += Program.to(_.vars[1]).as_int()
    return total
Example #8
0
def coin_solution_for_lock_coin(
    prev_coin: Coin,
    subtotal: int,
    coin: Coin,
) -> CoinSolution:
    puzzle_reveal = LOCK_INNER_PUZZLE.curry(prev_coin.as_list(), subtotal)
    coin = Coin(coin.name(), puzzle_reveal.get_tree_hash(), uint64(0))
    coin_solution = CoinSolution(coin, puzzle_reveal, Program.to(0))
    return coin_solution
Example #9
0
def get_innerpuzzle_from_puzzle(puzzle: Program) -> Optional[Program]:
    r = puzzle.uncurry()
    if r is None:
        return None
    inner_f, args = r
    if not is_did_core(inner_f):
        return None
    SINGLETON_STRUCT, INNER_PUZZLE = list(args.as_iter())
    return INNER_PUZZLE
Example #10
0
def lineage_proof_for_cc_parent(parent_coin: Coin,
                                parent_inner_puzzle_hash: bytes32) -> Program:
    return Program.to((
        1,
        [
            parent_coin.parent_coin_info, parent_inner_puzzle_hash,
            parent_coin.amount
        ],
    ))
Example #11
0
    def solve(self, puzzle_db: PuzzleDB, puzzle: Program,
              **kwargs: Any) -> Program:
        """
        The legal values and types for `kwargs` depends on the underlying solver
        that's invoked. The `kwargs` are passed through to any inner solvers
        that may need to be called.
        """
        puzzle_hash = puzzle.get_tree_hash()
        puzzle_args = []
        if puzzle_hash not in self.solvers_by_puzzle_hash:
            puzzle_template, args = puzzle.uncurry()
            puzzle_args = list(args.as_iter())
            puzzle_hash = puzzle_template.get_tree_hash()
        solver_f = self.solvers_by_puzzle_hash.get(puzzle_hash)
        if solver_f:
            return solver_f(self, puzzle_db, puzzle_args, kwargs)

        raise ValueError("can't solve")
Example #12
0
 def to_program(self) -> Program:
     final_list: List[Any] = []
     if self.parent_name is not None:
         final_list.append(self.parent_name)
     if self.inner_puzzle_hash is not None:
         final_list.append(self.inner_puzzle_hash)
     if self.amount is not None:
         final_list.append(self.amount)
     return Program.to(final_list)
Example #13
0
def solve_anyone_can_spend(solver: Solver, puzzle_db: PuzzleDB,
                           args: List[Program], kwargs: Dict) -> Program:
    """
    This is the anyone-can-spend puzzle `1`. Note that farmers can easily steal this coin, so don't use
    it except for testing.
    """
    conditions = from_kwargs(kwargs, "conditions", List[Program])
    solution = Program.to(conditions)
    return solution
Example #14
0
def solve_pool_member(solver: Solver, puzzle_db: PuzzleDB, args: List[Program],
                      kwargs: Dict) -> Program:
    pool_member_spend_type = from_kwargs(kwargs, "pool_member_spend_type")
    allowable = ["to-waiting-room", "claim-p2-nft"]
    if pool_member_spend_type not in allowable:
        raise ValueError(
            "`pool_member_spend_type` must be one of %s for POOL_MEMBER puzzle"
            % "/".join(allowable))
    to_waiting_room = pool_member_spend_type == "to-waiting-room"
    if to_waiting_room:
        key_value_list = from_kwargs(kwargs, "key_value_list",
                                     List[Tuple[str, Program]])
        return Program.to([0, 1, 0, 0, key_value_list])
    # it's an "absorb_pool_reward" type
    pool_reward_amount = from_kwargs(kwargs, "pool_reward_amount", int)
    pool_reward_height = from_kwargs(kwargs, "pool_reward_height", int)
    solution = Program.to([0, pool_reward_amount, pool_reward_height])
    return solution
Example #15
0
 async def test_invalid_puzzle_announcement(self):
     announce = Announcement(EASY_PUZZLE_HASH, b"test_bad")
     conditions = Program.to(
         assemble(
             f"(({ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT[0]} 'test')"
             f"({ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT[0]} 0x{announce.name().hex()}))"
         )
     )
     await check_conditions(conditions, expected_err=Err.ASSERT_ANNOUNCE_CONSUMED_FAILED)
Example #16
0
def claim_p2_singleton(
    p2_singleton_coin: Coin,
    singleton_inner_puzhash: bytes32,
    launcher_id: bytes32,
) -> Tuple[Program, Program, CoinSolution]:
    assertion = Program.to([
        ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT,
        std_hash(p2_singleton_coin.name() + b"$")
    ])
    announcement = Program.to(
        [ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT,
         p2_singleton_coin.name()])
    claim_coinsol = CoinSolution(
        p2_singleton_coin,
        pay_to_singleton_puzzle(launcher_id),
        solution_for_p2_singleton(p2_singleton_coin, singleton_inner_puzhash),
    )
    return assertion, announcement, claim_coinsol
Example #17
0
    def test_block_program_zero_with_curry(self):
        self.maxDiff = None
        cse1 = binutils.assemble(
            "(((0x0000000000000000000000000000000000000000000000000000000000000000 0x0186a0) (0xb081963921826355dcb6c355ccf9c2637c18adf7d38ee44d803ea9ca41587e48c913d8d46896eb830aeadfc13144a8eac3 (() (q (51 0x6b7a83babea1eec790c947db4464ab657dbe9b887fe9acc247062847b8c2a8a9 0x0186a0)) ()))))"
        )  # noqa
        cse2 = binutils.assemble("""
(
  ((0x0000000000000000000000000000000000000000000000000000000000000000 0x0186a0)
   (0xb081963921826355dcb6c355ccf9c2637c18adf7d38ee44d803ea9ca41587e48c913d8d46896eb830aeadfc13144a8eac3
    (() (q (51 0x6b7a83babea1eec790c947db4464ab657dbe9b887fe9acc247062847b8c2a8a9 0x0186a0)) ()))
  )

  ((0x0000000000000000000000000000000000000000000000000000000000000001 0x0186a0)
   (0xb0a6207f5173ec41491d9f2c1b8fff5579e13703077e0eaca8fe587669dcccf51e9209a6b65576845ece5f7c2f3229e7e3
   (() (q (51 0x24254a3efc3ebfac9979bbe0d615e2eda043aa329905f65b63846fa24149e2b6 0x0186a0)) ())))

)
        """)  # noqa

        start = 2 + 44
        end = start + 238

        # (mod (decompress_puzzle decompress_coin_solution_entry start end compressed_cses deserialize generator_list reserved_arg)
        # cost, out = DECOMPRESS_BLOCK.run_with_cost([DECOMPRESS_PUZZLE, DECOMPRESS_CSE, start, Program.to(end), cse0, DESERIALIZE_MOD, bytes(original_generator)])
        p = DECOMPRESS_BLOCK.curry(DECOMPRESS_PUZZLE,
                                   DECOMPRESS_CSE_WITH_PREFIX, start,
                                   Program.to(end))
        cost, out = p.run_with_cost(
            [cse2, DESERIALIZE_MOD,
             bytes(original_generator)])

        print()
        print(p)
        print(out)

        p_with_cses = DECOMPRESS_BLOCK.curry(DECOMPRESS_PUZZLE,
                                             DECOMPRESS_CSE_WITH_PREFIX, start,
                                             Program.to(end), cse2)
        cost, out = p_with_cses.run_with_cost(
            [DESERIALIZE_MOD, bytes(original_generator)])

        print()
        print(p_with_cses)
        print(out)
    async def test_genesis_by_puzhash(self, setup_sim):
        sim, sim_client = setup_sim

        try:
            standard_acs = Program.to(1)
            standard_acs_ph: bytes32 = standard_acs.get_tree_hash()
            await sim.farm_block(standard_acs_ph)

            starting_coin: Coin = (await sim_client.get_coin_records_by_puzzle_hash(standard_acs_ph))[0].coin
            tail: Program = GenesisByPuzhash.construct([Program.to(starting_coin.puzzle_hash)])
            checker_solution: Program = GenesisByPuzhash.solve([], starting_coin.to_json_dict())
            cat_puzzle: Program = construct_cat_puzzle(CAT_MOD, tail.get_tree_hash(), acs)
            cat_ph: bytes32 = cat_puzzle.get_tree_hash()

            await sim_client.push_tx(
                SpendBundle(
                    [CoinSpend(starting_coin, standard_acs, Program.to([[51, cat_ph, starting_coin.amount]]))],
                    G2Element(),
                )
            )
            await sim.farm_block()

            await self.do_spend(
                sim,
                sim_client,
                tail,
                [(await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False))[0].coin],
                [NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), starting_coin.amount],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    )
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                limitations_solutions=[checker_solution],
                cost_str="Genesis by Puzhash",
            )

        finally:
            await sim.close()
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]])
Example #20
0
def get_seconds_and_delayed_puzhash_from_p2_singleton_puzzle(
        puzzle: Program) -> Tuple[uint64, bytes32]:
    r = puzzle.uncurry()
    if r is None:
        return False
    inner_f, args = r
    singleton_mod_hash, launcher_id, launcher_puzzle_hash, seconds_delay, delayed_puzzle_hash = list(
        args.as_iter())
    seconds_delay = uint64(seconds_delay.as_int())
    return seconds_delay, delayed_puzzle_hash.as_atom()
Example #21
0
def default_payments_and_conditions(
    initial_index: int, key_lookup: KeyTool
) -> Tuple[List[Tuple[bytes32, int]], Program]:

    payments = [
        (throwaway_puzzle_hash(initial_index + 1, key_lookup), initial_index * 1000),
        (throwaway_puzzle_hash(initial_index + 2, key_lookup), (initial_index + 1) * 1000),
    ]
    conditions = Program.to([make_create_coin_condition(ph, amount) for ph, amount in payments])
    return payments, conditions
Example #22
0
    def test_rom_inputs(self):
        # this test checks that the generator just works
        # It's useful for debugging the generator prior to having the ROM invoke it.

        args = Program.to(
            [DESERIALIZE_MOD, [FIRST_GENERATOR, SECOND_GENERATOR]])
        sp = to_sp(COMPILED_GENERATOR_CODE)
        cost, r = sp.run_with_cost(MAX_COST, args)
        assert cost == EXPECTED_ABBREVIATED_COST
        assert r.as_bin().hex() == EXPECTED_OUTPUT
Example #23
0
 async def test_invalid_seconds_absolute(self):
     # TODO: make the test suite not use `time.time` so we can more accurately
     # set `time_now` to make it minimal while still failing
     time_now = int(time.time()) + 3000
     conditions = Program.to(
         assemble(
             f"(({ConditionOpcode.ASSERT_SECONDS_ABSOLUTE[0]} {time_now}))")
     )
     await check_conditions(conditions,
                            expected_err=Err.ASSERT_SECONDS_ABSOLUTE_FAILED)
Example #24
0
 async def test_valid_coin_announcement(self):
     blocks = initial_blocks()
     coin = list(blocks[-2].get_included_reward_coins())[0]
     announce = Announcement(coin.name(), b"test")
     conditions = Program.to(
         assemble(
             f"(({ConditionOpcode.CREATE_COIN_ANNOUNCEMENT[0]} 'test')"
             f"({ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT[0]} 0x{announce.name().hex()}))"
         ))
     await check_conditions(conditions)
def launcher_conditions_and_spend_bundle(
    puzzle_db: PuzzleDB,
    parent_coin_id: bytes32,
    launcher_amount: uint64,
    initial_singleton_inner_puzzle: Program,
    metadata: List[Tuple[str, str]],
    launcher_puzzle: Program,
) -> Tuple[bytes32, List[Program], SpendBundle]:
    puzzle_db.add_puzzle(launcher_puzzle)
    launcher_puzzle_hash = launcher_puzzle.get_tree_hash()
    launcher_coin = Coin(parent_coin_id, launcher_puzzle_hash, launcher_amount)
    singleton_full_puzzle = singleton_puzzle(launcher_coin.name(),
                                             launcher_puzzle_hash,
                                             initial_singleton_inner_puzzle)
    puzzle_db.add_puzzle(singleton_full_puzzle)
    singleton_full_puzzle_hash = singleton_full_puzzle.get_tree_hash()
    message_program = Program.to(
        [singleton_full_puzzle_hash, launcher_amount, metadata])
    expected_announcement = Announcement(launcher_coin.name(),
                                         message_program.get_tree_hash())
    expected_conditions = []
    expected_conditions.append(
        Program.to(
            binutils.assemble(
                f"(0x{ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT.hex()} 0x{expected_announcement.name()})"
            )))
    expected_conditions.append(
        Program.to(
            binutils.assemble(
                f"(0x{ConditionOpcode.CREATE_COIN.hex()} 0x{launcher_puzzle_hash} {launcher_amount})"
            )))
    solution = solve_puzzle(
        puzzle_db,
        launcher_puzzle,
        destination_puzzle_hash=singleton_full_puzzle_hash,
        launcher_amount=launcher_amount,
        metadata=metadata,
    )
    coin_spend = CoinSpend(launcher_coin,
                           SerializedProgram.from_program(launcher_puzzle),
                           solution)
    spend_bundle = SpendBundle([coin_spend], G2Element())
    return launcher_coin.name(), expected_conditions, spend_bundle
Example #26
0
def conditions_for_solution(
    puzzle_reveal: Program,
    solution: Program,
) -> Tuple[Optional[Err], Optional[List[ConditionWithArgs]], uint64]:
    # get the standard script for a puzzle hash and feed in the solution
    try:
        cost, r = puzzle_reveal.run_with_cost(solution)
        error, result = parse_sexp_to_conditions(r)
        return error, result, uint64(cost)
    except Program.EvalError:
        return Err.SEXP_ERROR, None, uint64(0)
Example #27
0
 async def test_invalid_my_id(self):
     blocks = initial_blocks()
     coin = list(blocks[-2].get_included_reward_coins())[0]
     wrong_name = bytearray(coin.name())
     wrong_name[-1] ^= 1
     conditions = Program.to(
         assemble(
             f"(({ConditionOpcode.ASSERT_MY_COIN_ID[0]} 0x{wrong_name.hex()}))"
         ))
     await check_conditions(conditions,
                            expected_err=Err.ASSERT_MY_COIN_ID_FAILED)
Example #28
0
 def sign_delegated_puz(self, del_puz: Program, coin: Coin) -> G2Element:
     synthetic_secret_key: PrivateKey = p2_delegated_puzzle_or_hidden_puzzle.calculate_synthetic_secret_key(  # noqa
         PrivateKey.from_bytes(
             secret_exponent_for_index(1).to_bytes(32, "big"), ),
         p2_delegated_puzzle_or_hidden_puzzle.DEFAULT_HIDDEN_PUZZLE_HASH,
     )
     return AugSchemeMPL.sign(
         synthetic_secret_key,
         (del_puz.get_tree_hash() + coin.name() +
          DEFAULT_CONSTANTS.AGG_SIG_ME_ADDITIONAL_DATA),  # noqa
     )
Example #29
0
 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,
         DEFAULT_CONSTANTS.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)
Example #30
0
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