Example #1
0
 def test_very_deep_tree(self):
     blob = b"a"
     for depth in [10, 100, 1000, 10000, 100000]:
         s = to_sexp_f(blob)
         for _ in range(depth):
             s = to_sexp_f((s, blob))
         self.check_serde(s)
Example #2
0
def disassemble_to_ir(sexp, keyword_from_atom, allow_keyword=None):
    if is_ir(sexp) and allow_keyword is not False:
        return ir_cons(ir_symbol("ir"), sexp)

    if sexp.nullp():
        return ir_null()

    if sexp.listp():
        if sexp.first().listp() or allow_keyword is None:
            allow_keyword = True
        v0 = disassemble_to_ir(sexp.first(),
                               keyword_from_atom,
                               allow_keyword=allow_keyword)
        v1 = disassemble_to_ir(sexp.rest(),
                               keyword_from_atom,
                               allow_keyword=False)
        return to_sexp_f((Type.CONS, (v0, v1)))

    as_atom = sexp.as_atom()
    if allow_keyword:
        v = keyword_from_atom.get(as_atom)
        if v is not None and v != '.':
            return ir_symbol(v)

    return to_sexp_f((type_for_atom(as_atom), as_atom))
Example #3
0
def assemble_from_ir(ir_sexp):
    keyword = ir_as_symbol(ir_sexp)
    if keyword:
        if keyword[:1] == "#":
            keyword = keyword[1:]
        atom = KEYWORD_TO_ATOM.get(keyword)
        if atom:
            return to_sexp_f(atom)
        if True:
            return ir_val(ir_sexp)
        raise SyntaxError("can't parse %s at %s" % (keyword, ir_sexp._offset))

    if not ir_listp(ir_sexp):
        return ir_val(ir_sexp)

    if ir_nullp(ir_sexp):
        return to_sexp_f([])

    # handle "q"
    first = ir_first(ir_sexp)
    keyword = ir_as_symbol(first)
    if keyword == "q":
        pass
        # TODO: note that any symbol is legal after this point

    sexp_1 = assemble_from_ir(first)
    sexp_2 = assemble_from_ir(ir_rest(ir_sexp))
    return sexp_1.cons(sexp_2)
Example #4
0
    def ap_generate_signed_aggregation_transaction(self):
        list_of_coinsolutions = []
        if self.aggregation_coins is False:  # empty sets evaluate to false in python
            return
        consolidating_coin = self.aggregation_coins.pop()

        pubkey, secretkey = self.get_keys(
            self.temp_coin.puzzle_hash, self.a_pubkey)

        # Spend wallet coin
        puzzle = ap_make_puzzle(self.a_pubkey, bytes(pubkey))
        solution = self.ap_make_solution_mode_2(self.temp_coin.puzzle_hash, consolidating_coin.parent_coin_info,
                                                consolidating_coin.puzzle_hash, consolidating_coin.amount, self.temp_coin.parent_coin_info, self.temp_coin.amount)
        signature = secretkey.sign(ProgramHash(solution))
        list_of_coinsolutions.append(CoinSolution(
            self.temp_coin, clvm.to_sexp_f([puzzle, solution])))

        # Spend consolidating coin
        puzzle = ap_make_aggregation_puzzle(self.temp_coin.puzzle_hash)
        solution = self.ac_make_aggregation_solution(consolidating_coin.name(
        ), self.temp_coin.parent_coin_info, self.temp_coin.amount)
        list_of_coinsolutions.append(CoinSolution(
            consolidating_coin, clvm.to_sexp_f([puzzle, solution])))
        # Spend lock
        puzstring = f"(r (c (q 0x{consolidating_coin.name().hex()}) (q ())))"
        puzzle = Program(binutils.assemble(puzstring))
        solution = Program(binutils.assemble("()"))
        list_of_coinsolutions.append(CoinSolution(Coin(self.temp_coin, ProgramHash(
            puzzle), 0), clvm.to_sexp_f([puzzle, solution])))

        self.temp_coin = Coin(self.temp_coin, self.temp_coin.puzzle_hash,
                              self.temp_coin.amount + consolidating_coin.amount)
        aggsig = BLSSignature.aggregate([signature])
        solution_list = CoinSolutionList(list_of_coinsolutions)
        return SpendBundle(solution_list, aggsig)
