예제 #1
0
def get_output_amount_for_puzzle_and_solution(puzzle, solution):
    error, conditions, cost = conditions_dict_for_solution(Program.to([puzzle, solution]))
    total = 0
    if conditions:
        for _ in conditions.get(ConditionOpcode.CREATE_COIN, []):
            total += Program.to(_.vars[1]).as_int()
    return total
 def test_deserialization_simple_list(self):
     # ("hello" "friend")
     b = hexstr_to_bytes("ff8568656c6c6fff86667269656e6480")
     cost, output = DESERIALIZE_MOD.run_with_cost([b])
     print(cost, output)
     prog = Program.to(output)
     assert prog == Program.from_bytes(b)
예제 #3
0
async def main():
    rpc_port = 8555
    self_hostname = "localhost"
    path = DEFAULT_ROOT_PATH
    config = load_config(path, "config.yaml")
    client = await FullNodeRpcClient.create(self_hostname, rpc_port, path,
                                            config)
    try:
        farmer_prefarm = (
            await
            client.get_block_record_by_height(1)).reward_claims_incorporated[1]
        pool_prefarm = (
            await
            client.get_block_record_by_height(1)).reward_claims_incorporated[0]

        pool_amounts = int(calculate_pool_reward(uint32(0)) / 2)
        farmer_amounts = int(calculate_base_farmer_reward(uint32(0)) / 2)
        print(farmer_prefarm.amount, farmer_amounts)
        assert farmer_amounts == farmer_prefarm.amount // 2
        assert pool_amounts == pool_prefarm.amount // 2

        address1 = "txch15gx26ndmacfaqlq8m0yajeggzceu7cvmaz4df0hahkukes695rss6lej7h"  # Gene wallet (m/12381/8444/2/42):
        address2 = (
            "txch1c2cguswhvmdyz9hr3q6hak2h6p9dw4rz82g4707k2xy2sarv705qcce4pn"  # Mariano address (m/12381/8444/2/0)
        )

        ph1 = decode_puzzle_hash(address1)
        ph2 = decode_puzzle_hash(address2)

        p_farmer_2 = Program.to(
            binutils.assemble(
                f"(q . ((51 0x{ph1.hex()} {farmer_amounts}) (51 0x{ph2.hex()} {farmer_amounts})))"
            ))
        p_pool_2 = Program.to(
            binutils.assemble(
                f"(q . ((51 0x{ph1.hex()} {pool_amounts}) (51 0x{ph2.hex()} {pool_amounts})))"
            ))

        p_solution = Program.to(binutils.assemble("()"))

        sb_farmer = SpendBundle(
            [CoinSolution(farmer_prefarm, p_farmer_2, p_solution)],
            G2Element())
        sb_pool = SpendBundle(
            [CoinSolution(pool_prefarm, p_pool_2, p_solution)], G2Element())

        print(sb_pool, sb_farmer)
        # res = await client.push_tx(sb_farmer)
        res = await client.push_tx(sb_pool)

        print(res)
        up = await client.get_coin_records_by_puzzle_hash(
            farmer_prefarm.puzzle_hash, True)
        uf = await client.get_coin_records_by_puzzle_hash(
            pool_prefarm.puzzle_hash, True)
        print(up)
        print(uf)
    finally:
        client.close()
 def test_deserialization_large_numbers(self):
     # '(99999999999999999999999999999999999999999999999999999999999999999 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -99999999999999999999999999999999999999999999999999999999999999999999999999999)'  # noqa
     b = hexstr_to_bytes(
         "ff9c00f316271c7fc3908a8bef464e3945ef7a253609ffffffffffffffffffb00fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1ff22ea0179500526edb610f148ec0c614155678491902d6000000000000000000180"  # noqa
     )  # noqa
     cost, output = DESERIALIZE_MOD.run_with_cost([b])
     print(cost, output)
     prog = Program.to(output)
     assert prog == Program.from_bytes(b)
