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,
            Program.to([full_puzzle, solution]),
        )
    ]
    aggsig = AugSchemeMPL.aggregate([])
    spend_bundle = SpendBundle(list_of_solutions, aggsig)
    return spend_bundle
def solution_with_hidden_puzzle(
    hidden_public_key: G1Element,
    hidden_puzzle: Program,
    solution_to_hidden_puzzle: Program,
) -> Program:
    synthetic_public_key = calculate_synthetic_public_key(
        hidden_public_key, hidden_puzzle
    )
    puzzle = puzzle_for_synthetic_public_key(synthetic_public_key)
    return Program.to(
        [puzzle, [hidden_public_key, hidden_puzzle, solution_to_hidden_puzzle]]
    )
示例#3
0
def best_solution_program(bundle: SpendBundle) -> Program:
    """
    This could potentially do a lot of clever and complicated compression
    optimizations in conjunction with choosing the set of SpendBundles to include.

    For now, we just quote the solutions we know.
    """
    r = []
    for coin_solution in bundle.coin_solutions:
        entry = [coin_solution.coin.name(), coin_solution.solution]
        r.append(entry)
    return Program.to([binutils.assemble("#q"), r])
示例#4
0
    async def create_spend_bundle_relative_amount(self, cc_amount, zero_coin: Coin = None) -> Optional[SpendBundle]:
        # If we're losing value then get coloured coins with at least that much value
        # If we're gaining value then our amount doesn't matter
        if cc_amount < 0:
            cc_spends = await self.select_coins(abs(cc_amount))
        else:
            if zero_coin is None:
                return None
            cc_spends = set()
            cc_spends.add(zero_coin)

        if cc_spends is None:
            return None

        # Calculate output amount given relative difference and sum of actual values
        spend_value = sum([coin.amount for coin in cc_spends])
        cc_amount = spend_value + cc_amount

        # Loop through coins and create solution for innerpuzzle
        list_of_solutions = []
        output_created = None
        sigs: List[G2Element] = []
        for coin in cc_spends:
            if output_created is None:
                newinnerpuzhash = await self.get_new_inner_hash()
                innersol = self.standard_wallet.make_solution(
                    primaries=[{"puzzlehash": newinnerpuzhash, "amount": cc_amount}]
                )
                output_created = coin
            else:
                innersol = self.standard_wallet.make_solution(consumed=[output_created.name()])
            innerpuz: Program = await self.inner_puzzle_for_cc_puzhash(coin.puzzle_hash)
            sigs = sigs + await self.get_sigs(innerpuz, innersol, coin.name())
            lineage_proof = await self.get_lineage_proof_for_coin(coin)
            puzzle_reveal = cc_puzzle_for_inner_puzzle(CC_MOD, self.cc_info.my_genesis_checker, innerpuz)
            # Use coin info to create solution and add coin and solution to list of CoinSolutions
            solution = [
                innersol,
                coin.as_list(),
                lineage_proof,
                None,
                None,
                None,
                None,
                None,
            ]
            full_solution = Program.to([puzzle_reveal, solution])

            list_of_solutions.append(CoinSolution(coin, full_solution))

        aggsig = AugSchemeMPL.aggregate(sigs)
        return SpendBundle(list_of_solutions, aggsig)
示例#5
0
 async def get_sigs(self, innerpuz: Program, innersol: Program, coin_name) -> List[G2Element]:
     puzzle_hash = innerpuz.get_tree_hash()
     pubkey, private = await self.wallet_state_manager.get_keys(puzzle_hash)
     synthetic_secret_key = calculate_synthetic_secret_key(private, DEFAULT_HIDDEN_PUZZLE_HASH)
     sigs: List[G2Element] = []
     code_ = [innerpuz, innersol]
     sexp = Program.to(code_)
     error, conditions, cost = conditions_dict_for_solution(sexp)
     if conditions is not None:
         for _, msg in pkm_pairs_for_conditions_dict(conditions, coin_name):
             signature = AugSchemeMPL.sign(synthetic_secret_key, msg)
             sigs.append(signature)
     return sigs
示例#6
0
def conditions_for_solution(
    solution_program, run_program=clvm.run_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)
        error, result = parse_sexp_to_conditions(r)
        return error, result, cost
    except EvalError:
        return Err.SEXP_ERROR, None, uint64(0)