Example #5
0
    def rl_generate_signed_aggregation_transaction(self):
        list_of_coinsolutions = []
        if self.aggregation_coins is False:  # empty sets evaluate to false in python
            return
        consolidating_coin = self.aggregation_coins.pop()

        pubkey, secretkey = self.get_keys(self.rl_coin.puzzle_hash)
        # Spend wallet coin
        puzzle = self.rl_puzzle_for_pk(pubkey.serialize(), self.limit,
                                       self.interval, self.rl_origin,
                                       self.rl_clawback_pk)

        if isinstance(self.rl_parent, Coin):
            solution = self.rl_make_solution_mode_2(
                self.rl_coin.puzzle_hash, consolidating_coin.parent_coin_info,
                consolidating_coin.puzzle_hash, consolidating_coin.amount,
                self.rl_coin.parent_coin_info, self.rl_coin.amount,
                self.rl_parent.amount, self.rl_parent.parent_coin_info)
        else:
            solution = self.rl_make_solution_mode_2(
                self.rl_coin.puzzle_hash, consolidating_coin.parent_coin_info,
                consolidating_coin.puzzle_hash, consolidating_coin.amount,
                self.rl_coin.parent_coin_info, self.rl_coin.amount,
                self.rl_parent["amount"], self.rl_parent["parent_coin_info"])
        signature = BLSPrivateKey(secretkey).sign(ProgramHash(solution))
        list_of_coinsolutions.append(
            CoinSolution(self.rl_coin, clvm.to_sexp_f([puzzle, solution])))

        # Spend consolidating coin
        puzzle = self.rl_make_aggregation_puzzle(self.rl_coin.puzzle_hash)
        solution = self.rl_make_aggregation_solution(
            consolidating_coin.name(), self.rl_coin.parent_coin_info,
            self.rl_coin.amount)
        list_of_coinsolutions.append(
            CoinSolution(consolidating_coin, clvm.to_sexp_f([puzzle,
                                                             solution])))
        # Spend lock
        puzstring = "(r (c (q 0x" + hexlify(
            consolidating_coin.name()).decode('ascii') + ") (q ())))"

        puzzle = Program(binutils.assemble(puzstring))
        solution = Program(binutils.assemble("()"))
        list_of_coinsolutions.append(
            CoinSolution(Coin(self.rl_coin, ProgramHash(puzzle), 0),
                         clvm.to_sexp_f([puzzle, solution])))

        aggsig = BLSSignature.aggregate([signature])
        solution_list = CoinSolutionList(list_of_coinsolutions)

        return SpendBundle(solution_list, aggsig)
Example #6
0
    def make_solution(self, condition_dic: Dict[ConditionOpcode,
                                                List[ConditionVarPair]]):
        ret = []

        for con_list in condition_dic.values():
            for cvp in con_list:
                if cvp.opcode == ConditionOpcode.CREATE_COIN:
                    ret.append(make_create_coin_condition(cvp.var1, cvp.var2))
                if cvp.opcode == ConditionOpcode.AGG_SIG:
                    ret.append(make_assert_aggsig_condition(cvp.var1))
                if cvp.opcode == ConditionOpcode.ASSERT_COIN_CONSUMED:
                    ret.append(make_assert_coin_consumed_condition(cvp.var1))
                if cvp.opcode == ConditionOpcode.ASSERT_TIME_EXCEEDS:
                    ret.append(make_assert_time_exceeds_condition(cvp.var1))
                if cvp.opcode == ConditionOpcode.ASSERT_MY_COIN_ID:
                    ret.append(make_assert_my_coin_id_condition(cvp.var1))
                if cvp.opcode == ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS:
                    ret.append(
                        make_assert_block_index_exceeds_condition(cvp.var1))
                if cvp.opcode == ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS:
                    ret.append(
                        make_assert_block_age_exceeds_condition(cvp.var1))
                if cvp.opcode == ConditionOpcode.ASSERT_FEE:
                    ret.append(make_assert_fee_condition(cvp.var1))

        return clvm.to_sexp_f([puzzle_for_conditions(ret), []])
Example #7
0
    def generate_recovery_transaction(self, coins, root_public_key, secret_key,
                                      escrow_duration):
        recovery_pubkey = root_public_key.public_child(
            0).get_public_key().serialize()
        signatures = []
        coin_solutions = []
        secret_key = BLSPrivateKey(secret_key)
        for coin in coins:
            pubkey = self.find_pubkey_for_escrow_puzzle(
                coin, root_public_key, escrow_duration)
            puzzle = self.get_escrow_puzzle_with_params(
                recovery_pubkey, pubkey.serialize(), escrow_duration)

            op_create_coin = ConditionOpcode.CREATE_COIN[0]
            puzzlehash = f'0x' + str(hexbytes(self.get_new_puzzlehash()))
            solution_src = sexp(
                quote(sexp(sexp(op_create_coin, puzzlehash, coin.amount))),
                sexp(), 1)
            solution = Program(binutils.assemble(solution_src))

            puzzle_solution_list = clvm.to_sexp_f([puzzle, solution])
            coin_solution = CoinSolution(coin, puzzle_solution_list)
            coin_solutions.append(coin_solution)

            conditions_dict = conditions_by_opcode(
                conditions_for_solution(puzzle_solution_list))
            for _ in hash_key_pairs_for_conditions_dict(conditions_dict):
                signature = secret_key.sign(_.message_hash)
                signatures.append(signature)

        coin_solution_list = CoinSolutionList(coin_solutions)
        aggsig = BLSSignature.aggregate(signatures)
        spend_bundle = SpendBundle(coin_solution_list, aggsig)
        return spend_bundle
Example #8
0
def create_spend_for_ephemeral(parent_of_e, auditor_coin, spend_amount):
    puzstring = f"(r (r (c (q 0x{auditor_coin.name()}) (c (q {spend_amount}) (q ())))))"
    puzzle = Program(binutils.assemble(puzstring))
    coin = Coin(parent_of_e.name(), puzzle.get_tree_hash(), uint64(0))
    solution = Program(binutils.assemble("()"))
    coinsol = CoinSolution(coin, clvm.to_sexp_f([puzzle, solution]))
    return coinsol