예제 #5
0
async def main():
    rpc_port = 8555
    self_hostname = "localhost"
    path = DEFAULT_ROOT_PATH
    config = load_config(path, "config.yaml")
    client = await FullNodeRpcClient.create(self_hostname, rpc_port, path,
                                            config)
    try:
        farmer_prefarm = (
            await
            client.get_block_record_by_height(1)).reward_claims_incorporated[1]
        pool_prefarm = (
            await
            client.get_block_record_by_height(1)).reward_claims_incorporated[0]

        pool_amounts = int(calculate_pool_reward(uint32(0)) / 2)
        farmer_amounts = int(calculate_base_farmer_reward(uint32(0)) / 2)
        print(farmer_prefarm.amount, farmer_amounts)
        assert farmer_amounts == farmer_prefarm.amount // 2
        assert pool_amounts == pool_prefarm.amount // 2

        address1 = "txch1k50glwkdffp2mrqq64rsgjtxj4waphuf72stqayz4qqk6mj9hd4qp7lrek"  # Gene wallet (m/12381/8444/2/51):
        address2 = "txch1430mtj60hvzyuyz4t45dyxwjdjsvphhl2fgreyry362reca4zpkszhjd3e"  # farmer1 key (m/12381/8444/2/51)

        ph1 = decode_puzzle_hash(address1)
        ph2 = decode_puzzle_hash(address2)

        p_farmer_2 = Program.to(
            binutils.assemble(
                f"(q . ((51 0x{ph1.hex()} {farmer_amounts}) (51 0x{ph2.hex()} {farmer_amounts})))"
            ))
        p_pool_2 = Program.to(
            binutils.assemble(
                f"(q . ((51 0x{ph1.hex()} {pool_amounts}) (51 0x{ph2.hex()} {pool_amounts})))"
            ))

        p_solution = Program.to(binutils.assemble("()"))

        sb_farmer = SpendBundle(
            [CoinSolution(farmer_prefarm, p_farmer_2, p_solution)],
            G2Element())
        sb_pool = SpendBundle(
            [CoinSolution(pool_prefarm, p_pool_2, p_solution)], G2Element())

        print(sb_pool, sb_farmer)
        # res = await client.push_tx(sb_farmer)
        # res = await client.push_tx(sb_pool)

        # print(res)
        up = await client.get_coin_records_by_puzzle_hash(
            farmer_prefarm.puzzle_hash, True)
        uf = await client.get_coin_records_by_puzzle_hash(
            pool_prefarm.puzzle_hash, True)
        print(up)
        print(uf)
    finally:
        client.close()
 def test_deserialization_password_coin(self):
     # (i (= (sha256 2) (q 0x2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824)) (c (q 51) (c 5 (c (q 100) (q ())))) (q "wrong password"))  # noqa
     b = hexstr_to_bytes(
         "ff04ffff0affff0bff0280ffff01ffa02cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b98248080ffff05ffff01ff3380ffff05ff05ffff05ffff01ff6480ffff01ff8080808080ffff01ff8e77726f6e672070617373776f72648080"  # noqa
     )  # noqa
     cost, output = DESERIALIZE_MOD.run_with_cost([b])
     print(cost, output)
     prog = Program.to(output)
     assert prog == Program.from_bytes(b)
예제 #7
0
    async def rl_generate_signed_aggregation_transaction(self, rl_info, consolidating_coin, rl_parent, rl_coin):
        if (
            rl_info.limit is None
            or rl_info.interval is None
            or rl_info.user_pubkey is None
            or rl_info.admin_pubkey is None
        ):
            raise ValueError("One or more of the elements of rl_info is None")
        if self.rl_coin_record is None:
            raise ValueError("Rl coin record is None")

        list_of_coinsolutions = []
        self.rl_coin_record = await self._get_rl_coin_record()
        pubkey, secretkey = await self.get_keys(self.rl_coin_record.coin.puzzle_hash)
        # Spend wallet coin
        puzzle = rl_puzzle_for_pk(
            rl_info.user_pubkey,
            rl_info.limit,
            rl_info.interval,
            rl_info.rl_origin_id,
            rl_info.admin_pubkey,
        )

        solution = rl_make_solution_mode_2(
            rl_coin.puzzle_hash,
            consolidating_coin.parent_coin_info,
            consolidating_coin.puzzle_hash,
            consolidating_coin.amount,
            rl_coin.parent_coin_info,
            rl_coin.amount,
            rl_parent.amount,
            rl_parent.parent_coin_info,
        )
        signature = AugSchemeMPL.sign(secretkey, solution.get_tree_hash())
        rl_spend = CoinSolution(self.rl_coin_record.coin, Program.to([puzzle, solution]))

        list_of_coinsolutions.append(rl_spend)

        # Spend consolidating coin
        puzzle = rl_make_aggregation_puzzle(self.rl_coin_record.coin.puzzle_hash)
        solution = rl_make_aggregation_solution(
            consolidating_coin.name(),
            self.rl_coin_record.coin.parent_coin_info,
            self.rl_coin_record.coin.amount,
        )
        agg_spend = CoinSolution(consolidating_coin, Program.to([puzzle, solution]))

        list_of_coinsolutions.append(agg_spend)
        aggsig = AugSchemeMPL.aggregate([signature])

        return SpendBundle(list_of_coinsolutions, aggsig)