示例#7
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,
            ],
        )
    )
示例#8
0
 async def get_sigs(self, innerpuz: Program,
                    innersol: Program) -> List[G2Element]:
     puzzle_hash = innerpuz.get_tree_hash()
     pubkey, private = await self.wallet_state_manager.get_keys(puzzle_hash)
     sigs: List[G2Element] = []
     code_ = [innerpuz, innersol]
     sexp = Program.to(code_)
     error, conditions, cost = conditions_dict_for_solution(sexp)
     if conditions is not None:
         for _, msg in pkm_pairs_for_conditions_dict(conditions):
             signature = AugSchemeMPL.sign(private, msg)
             sigs.append(signature)
     return sigs
示例#9
0
 async def get_sigs_for_innerpuz_with_innersol(
         self, innerpuz: Program, innersol: Program) -> List[BLSSignature]:
     puzzle_hash = innerpuz.get_tree_hash()
     pubkey, private = await self.wallet_state_manager.get_keys(puzzle_hash)
     private = BLSPrivateKey(private)
     sigs: List[BLSSignature] = []
     code_ = [innerpuz, innersol]
     sexp = Program.to(code_)
     error, conditions, cost = conditions_dict_for_solution(sexp)
     if conditions is not None:
         for _ in hash_key_pairs_for_conditions_dict(conditions):
             signature = private.sign(_.message_hash)
             sigs.append(signature)
     return sigs
示例#10
0
def issue_cc_from_farmed_coin(
    mod_code: Program,
    coin_checker_for_farmed_coin,
    block_id: int,
    inner_puzzle_hash: bytes32,
    amount: int,
) -> Tuple[Program, SpendBundle]:
    """
    This is an example of how to issue a cc.
    """
    # get a farmed coin

    farmed_puzzle = ANYONE_CAN_SPEND_PUZZLE
    farmed_puzzle_hash = farmed_puzzle.get_tree_hash()

    # mint a cc

    farmed_coin = generate_farmed_coin(block_id,
                                       farmed_puzzle_hash,
                                       amount=uint64(amount))
    genesis_coin_checker = coin_checker_for_farmed_coin(farmed_coin)

    minted_cc_puzzle_hash = cc_puzzle_hash_for_inner_puzzle_hash(
        mod_code, genesis_coin_checker, inner_puzzle_hash)

    output_conditions = [[
        ConditionOpcode.CREATE_COIN, minted_cc_puzzle_hash, farmed_coin.amount
    ]]

    # for this very simple puzzle, the solution is simply the output conditions
    # this is just a coincidence... for more complicated puzzles, you'll likely have to do some real work

    solution = Program.to(output_conditions)
    coin_solution = CoinSolution(farmed_coin,
                                 Program.to([farmed_puzzle, solution]))
    spend_bundle = SpendBundle([coin_solution], NULL_SIGNATURE)
    return genesis_coin_checker, spend_bundle
示例#11
0
    async def generate_unsigned_transaction(
        self,
        amount: uint64,
        newpuzzlehash: bytes32,
        fee: uint64 = uint64(0),
        origin_id: bytes32 = None,
        coins: Set[Coin] = None,
    ) -> List[CoinSolution]:
        """
        Generates a unsigned transaction in form of List(Puzzle, Solutions)
        """
        if coins is None:
            coins = await self.select_coins(amount + fee)
        assert len(coins) > 0

        self.log.info(f"coins is not None {coins}")
        spend_value = sum([coin.amount for coin in coins])
        change = spend_value - amount - fee

        spends: List[CoinSolution] = []
        output_created = False

        for coin in coins:
            self.log.info(f"coin from coins {coin}")
            puzzle: Program = await self.puzzle_for_puzzle_hash(
                coin.puzzle_hash)

            # Only one coin creates outputs
            if not output_created and origin_id in (None, coin.name()):
                primaries = [{"puzzlehash": newpuzzlehash, "amount": amount}]
                if change > 0:
                    changepuzzlehash = await self.get_new_puzzlehash()
                    primaries.append({
                        "puzzlehash": changepuzzlehash,
                        "amount": change
                    })

                solution = self.make_solution(primaries=primaries, fee=fee)
                output_created = True
            else:
                solution = self.make_solution()

            puzzle_solution_pair = Program.to([puzzle, solution])
            spends.append(CoinSolution(coin, puzzle_solution_pair))

        self.log.info(f"Spends is {spends}")
        return spends