Example #9
0
    def sign_transaction(self, spends: List[Tuple[Program, CoinSolution]]):
        sigs = []
        solution: Program
        puzzle: Program
        for puzzle, solution in spends:  # type: ignore # noqa
            pubkey, secretkey = self.get_keys(solution.coin.puzzle_hash)
            secretkey = BLSPrivateKey(secretkey)
            code_ = [puzzle, solution.solution]
            sexp = Program.to(code_)
            err, con, cost = conditions_for_solution(sexp)
            if not con:
                return
            conditions_dict = conditions_by_opcode(con)

            for _ in hash_key_pairs_for_conditions_dict(
                    conditions_dict, bytes(solution.coin)):
                signature = secretkey.sign(_.message_hash)
                sigs.append(signature)
        aggsig = BLSSignature.aggregate(sigs)
        solution_list: List[CoinSolution] = [
            CoinSolution(coin_solution.coin,
                         clvm.to_sexp_f([puzzle, coin_solution.solution]))
            for (puzzle, coin_solution) in spends
        ]
        spend_bundle = SpendBundle(solution_list, aggsig)
        return spend_bundle
Example #10
0
 def sign_transaction(self, spends: (Program, [CoinSolution])):
     sigs = []
     for puzzle, solution in spends:
         pubkey, secretkey = self.get_keys(solution.coin.puzzle_hash)
         code_ = [puzzle, solution.solution]
         sexp = clvm.to_sexp_f(code_)
         conditions_dict = conditions_by_opcode(
             conditions_for_solution(sexp))
         for _ in hash_key_pairs_for_conditions_dict(conditions_dict):
             signature = secretkey.sign(_.message_hash)
             sigs.append(signature)
     aggsig = BLSSignature.aggregate(sigs)
     solution_list = CoinSolutionList(
         [CoinSolution(coin_solution.coin, clvm.to_sexp_f([puzzle, coin_solution.solution])) for
          (puzzle, coin_solution) in spends])
     spend_bundle = SpendBundle(solution_list, aggsig)
     return spend_bundle
Example #11
0
    async def sign_transaction(
        self, spends: List[Tuple[Program, CoinSolution]]
    ) -> Optional[SpendBundle]:
        signatures = []
        for puzzle, solution in spends:
            # Get keys
            keys = await self.wallet_state_manager.get_keys(solution.coin.puzzle_hash)
            if not keys:
                self.log.error(
                    f"Sign transaction failed, No Keys for puzzlehash {solution.coin.puzzle_hash}"
                )
                return None

            pubkey, secretkey = keys
            secretkey = BLSPrivateKey(secretkey)
            code_ = [puzzle, solution.solution]
            sexp = clvm.to_sexp_f(code_)

            # Get AGGSIG conditions
            err, con, cost = conditions_for_solution(sexp)
            if err or not con:
                self.log.error(f"Sign transcation failed, con:{con}, error: {err}")
                return None

            conditions_dict = conditions_by_opcode(con)

            # Create signature
            for pk_message in hash_key_pairs_for_conditions_dict(
                conditions_dict, bytes(solution.coin)
            ):
                signature = secretkey.sign(pk_message.message_hash)
                signatures.append(signature)

        # Aggregate signatures
        aggsig = BLSSignature.aggregate(signatures)
        solution_list: List[CoinSolution] = [
            CoinSolution(
                coin_solution.coin, clvm.to_sexp_f([puzzle, coin_solution.solution])
            )
            for (puzzle, coin_solution) in spends
        ]
        spend_bundle = SpendBundle(solution_list, aggsig)

        return spend_bundle
Example #12
0
 def check_serde(self, s):
     v = to_sexp_f(s)
     b = v.as_bin()
     v1 = sexp_from_stream(io.BytesIO(b), to_sexp_f)
     if v != v1:
         print("%s: %d %s %s" % (v, len(b), b, v1))
         breakpoint()
         b = v.as_bin()
         v1 = sexp_from_stream(io.BytesIO(b), to_sexp_f)
     self.assertEqual(v, v1)
Example #13
0
def cc_generate_eve_spend(coin: Coin, full_puzzle: Program):
    solution = cc_make_eve_solution(coin.parent_coin_info, coin.puzzle_hash,
                                    coin.amount)
    list_of_solutions = [
        CoinSolution(
            coin,
            clvm.to_sexp_f([full_puzzle, solution]),
        )
    ]
    aggsig = BLSSignature.aggregate([])
    spend_bundle = SpendBundle(list_of_solutions, aggsig)
    return spend_bundle
Example #14
0
 def make_solution(self, primaries=[], min_time=0, me={}, consumed=[]):
     ret = []
     for primary in primaries:
         ret.append(make_create_coin_condition(
             primary['puzzlehash'], primary['amount']))
     for coin in consumed:
         ret.append(make_assert_coin_consumed_condition(coin))
     if min_time > 0:
         ret.append(make_assert_min_time_condition(min_time))
     if me:
         ret.append(make_assert_my_coin_id_condition(me['id']))
     return clvm.to_sexp_f([puzzle_for_conditions(ret), []])