예제 #8
0
    async def sign_clawback_transaction(
        self, spends: List[Tuple[Program, CoinSolution]], clawback_pubkey
    ) -> SpendBundle:
        sigs = []
        for puzzle, solution in spends:
            pubkey, secretkey = await self.get_keys_pk(clawback_pubkey)
            signature = AugSchemeMPL.sign(secretkey, Program.to(solution.solution).get_tree_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])))

        return SpendBundle(solution_list, aggsig)
예제 #9
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
예제 #10
0
def disassemble(sexp):
    """
    This version of `disassemble` also disassembles condition opcodes like `ASSERT_ANNOUNCEMENT_CONSUMED`.
    """
    kfa = dict(KEYWORD_FROM_ATOM)
    kfa.update((Program.to(k).as_atom(), v) for k, v in KFA.items())
    return bu_disassemble(sexp, kfa)
예제 #11
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],
        )
    )
예제 #12
0
def make_puzzle(amount: int) -> int:
    puzzle = f"(q . ((51 0x{ph1.hex()} {amount}) (51 0x{ph2.hex()} {amount})))"
    # print(puzzle)

    puzzle_prog = Program.to(binutils.assemble(puzzle))
    print("Program: ", puzzle_prog)
    puzzle_hash = puzzle_prog.get_tree_hash()

    solution = "()"
    prefix = "xch"
    print("PH", puzzle_hash)
    print(f"Address: {encode_puzzle_hash(puzzle_hash, prefix)}")

    result = puzzle_prog.run(solution)
    error, result_human = parse_sexp_to_conditions(result)

    total_chia = 0
    if error:
        print(f"Error: {error}")
    else:
        assert result_human is not None
        for cvp in result_human:
            assert len(cvp.vars) == 2
            total_chia += int_from_bytes(cvp.vars[1])
            print(
                f"{ConditionOpcode(cvp.opcode).name}: {encode_puzzle_hash(cvp.vars[0], prefix)},"
                f" amount: {int_from_bytes(cvp.vars[1])}")
    return total_chia
예제 #13
0
def test_1():
    puzzle_program_1 = puzzle_program_for_index(uint32(1))
    puzzle_program_2 = puzzle_program_for_index(uint32(2))

    conditions = Program.to([
        make_create_coin_condition(std_hash(bytes(pp)), amount)
        for pp, amount in [(puzzle_program_1, 1000), (puzzle_program_2, 2000)]
    ])

    assert conditions is not None
    puzzle_reveal = p2_delegated_puzzle.puzzle_reveal_for_conditions(
        conditions)
    solution = p2_delegated_puzzle.solution_for_conditions(conditions)

    error, output_conditions, cost = conditions_for_solution(
        puzzle_reveal, solution)
    assert error is None
    from pprint import pprint

    assert output_conditions is not None
    output_conditions_dict = conditions_by_opcode(output_conditions)
    pprint(output_conditions_dict)
    input_coin_info_hash = bytes([0] * 32)
    created_outputs_for_conditions_dict(output_conditions_dict,
                                        input_coin_info_hash)
    aggsigs = aggsig_in_conditions_dict(output_conditions_dict)
    pprint(aggsigs)