示例#12
0
    async def test_agg_sig_condition(self, two_nodes):
        num_blocks = 2
        wallet_a = bt.get_pool_wallet_tool()
        wallet_receiver = WalletTool()
        receiver_puzzlehash = wallet_receiver.get_new_puzzlehash()

        blocks = bt.get_consecutive_blocks(test_constants, num_blocks, [], 10,
                                           b"")
        full_node_1, full_node_2, server_1, server_2 = two_nodes

        block = blocks[1]
        async for _ in full_node_1.respond_block(
                full_node_protocol.RespondBlock(block)):
            pass

        unsigned: List[Tuple[
            Program, CoinSolution]] = wallet_a.generate_unsigned_transaction(
                1000, receiver_puzzlehash, block.get_coinbase(), {}, 0)
        assert len(unsigned) == 1

        puzzle, solution = unsigned[0]
        code_ = [puzzle, solution.solution]
        sexp = Program.to(code_)

        err, con, cost = conditions_for_solution(sexp)
        assert con is not None

        conditions_dict = conditions_by_opcode(con)
        pkm_pairs = pkm_pairs_for_conditions_dict(conditions_dict,
                                                  solution.coin.name())
        assert len(pkm_pairs) == 1

        assert pkm_pairs[0][1] == solution.solution.first().get_tree_hash()

        spend_bundle = wallet_a.sign_transaction(unsigned)
        assert spend_bundle is not None

        tx: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(
            spend_bundle)
        async for _ in full_node_1.respond_transaction(tx):
            outbound: OutboundMessage = _
            # Maybe transaction means that it's accepted in mempool
            assert outbound.message.function == "new_transaction"

        sb = full_node_1.mempool_manager.get_spendbundle(spend_bundle.name())
        assert sb is spend_bundle
示例#13
0
    async def rl_sign_transaction(
            self, spends: List[Tuple[Program, CoinSolution]]) -> SpendBundle:
        sigs = []
        for puzzle, solution in spends:
            pubkey, secretkey = await self.get_keys(solution.coin.puzzle_hash)
            signature = AugSchemeMPL.sign(
                secretkey,
                Program(solution.solution).get_tree_hash())
            sigs.append(signature)

        aggsig = AugSchemeMPL.aggregate(sigs)

        solution_list: List[CoinSolution] = []
        for puzzle, coin_solution in spends:
            solution_list.append(
                CoinSolution(coin_solution.coin,
                             Program.to([puzzle, coin_solution.solution])))

        return SpendBundle(solution_list, aggsig)
示例#14
0
    async def coin_added(self, coin: Coin, height: int, header_hash: bytes32,
                         removals: List[Coin]):
        """ Notification from wallet state manager that wallet has been received. """
        self.log.info(f"CC wallet has been notified that {coin} was added")

        search_for_parent: bool = True

        inner_puzzle = await self.inner_puzzle_for_cc_puzhash(coin.puzzle_hash)
        lineage_proof = Program.to((
            1,
            [
                coin.parent_coin_info,
                inner_puzzle.get_tree_hash(),
                coin.amount,
            ],
        ))
        await self.add_lineage(coin.name(), lineage_proof)

        for name, lineage_proofs in self.cc_info.lineage_proofs:
            if coin.parent_coin_info == name:
                search_for_parent = False
                break

        if search_for_parent:
            data: Dict[str, Any] = {
                "data": {
                    "action_data": {
                        "api_name": "request_generator",
                        "height": height,
                        "header_hash": header_hash,
                    }
                }
            }

            data_str = dict_to_json_str(data)
            await self.wallet_state_manager.create_action(
                name="request_generator",
                wallet_id=self.wallet_info.id,
                type=self.wallet_info.type,
                callback="generator_received",
                done=False,
                data=data_str,
            )
示例#15
0
    async def create_spend_bundle_relative_chia(
            self, chia_amount: int,
            exclude: List[Coin]) -> Optional[SpendBundle]:
        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[G2Element] = []
        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, Program.to([puzzle, solution])))
            new_sigs = await self.get_sigs_for_innerpuz_with_innersol(
                puzzle, solution)
            sigs = sigs + new_sigs

        aggsig = AugSchemeMPL.aggregate(sigs)
        spend_bundle = SpendBundle(list_of_solutions, aggsig)
        return spend_bundle