Example #15
0
 def sign_clawback_transaction(self, spends: (Program, [CoinSolution]), clawback_pubkey):
     sigs = []
     for puzzle, solution in spends:
         pubkey, secretkey = self.get_keys_pk(clawback_pubkey)
         signature = secretkey.sign(
             ProgramHash(Program(solution.solution)))
         sigs.append(signature)
     aggsig = BLSSignature.aggregate(sigs)
     solution_list = CoinSolutionList(
         [CoinSolution(coin_solution.coin, clvm.to_sexp_f([puzzle, coin_solution.solution])) for
          (puzzle, coin_solution) in spends])
     spend_bundle = SpendBundle(solution_list, aggsig)
     return spend_bundle
Example #16
0
 def check_serde(self, s):
     v = to_sexp_f(s)
     b = v.as_bin()
     v1 = sexp_from_stream(io.BytesIO(b), to_sexp_f)
     if v != v1:
         print("%s: %d %s %s" % (v, len(b), b, v1))
         breakpoint()
         b = v.as_bin()
         v1 = sexp_from_stream(io.BytesIO(b), to_sexp_f)
     self.assertEqual(v, v1)
     # this copies the bytes that represent a single s-expression, just to
     # know where the message ends. It doesn't build a python representaion
     # of it
     buf = sexp_buffer_from_stream(io.BytesIO(b))
     self.assertEqual(buf, b)
Example #17
0
 def ap_sign_transaction(self, spends: (Program, [CoinSolution]), signatures_from_a):
     sigs = []
     for puzzle, solution in spends:
         pubkey, secretkey = self.get_keys(
             solution.coin.puzzle_hash, self.a_pubkey)
         signature = secretkey.sign(
             ProgramHash(Program(solution.solution)))
         sigs.append(signature)
     for s in signatures_from_a:
         sigs.append(s)
     aggsig = BLSSignature.aggregate(sigs)
     solution_list = CoinSolutionList(
         [CoinSolution(coin_solution.coin, clvm.to_sexp_f([puzzle, coin_solution.solution])) for
          (puzzle, coin_solution) in spends])
     spend_bundle = SpendBundle(solution_list, aggsig)
     return spend_bundle
def make_solution(parent,
                  puzzlehash,
                  value,
                  stake_factor,
                  primaries=[],
                  recovery=False):
    conditions = []
    for primary in primaries:
        conditions.append(
            make_create_coin_condition(primary['puzzlehash'],
                                       primary['amount']))
    conditions = [binutils.assemble("#q"), conditions]
    solution = [
        conditions, [], 1 if recovery else 0, parent, puzzlehash, value,
        math.floor(value * stake_factor)
    ]
    program = Program(to_sexp_f(solution))
    return program
Example #19
0
    def generate_recovery_to_escrow_transaction(self, coin, recovery_pubkey,
                                                pubkey, stake_factor,
                                                escrow_duration):
        solution = make_solution(coin.parent_coin_info,
                                 coin.puzzle_hash,
                                 coin.amount,
                                 stake_factor,
                                 recovery=True)
        puzzle = self.get_new_puzzle_with_params_and_root(
            recovery_pubkey, pubkey, stake_factor, escrow_duration)

        sexp = clvm.to_sexp_f([puzzle, solution])
        destination_puzzle_hash = get_destination_puzzle_hash(sexp)
        staked_amount = math.ceil(coin.amount * (stake_factor - 1))
        spends = self.generate_unsigned_transaction_without_recipient(
            staked_amount)
        spends.append((puzzle, CoinSolution(coin, solution)))
        return spends, destination_puzzle_hash, coin.amount + staked_amount
Example #20
0
    async def sign_clawback_transaction(self,
                                        spends: List[Tuple[Program,
                                                           CoinSolution]],
                                        clawback_pubkey):
        sigs = []
        for puzzle, solution in spends:
            pubkey, secretkey = await self.get_keys_pk(clawback_pubkey)
            signature = secretkey.sign(Program(solution.solution).get_hash())
            sigs.append(signature)
        aggsig = BLSSignature.aggregate(sigs)
        solution_list = []
        for puzzle, coin_solution in spends:
            solution_list.append(
                CoinSolution(coin_solution.coin,
                             clvm.to_sexp_f([puzzle, coin_solution.solution])))

        spend_bundle = SpendBundle(solution_list, aggsig)
        return spend_bundle
Example #21
0
    async def create_spend_bundle_relative_chia(
        self, chia_amount: int, exclude: List[Coin]
    ):
        list_of_solutions = []
        utxos = None

        # If we're losing value then get coins with at least that much value
        # If we're gaining value then our amount doesn't matter
        if chia_amount < 0:
            utxos = await self.select_coins(abs(chia_amount), exclude)
        else:
            utxos = await self.select_coins(0, exclude)

        if utxos is None:
            return None

        # Calculate output amount given sum of utxos
        spend_value = sum([coin.amount for coin in utxos])
        chia_amount = spend_value + chia_amount

        # Create coin solutions for each utxo
        output_created = None
        sigs: List[BLSSignature] = []
        for coin in utxos:
            pubkey, secretkey = await self.wallet_state_manager.get_keys(
                coin.puzzle_hash
            )
            puzzle = self.puzzle_for_pk(bytes(pubkey))
            if output_created is None:
                newpuzhash = await self.get_new_puzzlehash()
                primaries = [{"puzzlehash": newpuzhash, "amount": chia_amount}]
                solution = self.make_solution(primaries=primaries)
                output_created = coin
            else:
                solution = self.make_solution(consumed=[output_created.name()])
            list_of_solutions.append(
                CoinSolution(coin, clvm.to_sexp_f([puzzle, solution]))
            )
            new_sigs = await self.get_sigs_for_innerpuz_with_innersol(puzzle, solution)
            sigs = sigs + new_sigs

        aggsig = BLSSignature.aggregate(sigs)
        spend_bundle = SpendBundle(list_of_solutions, aggsig)
        return spend_bundle