예제 #14
0
    async def generate_unsigned_transaction(
        self,
        amount: uint64,
        newpuzzlehash: bytes32,
        fee: uint64 = uint64(0),
        origin_id: bytes32 = None,
        coins: Set[Coin] = None,
        primaries: Optional[List[Dict[str, bytes32]]] = None,
        ignore_max_send_amount: bool = False,
    ) -> List[CoinSolution]:
        """
        Generates a unsigned transaction in form of List(Puzzle, Solutions)
        """
        if primaries is None:
            total_amount = amount + fee
        else:
            primaries_amount = 0
            for prim in primaries:
                primaries_amount += prim["amount"]
            total_amount = amount + fee + primaries_amount

        if not ignore_max_send_amount:
            max_send = await self.get_max_send_amount()
            if total_amount > max_send:
                raise ValueError(f"Can't send more than {max_send} in a single transaction")

        if coins is None:
            coins = await self.select_coins(total_amount)
        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 - total_amount

        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()):
                if primaries is None:
                    primaries = [{"puzzlehash": newpuzzlehash, "amount": amount}]
                else:
                    primaries.append({"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
예제 #15
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)
예제 #16
0
    async def test_invalid_my_puzhash(self, two_nodes):
        reward_ph = WALLET_A.get_new_puzzlehash()
        full_node_1, full_node_2, server_1, server_2 = two_nodes
        blocks = await full_node_1.get_all_full_blocks()
        start_height = blocks[-1].height if len(blocks) > 0 else -1
        blocks = bt.get_consecutive_blocks(
            3,
            block_list_input=blocks,
            guarantee_transaction_block=True,
            farmer_reward_puzzle_hash=reward_ph,
            pool_reward_puzzle_hash=reward_ph,
        )
        peer = await connect_and_get_peer(server_1, server_2)

        for block in blocks:
            await full_node_1.full_node.respond_block(full_node_protocol.RespondBlock(block))

        await time_out_assert(60, node_height_at_least, True, full_node_1, start_height + 3)

        coin = list(blocks[-1].get_included_reward_coins())[0]
        cvp = ConditionVarPair(ConditionOpcode.ASSERT_MY_PUZZLEHASH, [Program.to([]).get_tree_hash()])
        dic = {cvp.opcode: [cvp]}

        spend_bundle1 = generate_test_spend_bundle(coin, dic)

        assert spend_bundle1 is not None
        tx1: full_node_protocol.RespondTransaction = full_node_protocol.RespondTransaction(spend_bundle1)
        await full_node_1.respond_transaction(tx1, peer)

        sb1 = full_node_1.full_node.mempool_manager.get_spendbundle(spend_bundle1.name())

        assert sb1 is None
예제 #17
0
    def test_shatrees_match(self):
        """Checks to see that all .sha256tree files match their .hex files"""
        for prog_path in wallet_program_files:
            # load the .hex file as a program
            hex_filename = path_with_ext(prog_path, ".hex")
            clvm_hex = hex_filename.read_text()  # .decode("utf8")
            clvm_blob = bytes.fromhex(clvm_hex)
            s = SerializedProgram.from_bytes(clvm_blob)
            p = Program.from_bytes(clvm_blob)

            # load the checked-in shatree
            existing_sha = path_with_ext(
                prog_path, ".hex.sha256tree").read_text().strip()

            self.assertEqual(
                s.get_tree_hash().hex(),
                existing_sha,
                msg=
                f"Checked-in shatree hash file does not match shatree hash of loaded SerializedProgram: {prog_path}",  # noqa
            )
            self.assertEqual(
                p.get_tree_hash().hex(),
                existing_sha,
                msg=
                f"Checked-in shatree hash file does not match shatree hash of loaded Program: {prog_path}",
            )
예제 #18
0
def solution_for_hidden_puzzle(
    hidden_public_key: G1Element,
    hidden_puzzle: Program,
    solution_to_hidden_puzzle: Program,
) -> Program:
    return Program.to(
        [hidden_public_key, hidden_puzzle, solution_to_hidden_puzzle])
예제 #19
0
def rl_make_solution_mode_2(
    my_puzzle_hash,
    consolidating_primary_input,
    consolidating_coin_puzzle_hash,
    outgoing_amount,
    my_primary_input,
    incoming_amount,
    parent_amount,
    my_parent_parent_id,
):
    my_puzzle_hash = hexlify(my_puzzle_hash).decode("ascii")
    consolidating_primary_input = hexlify(consolidating_primary_input).decode(
        "ascii")
    consolidating_coin_puzzle_hash = hexlify(
        consolidating_coin_puzzle_hash).decode("ascii")
    primary_input = hexlify(my_primary_input).decode("ascii")
    sol = sexp(
        AGGREGATION_MODE,
        "0x" + my_puzzle_hash,
        "0x" + consolidating_primary_input,
        "0x" + consolidating_coin_puzzle_hash,
        outgoing_amount,
        "0x" + primary_input,
        incoming_amount,
        parent_amount,
        "0x" + str(my_parent_parent_id),
    )
    return Program.to(binutils.assemble(sol))
예제 #20
0
def solution_for_rl(
    my_parent_id: bytes32,
    my_puzzlehash: bytes32,
    my_amount: uint64,
    out_puzzlehash: bytes32,
    out_amount: uint64,
    my_parent_parent_id: bytes32,
    parent_amount: uint64,
    interval,
    limit,
    fee,
):
    """
    Solution is (1 my_parent_id, my_puzzlehash, my_amount, outgoing_puzzle_hash, outgoing_amount,
    min_block_time, parent_parent_id, parent_amount, fee)
    min block time = Math.ceil((new_amount * self.interval) / self.limit)
    """

    min_block_count = math.ceil((out_amount * interval) / limit)
    solution = sexp(
        RATE_LIMITED_MODE,
        "0x" + my_parent_id.hex(),
        "0x" + my_puzzlehash.hex(),
        my_amount,
        "0x" + out_puzzlehash.hex(),
        out_amount,
        min_block_count,
        "0x" + my_parent_parent_id.hex(),
        parent_amount,
        fee,
    )
    return Program.to(binutils.assemble(solution))
예제 #21
0
    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.CREATE_ANNOUNCEMENT:
                    ret.append(make_create_announcement(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.AGG_SIG:
                    ret.append(make_assert_aggsig_condition(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.ASSERT_ANNOUNCEMENT:
                    ret.append(make_assert_announcement(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.ASSERT_SECONDS_NOW_EXCEEDS:
                    ret.append(
                        make_assert_seconds_now_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_HEIGHT_NOW_EXCEEDS:
                    ret.append(
                        make_assert_height_now_exceeds_condition(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.ASSERT_HEIGHT_AGE_EXCEEDS:
                    ret.append(
                        make_assert_height_age_exceeds_condition(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.RESERVE_FEE:
                    ret.append(make_reserve_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
            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
    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.CREATE_ANNOUNCEMENT:
                    ret.append(make_create_announcement(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.AGG_SIG:
                    ret.append(make_assert_aggsig_condition(cvp.vars[0]))
                if cvp.opcode == ConditionOpcode.ASSERT_ANNOUNCEMENT:
                    ret.append(make_assert_announcement(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))
예제 #24
0
def test_spend_zero_coin(mod_code: Program, coin_checker_for_farmed_coin):
    """
    Test to spend ccs from a farmed coin to a cc genesis coin, then to N outputs,
    then joining back down to two outputs.
    """

    eve_inner_puzzle = ANYONE_CAN_SPEND_PUZZLE
    eve_inner_puzzle_hash = eve_inner_puzzle.get_tree_hash()

    total_minted = 0x111

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

    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)

    eve_cc_list = []
    for _ in spend_bundle.coin_solutions:
        eve_cc_list.extend(
            spendable_cc_list_from_coin_solution(_, hash_to_puzzle_f))
    assert len(eve_cc_list) == 1
    eve_cc_spendable = eve_cc_list[0]

    # farm regular chia

    farmed_coin = generate_farmed_coin(2, eve_inner_puzzle_hash, amount=500)

    # create a zero cc from this farmed coin

    wrapped_cc_puzzle_hash = cc_puzzle_hash_for_inner_puzzle_hash(
        mod_code, genesis_coin_checker, eve_inner_puzzle_hash)

    solution = solution_for_pay_to_any([(wrapped_cc_puzzle_hash, 0)])
    reveal_w_solution = Program.to([ANYONE_CAN_SPEND_PUZZLE, solution])
    coin_solution = CoinSolution(farmed_coin, reveal_w_solution)
    spendable_cc_list = spendable_cc_list_from_coin_solution(
        coin_solution, hash_to_puzzle_f)
    assert len(spendable_cc_list) == 1
    zero_cc_spendable = spendable_cc_list[0]

    # we have our zero coin
    # now try to spend it

    spendable_cc_list = [eve_cc_spendable, zero_cc_spendable]
    inner_solutions = [
        solution_for_pay_to_any([]),
        solution_for_pay_to_any([(wrapped_cc_puzzle_hash,
                                  eve_cc_spendable.coin.amount)]),
    ]
    spend_bundle = spend_bundle_for_spendable_ccs(mod_code,
                                                  genesis_coin_checker,
                                                  spendable_cc_list,
                                                  inner_solutions)
    debug_spend_bundle(spend_bundle)
예제 #25
0
def run_and_return_cost_time(chialisp):

    start = time.time()
    clvm_loop = "((c (q ((c (f (a)) (c (f (a)) (c (f (r (a))) (c (f (r (r (a))))"
    " (q ()))))))) (c (q ((c (i (f (r (a))) (q (i (q 1) ((c (f (a)) (c (f (a))"
    " (c (- (f (r (a))) (q 1)) (c (f (r (r (a)))) (q ()))))))"
    " ((c (f (r (r (a)))) (q ()))))) (q (q ()))) (a)))) (a))))"
    loop_program = Program.to(binutils.assemble(clvm_loop))
    clvm_loop_solution = f"(1000 {chialisp})"
    solution_program = Program.to(binutils.assemble(clvm_loop_solution))

    cost, sexp = loop_program.run_with_cost(solution_program)

    end = time.time()
    total_time = end - start

    return cost, total_time
예제 #26
0
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]])
예제 #27
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
예제 #28
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
예제 #29
0
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]
    ])
예제 #30
0
def conditions_for_solution(
    puzzle_reveal: Program,
    solution: Program,
) -> Tuple[Optional[Err], Optional[List[ConditionVarPair]], 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)