示例#16
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 = AugSchemeMPL.aggregate(sigs)
        solution_list = []
        for puzzle, coin_solution in spends:
            solution_list.append(
                CoinSolution(
                    coin_solution.coin, Program.to([puzzle, coin_solution.solution])
                )
            )

        spend_bundle = SpendBundle(solution_list, aggsig)
        return spend_bundle
示例#17
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 Program.to([puzzle_for_conditions(condition_list), []])
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)
    """
    opcode_myid = hexlify(ConditionOpcode.ASSERT_MY_COIN_ID).decode("ascii")
    opcode_consumed = hexlify(ConditionOpcode.ASSERT_COIN_CONSUMED).decode("ascii")
    me_is_my_id = make_list(hexstr(opcode_myid), args(0))

    # lock_puzzle is the hash of '(r (c (q "merge in ID") (q ())))'
    lock_puzzle = sha256tree(
        make_list(
            quote(7),
            make_list(quote(5), make_list(quote(1), args(0)), quote(quote(sexp()))),
        )
    )
    parent_coin_id = sha256(args(1), hexstr(wallet_puzzle), args(2))
    input_of_lock = make_list(hexstr(opcode_consumed), sha256(parent_coin_id, lock_puzzle, quote(0)))
    puz = make_list(me_is_my_id, input_of_lock)

    return Program.to(binutils.assemble(puz))
示例#19
0
    def generate_unsigned_transaction(
        self,
        amount: uint64,
        newpuzzlehash: bytes32,
        coin: Coin,
        condition_dic: Dict[ConditionOpcode, List[ConditionVarPair]],
        fee: int = 0,
        secretkey=None,
    ) -> List[CoinSolution]:
        spends = []
        spend_value = coin.amount
        puzzle_hash = coin.puzzle_hash
        if secretkey is None:
            secretkey = self.get_private_key_for_puzzle_hash(puzzle_hash)
        pubkey = secretkey.get_g1()
        puzzle = puzzle_for_pk(bytes(pubkey))
        if ConditionOpcode.CREATE_COIN not in condition_dic:
            condition_dic[ConditionOpcode.CREATE_COIN] = []

        output = ConditionVarPair(ConditionOpcode.CREATE_COIN, newpuzzlehash,
                                  int_to_bytes(amount))
        condition_dic[output.opcode].append(output)
        amount_total = sum(
            int_from_bytes(cvp.var2)
            for cvp in condition_dic[ConditionOpcode.CREATE_COIN])
        change = spend_value - amount_total - fee
        if change > 0:
            changepuzzlehash = self.get_new_puzzlehash()
            change_output = ConditionVarPair(ConditionOpcode.CREATE_COIN,
                                             changepuzzlehash,
                                             int_to_bytes(change))
            condition_dic[output.opcode].append(change_output)
            solution = self.make_solution(condition_dic)
        else:
            solution = self.make_solution(condition_dic)
        puzzle_solution_pair = Program.to([puzzle, solution])

        spends.append(CoinSolution(coin, puzzle_solution_pair))
        return spends
示例#20
0
    async def generate_new_coloured_coin(self, amount: uint64) -> SpendBundle:
        coins = await self.standard_wallet.select_coins(amount)

        origin = coins.copy().pop()
        origin_id = origin.name()

        cc_inner_hash = await self.get_new_inner_hash()
        await self.add_lineage(origin_id, Program.to((0, [origin.as_list(), 0])))
        genesis_coin_checker = create_genesis_or_zero_coin_checker(origin_id)

        minted_cc_puzzle_hash = cc_puzzle_hash_for_inner_puzzle_hash(CC_MOD, genesis_coin_checker, cc_inner_hash)

        tx_record: TransactionRecord = await self.standard_wallet.generate_signed_transaction(
            amount, minted_cc_puzzle_hash, uint64(0), origin_id, coins
        )
        assert tx_record.spend_bundle is not None

        lineage_proof: Optional[Program] = lineage_proof_for_genesis(origin)
        lineage_proofs = [(origin_id, lineage_proof)]
        cc_info: CCInfo = CCInfo(genesis_coin_checker, lineage_proofs)
        await self.save_info(cc_info)
        return tx_record.spend_bundle
    def make_solution(self, condition_dic: Dict[ConditionOpcode, List[ConditionVarPair]]) -> Program:
        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.vars[0], cvp.vars[1]))
                if cvp.opcode == ConditionOpcode.AGG_SIG:
                    ret.append(make_assert_aggsig_condition(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.ASSERT_COIN_CONSUMED:
                    ret.append(make_assert_coin_consumed_condition(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.ASSERT_TIME_EXCEEDS:
                    ret.append(make_assert_time_exceeds_condition(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.ASSERT_MY_COIN_ID:
                    ret.append(make_assert_my_coin_id_condition(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.ASSERT_BLOCK_INDEX_EXCEEDS:
                    ret.append(make_assert_block_index_exceeds_condition(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.ASSERT_BLOCK_AGE_EXCEEDS:
                    ret.append(make_assert_block_age_exceeds_condition(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.ASSERT_FEE:
                    ret.append(make_assert_fee_condition(cvp.vars[0]))

        return solution_for_conditions(Program.to(ret))
示例#22
0
    async def create_spend_bundle_relative_chia(
        self, chia_amount: int, exclude: List[Coin]
    ) -> SpendBundle:
        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)

        assert len(utxos) > 0

        # 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
        for coin in utxos:
            puzzle = await self.puzzle_for_puzzle_hash(coin.puzzle_hash)
            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, Program.to([puzzle, solution])))

        await self.hack_populate_secret_keys_for_coin_solutions(list_of_solutions)
        spend_bundle = await sign_coin_solutions(
            list_of_solutions, self.secret_key_store.secret_key_for_public_key
        )
        return spend_bundle
示例#23
0
    async def create_spend_bundle_relative_amount(self,
                                                  cc_amount,
                                                  zero_coin: Coin = None):
        # If we're losing value then get coloured coins with at least that much value
        # If we're gaining value then our amount doesn't matter
        if cc_amount < 0:
            cc_spends = await self.select_coins(abs(cc_amount))
        else:
            if zero_coin is None:
                return None
            cc_spends = set()
            cc_spends.add(zero_coin)

        if cc_spends is None:
            return None

        # Calculate output amount given relative difference and sum of actual values
        spend_value = sum([coin.amount for coin in cc_spends])
        cc_amount = spend_value + cc_amount

        # Loop through coins and create solution for innerpuzzle
        list_of_solutions = []
        output_created = None
        sigs: List[G2Element] = []
        for coin in cc_spends:
            if output_created is None:
                newinnerpuzhash = await self.get_new_inner_hash()
                innersol = self.standard_wallet.make_solution(
                    primaries=[{
                        "puzzlehash": newinnerpuzhash,
                        "amount": cc_amount
                    }])
                output_created = coin
            else:
                innersol = self.standard_wallet.make_solution()
            innerpuz: Program = await self.inner_puzzle_for_cc_puzzle(
                coin.puzzle_hash)

            parent_info = await self.get_parent_for_coin(coin)
            assert parent_info is not None
            assert self.cc_info.my_core is not None
            # Use coin info to create solution and add coin and solution to list of CoinSolutions
            solution = cc_wallet_puzzles.cc_make_solution(
                self.cc_info.my_core,
                (
                    parent_info.parent_name,
                    parent_info.inner_puzzle_hash,
                    parent_info.amount,
                ),
                coin.amount,
                binutils.disassemble(innerpuz),
                binutils.disassemble(innersol),
                None,
                None,
            )
            list_of_solutions.append(
                CoinSolution(
                    coin,
                    Program.to([
                        cc_wallet_puzzles.cc_make_puzzle(
                            innerpuz.get_tree_hash(), self.cc_info.my_core),
                        solution,
                    ]),
                ))
            sigs = sigs + await self.get_sigs(innerpuz, innersol)

        aggsig = AugSchemeMPL.aggregate(sigs)
        spend_bundle = SpendBundle(list_of_solutions, aggsig)
        return spend_bundle
示例#24
0
    async def generate_signed_transaction(
        self,
        amount: uint64,
        to_address: bytes32,
        fee: uint64 = uint64(0),
        origin_id: bytes32 = None,
        coins: Set[Coin] = None,
    ) -> Optional[TransactionRecord]:
        sigs: List[G2Element] = []

        # Get coins and calculate amount of change required
        if coins is None:
            selected_coins: Optional[Set[Coin]] = await self.select_coins(
                amount)
        else:
            selected_coins = coins
        if selected_coins is None:
            return None

        total_amount = sum([x.amount for x in selected_coins])
        change = total_amount - amount

        # first coin becomes the auditor special case
        auditor = selected_coins.pop()
        puzzle_hash = auditor.puzzle_hash
        inner_puzzle: Program = await self.inner_puzzle_for_cc_puzzle(
            puzzle_hash)

        auditor_info = (
            auditor.parent_coin_info,
            inner_puzzle.get_tree_hash(),
            auditor.amount,
        )
        list_of_solutions = []

        # auditees should be (primary_input, innerpuzhash, coin_amount, output_amount)
        auditees = [(
            auditor.parent_coin_info,
            inner_puzzle.get_tree_hash(),
            auditor.amount,
            total_amount,
        )]
        for coin in selected_coins:
            coin_inner_puzzle: Program = await self.inner_puzzle_for_cc_puzzle(
                coin.puzzle_hash)
            auditees.append((
                coin.parent_coin_info,
                coin_inner_puzzle[coin],
                coin.amount,
                0,
            ))

        primaries = [{"puzzlehash": to_address, "amount": amount}]
        if change > 0:
            changepuzzlehash = await self.get_new_inner_hash()
            primaries.append({
                "puzzlehash": changepuzzlehash,
                "amount": change
            })

        innersol = self.standard_wallet.make_solution(primaries=primaries)
        sigs = sigs + await self.get_sigs(inner_puzzle, innersol)
        parent_info = await self.get_parent_for_coin(auditor)
        assert parent_info is not None
        assert self.cc_info.my_core is not None

        solution = cc_wallet_puzzles.cc_make_solution(
            self.cc_info.my_core,
            (
                parent_info.parent_name,
                parent_info.inner_puzzle_hash,
                parent_info.amount,
            ),
            auditor.amount,
            binutils.disassemble(inner_puzzle),
            binutils.disassemble(innersol),
            auditor_info,
            auditees,
            False,
        )

        main_coin_solution = CoinSolution(
            auditor,
            Program.to([
                cc_wallet_puzzles.cc_make_puzzle(
                    inner_puzzle.get_tree_hash(),
                    self.cc_info.my_core,
                ),
                solution,
            ]),
        )
        list_of_solutions.append(main_coin_solution)
        # main = SpendBundle([main_coin_solution], ZERO96)

        ephemeral_coin_solution = create_spend_for_ephemeral(
            auditor, auditor, total_amount)
        list_of_solutions.append(ephemeral_coin_solution)
        # eph = SpendBundle([ephemeral_coin_solution], ZERO96)

        auditor_coin_colution = create_spend_for_auditor(auditor, auditor)
        list_of_solutions.append(auditor_coin_colution)
        # aud = SpendBundle([auditor_coin_colution], ZERO96)

        # loop through remaining spends, treating them as aggregatees
        for coin in selected_coins:
            coin_inner_puzzle = await self.inner_puzzle_for_cc_puzzle(
                coin.puzzle_hash)
            innersol = self.standard_wallet.make_solution()
            parent_info = await self.get_parent_for_coin(coin)
            assert parent_info is not None
            sigs = sigs + await self.get_sigs(coin_inner_puzzle, innersol)

            solution = cc_wallet_puzzles.cc_make_solution(
                self.cc_info.my_core,
                (
                    parent_info.parent_name,
                    parent_info.inner_puzzle_hash,
                    parent_info.amount,
                ),
                coin.amount,
                binutils.disassemble(coin_inner_puzzle),
                binutils.disassemble(innersol),
                auditor_info,
                None,
            )
            list_of_solutions.append(
                CoinSolution(
                    coin,
                    Program.to([
                        cc_wallet_puzzles.cc_make_puzzle(
                            coin_inner_puzzle.get_tree_hash(),
                            self.cc_info.my_core,
                        ),
                        solution,
                    ]),
                ))
            list_of_solutions.append(
                create_spend_for_ephemeral(coin, auditor, 0))
            list_of_solutions.append(create_spend_for_auditor(auditor, coin))

        aggsig = AugSchemeMPL.aggregate(sigs)
        spend_bundle = SpendBundle(list_of_solutions, aggsig)

        tx_record = TransactionRecord(
            confirmed_at_index=uint32(0),
            created_at_time=uint64(int(time.time())),
            to_puzzle_hash=to_address,
            amount=uint64(amount),
            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=self.wallet_info.id,
            sent_to=[],
            trade_id=None,
        )

        return tx_record
def cc_make_puzzle(innerpuzhash, core):
    # Puzzle runs the core, but stores innerpuzhash commitment
    puzstring = f"(r (c (q 0x{innerpuzhash}) ((c (q {core}) (a)))))"
    result = Program.to(binutils.assemble(puzstring))
    return result
示例#26
0
def solution_for_contract(contract, puzzle_parameters, solution_parameters):
    cost, r = run_program(
        contract, Program.to((1, (puzzle_parameters, solution_parameters))))
    return r
示例#27
0
def puzzle_for_contract(contract, puzzle_parameters):
    env = Program.to([]).cons(Program.to(puzzle_parameters))
    cost, r = run_program(contract, env)
    return Program.to(r)
def solution_for_delegated_puzzle(delegated_puzzle: Program,
                                  delegated_solution: Program) -> Program:
    return Program.to([delegated_puzzle, delegated_solution])
def solution_for_conditions(conditions) -> Program:
    delegated_puzzle = p2_conditions.puzzle_for_conditions(conditions)
    return solution_for_delegated_puzzle(delegated_puzzle, Program.to(0))
示例#30
0
def test_spend_through_n(mod_code, coin_checker_for_farmed_coin, n):
    """
    Test to spend ccs from a farmed coin to a cc genesis coin, then to N outputs,
    then joining back down to two outputs.
    """

    ################################

    # spend from a farmed coin to a cc genesis coin

    # get a farmed coin

    eve_inner_puzzle = ANYONE_CAN_SPEND_PUZZLE
    eve_inner_puzzle_hash = eve_inner_puzzle.get_tree_hash()

    # generate output values [0x100, 0x200, ...]

    output_values = [0x100 + 0x100 * _ for _ in range(n)]
    total_minted = sum(output_values)

    genesis_coin_checker, spend_bundle = issue_cc_from_farmed_coin(
        mod_code, coin_checker_for_farmed_coin, 1, eve_inner_puzzle_hash,
        total_minted)

    # hack the wrapped puzzles into the PUZZLE_TABLE DB

    puzzles_for_db = [
        cc_puzzle_for_inner_puzzle(mod_code, genesis_coin_checker,
                                   eve_inner_puzzle)
    ]
    add_puzzles_to_puzzle_preimage_db(puzzles_for_db)

    debug_spend_bundle(spend_bundle)

    ################################

    # collect up the spendable coins

    spendable_cc_list = []
    for coin_solution in spend_bundle.coin_solutions:
        spendable_cc_list.extend(
            spendable_cc_list_from_coin_solution(coin_solution,
                                                 hash_to_puzzle_f))

    # now spend the genesis coin cc to N outputs

    output_conditions = solution_for_pay_to_any([(eve_inner_puzzle_hash, _)
                                                 for _ in output_values])
    inner_puzzle_solution = Program.to(output_conditions)

    spend_bundle = spend_bundle_for_spendable_ccs(
        mod_code,
        genesis_coin_checker,
        spendable_cc_list,
        [inner_puzzle_solution],
    )

    debug_spend_bundle(spend_bundle)

    ################################

    # collect up the spendable coins

    spendable_cc_list = []
    for coin_solution in spend_bundle.coin_solutions:
        spendable_cc_list.extend(
            spendable_cc_list_from_coin_solution(coin_solution,
                                                 hash_to_puzzle_f))

    # now spend N inputs to two outputs

    output_amounts = ([0] * (n - 2)) + [0x1, total_minted - 1]

    inner_solutions = [
        solution_for_pay_to_any([(eve_inner_puzzle_hash,
                                  amount)] if amount else [])
        for amount in output_amounts
    ]

    spend_bundle = spend_bundle_for_spendable_ccs(
        mod_code,
        genesis_coin_checker,
        spendable_cc_list,
        inner_solutions,
    )

    debug_spend_bundle(spend_bundle)