Example #22
0
 def make_solution(
     self, primaries=None, min_time=0, me=None, consumed=None, fee=None
 ):
     condition_list = []
     if primaries:
         for primary in primaries:
             condition_list.append(
                 make_create_coin_condition(primary["puzzlehash"], primary["amount"])
             )
     if consumed:
         for coin in consumed:
             condition_list.append(make_assert_coin_consumed_condition(coin))
     if min_time > 0:
         condition_list.append(make_assert_time_exceeds_condition(min_time))
     if me:
         condition_list.append(make_assert_my_coin_id_condition(me["id"]))
     if fee:
         condition_list.append(make_assert_fee_condition(fee))
     return clvm.to_sexp_f([puzzle_for_conditions(condition_list), []])
Example #23
0
 def cp_sign_transaction(self,
                         spends: (Program, [CoinSolution]),
                         approval=None):
     sigs = []
     for puzzle, solution in spends:
         pubkey, secretkey = self.get_keys(solution.coin.puzzle_hash)
         signature = secretkey.sign(ProgramHash(Program(solution.solution)))
         sigs.append(signature)
     if approval is not None:
         app = BLSSignature(approval)
         sigs.append(app)
     aggsig = BLSSignature.aggregate(sigs)
     solution_list = CoinSolutionList([
         CoinSolution(coin_solution.coin,
                      clvm.to_sexp_f([puzzle, coin_solution.solution]))
         for (puzzle, coin_solution) in spends
     ])
     spend_bundle = SpendBundle(solution_list, aggsig)
     return spend_bundle
Example #24
0
 def test_zero(self):
     v = to_sexp_f(b"\x00")
     self.assertEqual(v.as_bin(), b"\x00")
Example #25
0
from clvm import run_program as default_run_program, to_sexp_f, KEYWORD_TO_ATOM  # noqa
from clvm.operators import OPERATOR_LOOKUP  # noqa
from clvm.EvalError import EvalError  # noqa
from clvm.casts import int_from_bytes, int_to_bytes  # noqa
from clvm.serialize import sexp_from_stream, sexp_to_stream  # noqa

SExp = to_sexp_f(1).__class__
BaseSExp = SExp


def run_program(
    program,
    args,
    quote_kw=KEYWORD_TO_ATOM["q"],
    args_kw=KEYWORD_TO_ATOM["a"],
    operator_lookup=OPERATOR_LOOKUP,
    max_cost=None,
    pre_eval_f=None,
):
    return default_run_program(
        program,
        args,
        quote_kw,
        args_kw,
        operator_lookup,
        max_cost,
        pre_eval_f=pre_eval_f,
    )
Example #26
0
def launch_tool(args, tool_name, default_stage=0):
    parser = argparse.ArgumentParser(description='Execute a clvm script.')
    parser.add_argument("-s",
                        "--stage",
                        type=stage_import,
                        help="stage number to include",
                        default=stage_import(default_stage))
    parser.add_argument(
        "-v",
        "--verbose",
        action="store_true",
        help="Display resolve of all reductions, for debugging")
    parser.add_argument("-c", "--cost", action="store_true", help="Show cost")
    parser.add_argument("-m", "--max-cost", type=int, help="Maximum cost")
    parser.add_argument("-d",
                        "--dump",
                        action="store_true",
                        help="dump hex version of final output")
    parser.add_argument("-y",
                        "--symbol-table",
                        type=pathlib.Path,
                        help=".SYM file generated by compiler")
    parser.add_argument(
        "-i",
        "--include",
        type=pathlib.Path,
        help="add a search path for included files",
        action="append",
        default=[],
    )
    parser.add_argument("path_or_code",
                        type=path_or_code,
                        help="path to clvm script, or literal script")
    parser.add_argument("args",
                        type=reader.read_ir,
                        help="arguments",
                        nargs="?",
                        default=reader.read_ir("()"))

    args = parser.parse_args(args=args[1:])

    if hasattr(args.stage, "run_program_for_search_paths"):
        run_program = args.stage.run_program_for_search_paths(args.include)
    else:
        run_program = args.stage.run_program

    src_text = args.path_or_code
    src_sexp = reader.read_ir(src_text)
    assembled_sexp = binutils.assemble_from_ir(src_sexp)

    pre_eval_f = None
    symbol_table = None

    log_entries = []

    if args.symbol_table:
        with open(args.symbol_table) as f:
            symbol_table = json.load(f)
        pre_eval_f = make_trace_pre_eval(log_entries, symbol_table)
    elif args.verbose:
        pre_eval_f = make_trace_pre_eval(log_entries)

    run_script = getattr(args.stage, tool_name)

    cost = 0
    try:
        output = "(didn't finish)"
        env = binutils.assemble_from_ir(args.args)
        input_sexp = to_sexp_f((assembled_sexp, env))
        cost, result = run_program(run_script,
                                   input_sexp,
                                   max_cost=args.max_cost,
                                   pre_eval_f=pre_eval_f)
        if args.cost:
            print("cost = %d" % cost)
        if args.dump:
            blob = as_bin(lambda f: sexp_to_stream(result, f))
            output = blob.hex()
        else:
            output = binutils.disassemble(result)
    except EvalError as ex:
        output = "FAIL: %s %s" % (ex, binutils.disassemble(ex._sexp))
        result = ex._sexp
        return -1
    except Exception as ex:
        result = src_sexp
        output = str(ex)
        raise
    finally:
        print(output)
        if args.verbose or symbol_table:
            print()
            trace_to_text(log_entries, binutils.disassemble, symbol_table)
Example #27
0
from clvm import to_sexp_f

from . import binutils

# monkey-patch SExp
SExp = to_sexp_f([]).__class__
SExp.__str__ = SExp.__repr__ = binutils.disassemble
Example #28
0
    async def respond_to_offer(self,
                               file_path: Path) -> Tuple[bool, Optional[str]]:
        has_wallets = await self.maybe_create_wallets_for_offer(file_path)
        if not has_wallets:
            return False, "Unknown Error"
        trade_offer_hex = file_path.read_text()
        trade_offer = SpendBundle.from_bytes(bytes.fromhex(trade_offer_hex))

        coinsols = []  # [] of CoinSolutions
        cc_coinsol_outamounts: Dict[bytes32, List[Tuple[Any, int]]] = dict()
        # Used for generating auditor solution, key is colour
        auditees: Dict[bytes32, List[Tuple[bytes32, bytes32, Any,
                                           int]]] = dict()
        aggsig = trade_offer.aggregated_signature
        cc_discrepancies: Dict[bytes32, int] = dict()
        chia_discrepancy = None
        wallets: Dict[bytes32, Any] = dict()  # colour to wallet dict

        for coinsol in trade_offer.coin_solutions:
            puzzle = coinsol.solution.first()
            solution = coinsol.solution.rest().first()

            # work out the deficits between coin amount and expected output for each
            if cc_wallet_puzzles.check_is_cc_puzzle(puzzle):
                parent_info = binutils.disassemble(
                    solution.rest().first()).split(" ")

                if len(parent_info) > 1:
                    # Calculate output amounts
                    colour = cc_wallet_puzzles.get_genesis_from_puzzle(
                        binutils.disassemble(puzzle))
                    if colour not in wallets:
                        wallets[
                            colour] = await self.wallet_state_manager.get_wallet_for_colour(
                                colour)
                    unspent = await self.wallet_state_manager.get_spendable_coins_for_wallet(
                        wallets[colour].wallet_info.id)
                    if coinsol.coin in [record.coin for record in unspent]:
                        return False, "can't respond to own offer"
                    innerpuzzlereveal = solution.rest().rest().rest().first()
                    innersol = solution.rest().rest().rest().rest().first()
                    out_amount = cc_wallet_puzzles.get_output_amount_for_puzzle_and_solution(
                        innerpuzzlereveal, innersol)

                    if colour in cc_discrepancies:
                        cc_discrepancies[
                            colour] += coinsol.coin.amount - out_amount
                    else:
                        cc_discrepancies[
                            colour] = coinsol.coin.amount - out_amount
                    # Store coinsol and output amount for later
                    if colour in cc_coinsol_outamounts:
                        cc_coinsol_outamounts[colour].append(
                            (coinsol, out_amount))
                    else:
                        cc_coinsol_outamounts[colour] = [(coinsol, out_amount)]

                    # auditees should be (primary_input, innerpuzhash, coin_amount, output_amount)
                    if colour in auditees:
                        auditees[colour].append((
                            coinsol.coin.parent_coin_info,
                            Program(innerpuzzlereveal).get_tree_hash(),
                            coinsol.coin.amount,
                            out_amount,
                        ))
                    else:
                        auditees[colour] = [(
                            coinsol.coin.parent_coin_info,
                            Program(innerpuzzlereveal).get_tree_hash(),
                            coinsol.coin.amount,
                            out_amount,
                        )]
                else:
                    coinsols.append(coinsol)
            else:
                # standard chia coin
                unspent = await self.wallet_state_manager.get_spendable_coins_for_wallet(
                    1)
                if coinsol.coin in [record.coin for record in unspent]:
                    return False, "can't respond to own offer"
                if chia_discrepancy is None:
                    chia_discrepancy = cc_wallet_puzzles.get_output_discrepancy_for_puzzle_and_solution(
                        coinsol.coin, puzzle, solution)
                else:
                    chia_discrepancy += cc_wallet_puzzles.get_output_discrepancy_for_puzzle_and_solution(
                        coinsol.coin, puzzle, solution)
                coinsols.append(coinsol)

        chia_spend_bundle: Optional[SpendBundle] = None
        if chia_discrepancy is not None:
            chia_spend_bundle = await self.wallet_state_manager.main_wallet.create_spend_bundle_relative_chia(
                chia_discrepancy, [])

        zero_spend_list: List[SpendBundle] = []
        # create coloured coin
        self.log.info(cc_discrepancies)
        for colour in cc_discrepancies.keys():
            if cc_discrepancies[colour] < 0:
                my_cc_spends = await wallets[colour].select_coins(
                    abs(cc_discrepancies[colour]))
            else:
                if chia_spend_bundle is None:
                    to_exclude: List = []
                else:
                    to_exclude = chia_spend_bundle.removals()
                my_cc_spends = await wallets[colour].select_coins(0)
                if my_cc_spends is None or my_cc_spends == set():
                    zero_spend_bundle: SpendBundle = await wallets[
                        colour].generate_zero_val_coin(False, to_exclude)
                    if zero_spend_bundle is None:
                        return (
                            False,
                            "unable to generate zero value coin, check you have chia available",
                        )
                    zero_spend_list.append(zero_spend_bundle)

                    additions = zero_spend_bundle.additions()
                    removals = zero_spend_bundle.removals()
                    my_cc_spends = set()
                    for add in additions:
                        if add not in removals and add.amount == 0:
                            my_cc_spends.add(add)

            if my_cc_spends == set() or my_cc_spends is None:
                return False, "insufficient funds"

            auditor = my_cc_spends.pop()
            auditor_inner_puzzle = await self.get_inner_puzzle_for_puzzle_hash(
                auditor.puzzle_hash)
            assert auditor_inner_puzzle is not None
            inner_hash = auditor_inner_puzzle.get_tree_hash()

            auditor_info = (
                auditor.parent_coin_info,
                inner_hash,
                auditor.amount,
            )
            auditor_formatted = (
                f"(0x{auditor.parent_coin_info} 0x{inner_hash} {auditor.amount})"
            )
            core = cc_wallet_puzzles.cc_make_core(colour)
            parent_info = await wallets[colour].get_parent_for_coin(auditor)

            for coloured_coin in my_cc_spends:
                inner_solution = self.wallet_state_manager.main_wallet.make_solution(
                    consumed=[auditor.name()])
                sig = await wallets[
                    colour].get_sigs_for_innerpuz_with_innersol(
                        await self.get_inner_puzzle_for_puzzle_hash(
                            coloured_coin.puzzle_hash),
                        inner_solution,
                    )
                aggsig = BLSSignature.aggregate(
                    [BLSSignature.aggregate(sig), aggsig])
                inner_puzzle = await self.get_inner_puzzle_for_puzzle_hash(
                    coloured_coin.puzzle_hash)
                assert inner_puzzle is not None
                # auditees should be (primary_input, innerpuzhash, coin_amount, output_amount)
                auditees[colour].append((
                    coloured_coin.parent_coin_info,
                    inner_puzzle.get_tree_hash(),
                    coloured_coin.amount,
                    0,
                ))

                solution = cc_wallet_puzzles.cc_make_solution(
                    core,
                    (
                        parent_info.parent_name,
                        parent_info.inner_puzzle_hash,
                        parent_info.amount,
                    ),
                    coloured_coin.amount,
                    binutils.disassemble(inner_puzzle),
                    binutils.disassemble(inner_solution),
                    auditor_info,
                    None,
                )
                coin_spend = CoinSolution(
                    coloured_coin,
                    clvm.to_sexp_f([
                        cc_wallet_puzzles.cc_make_puzzle(
                            inner_puzzle.get_tree_hash(),
                            core,
                        ),
                        solution,
                    ]),
                )
                coinsols.append(coin_spend)

                ephemeral = cc_wallet_puzzles.create_spend_for_ephemeral(
                    coloured_coin, auditor, 0)
                coinsols.append(ephemeral)

                auditor = cc_wallet_puzzles.create_spend_for_auditor(
                    auditor, coloured_coin)
                coinsols.append(auditor)

            # Tweak the offer's solution to include the new auditor
            for cc_coinsol_out in cc_coinsol_outamounts[colour]:
                cc_coinsol = cc_coinsol_out[0]
                offer_sol = binutils.disassemble(cc_coinsol.solution)
                # auditor is (primary_input, innerpuzzlehash, amount)
                offer_sol = offer_sol.replace(
                    "))) ()) () ()))", f"))) ()) {auditor_formatted} ()))")
                new_coinsol = CoinSolution(cc_coinsol.coin,
                                           binutils.assemble(offer_sol))
                coinsols.append(new_coinsol)

                eph = cc_wallet_puzzles.create_spend_for_ephemeral(
                    cc_coinsol.coin, auditor, cc_coinsol_out[1])
                coinsols.append(eph)

                aud = cc_wallet_puzzles.create_spend_for_auditor(
                    auditor, cc_coinsol.coin)
                coinsols.append(aud)

            # Finish the auditor CoinSolution with new information
            newinnerpuzhash = await wallets[colour].get_new_inner_hash()
            outputamount = (sum([c.amount for c in my_cc_spends]) +
                            cc_discrepancies[colour] + auditor.amount)
            innersol = self.wallet_state_manager.main_wallet.make_solution(
                primaries=[{
                    "puzzlehash": newinnerpuzhash,
                    "amount": outputamount
                }])
            parent_info = await wallets[colour].get_parent_for_coin(auditor)

            auditees[colour].append((
                auditor.parent_coin_info,
                auditor_inner_puzzle.get_tree_hash(),
                auditor.amount,
                outputamount,
            ))

            sig = await wallets[colour].get_sigs(auditor_inner_puzzle,
                                                 innersol)
            aggsig = BLSSignature.aggregate(
                [BLSSignature.aggregate(sig), aggsig])

            solution = cc_wallet_puzzles.cc_make_solution(
                core,
                (
                    parent_info.parent_name,
                    parent_info.inner_puzzle_hash,
                    parent_info.amount,
                ),
                auditor.amount,
                binutils.disassemble(auditor_inner_puzzle),
                binutils.disassemble(innersol),
                auditor_info,
                auditees[colour],
            )

            cs = CoinSolution(
                auditor,
                clvm.to_sexp_f([
                    cc_wallet_puzzles.cc_make_puzzle(
                        auditor_inner_puzzle.get_tree_hash(), core),
                    solution,
                ]),
            )
            coinsols.append(cs)

            cs_eph = create_spend_for_ephemeral(auditor, auditor, outputamount)
            coinsols.append(cs_eph)

            cs_aud = create_spend_for_auditor(auditor, auditor)
            coinsols.append(cs_aud)

        spend_bundle = SpendBundle(coinsols, aggsig)
        my_tx_records = []

        if zero_spend_list is not None:
            zero_spend_list.append(spend_bundle)
            spend_bundle = SpendBundle.aggregate(zero_spend_list)

        # Add transaction history hor this trade
        if chia_spend_bundle is not None:
            spend_bundle = SpendBundle.aggregate(
                [spend_bundle, chia_spend_bundle])
            if chia_discrepancy < 0:
                tx_record = TransactionRecord(
                    confirmed_at_index=uint32(0),
                    created_at_time=uint64(int(time.time())),
                    to_puzzle_hash=token_bytes(),
                    amount=uint64(abs(chia_discrepancy)),
                    fee_amount=uint64(0),
                    incoming=False,
                    confirmed=False,
                    sent=uint32(10),
                    spend_bundle=chia_spend_bundle,
                    additions=chia_spend_bundle.additions(),
                    removals=chia_spend_bundle.removals(),
                    wallet_id=uint32(1),
                    sent_to=[],
                )
            else:
                tx_record = TransactionRecord(
                    confirmed_at_index=uint32(0),
                    created_at_time=uint64(int(time.time())),
                    to_puzzle_hash=token_bytes(),
                    amount=uint64(abs(chia_discrepancy)),
                    fee_amount=uint64(0),
                    incoming=True,
                    confirmed=False,
                    sent=uint32(10),
                    spend_bundle=chia_spend_bundle,
                    additions=chia_spend_bundle.additions(),
                    removals=chia_spend_bundle.removals(),
                    wallet_id=uint32(1),
                    sent_to=[],
                )
            my_tx_records.append(tx_record)

        for colour, amount in cc_discrepancies.items():
            wallet = wallets[colour]
            if chia_discrepancy > 0:
                tx_record = TransactionRecord(
                    confirmed_at_index=uint32(0),
                    created_at_time=uint64(int(time.time())),
                    to_puzzle_hash=token_bytes(),
                    amount=uint64(abs(amount)),
                    fee_amount=uint64(0),
                    incoming=False,
                    confirmed=False,
                    sent=uint32(10),
                    spend_bundle=spend_bundle,
                    additions=spend_bundle.additions(),
                    removals=spend_bundle.removals(),
                    wallet_id=wallet.wallet_info.id,
                    sent_to=[],
                )
            else:
                tx_record = TransactionRecord(
                    confirmed_at_index=uint32(0),
                    created_at_time=uint64(int(time.time())),
                    to_puzzle_hash=token_bytes(),
                    amount=uint64(abs(amount)),
                    fee_amount=uint64(0),
                    incoming=True,
                    confirmed=False,
                    sent=uint32(10),
                    spend_bundle=spend_bundle,
                    additions=spend_bundle.additions(),
                    removals=spend_bundle.removals(),
                    wallet_id=wallet.wallet_info.id,
                    sent_to=[],
                )
            my_tx_records.append(tx_record)

        tx_record = TransactionRecord(
            confirmed_at_index=uint32(0),
            created_at_time=uint64(int(time.time())),
            to_puzzle_hash=token_bytes(),
            amount=uint64(0),
            fee_amount=uint64(0),
            incoming=False,
            confirmed=False,
            sent=uint32(0),
            spend_bundle=spend_bundle,
            additions=spend_bundle.additions(),
            removals=spend_bundle.removals(),
            wallet_id=uint32(0),
            sent_to=[],
        )

        await self.wallet_state_manager.add_pending_transaction(tx_record)
        for tx in my_tx_records:
            await self.wallet_state_manager.add_transaction(tx)

        return True, None
Example #29
0
def default_macro_lookup(eval):
    global DEFAULT_MACRO_LOOKUP
    if DEFAULT_MACRO_LOOKUP is None:
        DEFAULT_MACRO_LOOKUP = to_sexp_f([])
        DEFAULT_MACRO_LOOKUP = build_default_macro_lookup(eval)
    return DEFAULT_MACRO_LOOKUP
Example #30
0
 def test_empty(self):
     v = to_sexp_f(b"")
     self.assertEqual(v.as_bin(), b"\x80")