예제 #1
0
    async def test_delegated_tail(self, setup_sim):
        sim, sim_client = setup_sim

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

            starting_coin: Coin = (await sim_client.get_coin_records_by_puzzle_hash(standard_acs_ph))[0].coin
            sk = PrivateKey.from_bytes(secret_exponent_for_index(1).to_bytes(32, "big"))
            tail: Program = DelegatedLimitations.construct([Program.to(sk.get_g1())])
            cat_puzzle: Program = construct_cat_puzzle(CAT_MOD, tail.get_tree_hash(), acs)
            cat_ph: bytes32 = cat_puzzle.get_tree_hash()

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

            # We're signing a different tail to use here
            name_as_program = Program.to(starting_coin.name())
            new_tail: Program = GenesisById.construct([name_as_program])
            checker_solution: Program = DelegatedLimitations.solve(
                [name_as_program],
                {
                    "signed_program": {
                        "identifier": "genesis_by_id",
                        "args": [str(name_as_program)],
                    },
                    "program_arguments": {},
                },
            )
            signature: G2Element = AugSchemeMPL.sign(sk, new_tail.get_tree_hash())

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

        finally:
            await sim.close()
예제 #2
0
    async def generate_issuance_bundle(
            cls, wallet, _: Dict,
            amount: uint64) -> Tuple[TransactionRecord, SpendBundle]:
        coins = await wallet.standard_wallet.select_coins(amount)

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

        cc_inner: Program = await wallet.get_new_inner_puzzle()
        await wallet.add_lineage(origin_id, LineageProof())
        genesis_coin_checker: Program = cls.construct([Program.to(origin_id)])

        minted_cc_puzzle_hash: bytes32 = construct_cat_puzzle(
            CAT_MOD, genesis_coin_checker.get_tree_hash(),
            cc_inner).get_tree_hash()

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

        inner_solution = wallet.standard_wallet.add_condition_to_solution(
            Program.to([51, 0, -113, genesis_coin_checker, []]),
            wallet.standard_wallet.make_solution(primaries=[{
                "puzzlehash":
                cc_inner.get_tree_hash(),
                "amount":
                amount
            }], ),
        )
        eve_spend = unsigned_spend_bundle_for_spendable_cats(
            CAT_MOD,
            [
                SpendableCAT(
                    list(
                        filter(lambda a: a.amount == amount,
                               tx_record.additions))[0],
                    genesis_coin_checker.get_tree_hash(),
                    cc_inner,
                    inner_solution,
                    limitations_program_reveal=genesis_coin_checker,
                )
            ],
        )
        signed_eve_spend = await wallet.sign(eve_spend)

        if wallet.cat_info.my_tail is None:
            await wallet.save_info(
                CATInfo(genesis_coin_checker.get_tree_hash(),
                        genesis_coin_checker, wallet.cat_info.lineage_proofs),
                False,
            )

        return tx_record, SpendBundle.aggregate(
            [tx_record.spend_bundle, signed_eve_spend])
예제 #3
0
 async def check_all_there():
     spendable = await cat_wallet.get_cat_spendable_coins()
     spendable_name_set = set()
     for record in spendable:
         spendable_name_set.add(record.coin.name())
     puzzle_hash = construct_cat_puzzle(
         CAT_MOD, cat_wallet.cat_info.limitations_program_hash,
         cat_2).get_tree_hash()
     for i in range(1, 50):
         coin = Coin(spent_coint.name(), puzzle_hash, i)
         if coin.name() not in spendable_name_set:
             return False
     return True
예제 #4
0
    async def test_genesis_by_puzhash(self, setup_sim):
        sim, sim_client = setup_sim

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

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

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

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

        finally:
            await sim.close()
예제 #5
0
    async def test_everything_with_signature(self, setup_sim):
        sim, sim_client = setup_sim

        try:
            sk = PrivateKey.from_bytes(secret_exponent_for_index(1).to_bytes(32, "big"))
            tail: Program = EverythingWithSig.construct([Program.to(sk.get_g1())])
            checker_solution: Program = EverythingWithSig.solve([], {})
            cat_puzzle: Program = construct_cat_puzzle(CAT_MOD, tail.get_tree_hash(), acs)
            cat_ph: bytes32 = cat_puzzle.get_tree_hash()
            await sim.farm_block(cat_ph)

            # Test eve spend
            # We don't sign any message data because CLVM 0 translates to b'' apparently
            starting_coin: Coin = (await sim_client.get_coin_records_by_puzzle_hash(cat_ph))[0].coin
            signature: G2Element = AugSchemeMPL.sign(
                sk, (starting_coin.name() + sim.defaults.AGG_SIG_ME_ADDITIONAL_DATA)
            )

            await self.do_spend(
                sim,
                sim_client,
                tail,
                [starting_coin],
                [NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), starting_coin.amount],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    )
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                limitations_solutions=[checker_solution],
                signatures=[signature],
                cost_str="Signature Issuance",
            )

            # Test melting value
            coin: Coin = (await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False))[0].coin
            signature = AugSchemeMPL.sign(
                sk, (int_to_bytes(-1) + coin.name() + sim.defaults.AGG_SIG_ME_ADDITIONAL_DATA)
            )

            await self.do_spend(
                sim,
                sim_client,
                tail,
                [coin],
                [NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), coin.amount - 1],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    )
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                extra_deltas=[-1],
                limitations_solutions=[checker_solution],
                signatures=[signature],
                cost_str="Signature Melt",
            )

            # Test minting value
            coin = (await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False))[0].coin
            signature = AugSchemeMPL.sign(sk, (int_to_bytes(1) + coin.name() + sim.defaults.AGG_SIG_ME_ADDITIONAL_DATA))

            # Need something to fund the minting
            temp_p = Program.to(1)
            temp_ph: bytes32 = temp_p.get_tree_hash()
            await sim.farm_block(temp_ph)
            acs_coin: Coin = (await sim_client.get_coin_records_by_puzzle_hash(temp_ph, include_spent_coins=False))[
                0
            ].coin
            acs_bundle = SpendBundle(
                [
                    CoinSpend(
                        acs_coin,
                        temp_p,
                        Program.to([]),
                    )
                ],
                G2Element(),
            )

            await self.do_spend(
                sim,
                sim_client,
                tail,
                [coin],
                [NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), coin.amount + 1],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    )
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                extra_deltas=[1],
                limitations_solutions=[checker_solution],
                signatures=[signature],
                additional_spends=[acs_bundle],
                cost_str="Signature Mint",
            )

        finally:
            await sim.close()
예제 #6
0
    async def test_complex_spend(self, setup_sim):
        sim, sim_client = setup_sim

        try:
            tail = Program.to([])
            checker_solution = Program.to([])
            cat_puzzle: Program = construct_cat_puzzle(CAT_MOD, tail.get_tree_hash(), acs)
            cat_ph: bytes32 = cat_puzzle.get_tree_hash()
            await sim.farm_block(cat_ph)
            await sim.farm_block(cat_ph)

            cat_records = await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False)
            parent_of_mint = cat_records[0].coin
            parent_of_melt = cat_records[1].coin
            eve_to_mint = cat_records[2].coin
            eve_to_melt = cat_records[3].coin

            # Spend two of them to make them non-eve
            await self.do_spend(
                sim,
                sim_client,
                tail,
                [parent_of_mint, parent_of_melt],
                [NO_LINEAGE_PROOF, NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), parent_of_mint.amount],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    ),
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), parent_of_melt.amount],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    ),
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                limitations_solutions=[checker_solution] * 2,
                cost_str="Spend two eves",
            )

            # Make the lineage proofs for the non-eves
            mint_lineage = LineageProof(parent_of_mint.parent_coin_info, acs_ph, parent_of_mint.amount)
            melt_lineage = LineageProof(parent_of_melt.parent_coin_info, acs_ph, parent_of_melt.amount)

            # Find the two new coins
            all_cats = await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False)
            all_cat_coins = [cr.coin for cr in all_cats]
            standard_to_mint = list(filter(lambda cr: cr.parent_coin_info == parent_of_mint.name(), all_cat_coins))[0]
            standard_to_melt = list(filter(lambda cr: cr.parent_coin_info == parent_of_melt.name(), all_cat_coins))[0]

            # Do the complex spend
            # We have both and eve and non-eve doing both minting and melting
            await self.do_spend(
                sim,
                sim_client,
                tail,
                [eve_to_mint, eve_to_melt, standard_to_mint, standard_to_melt],
                [NO_LINEAGE_PROOF, NO_LINEAGE_PROOF, mint_lineage, melt_lineage],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), eve_to_mint.amount + 13],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    ),
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), eve_to_melt.amount - 21],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    ),
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), standard_to_mint.amount + 21],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    ),
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), standard_to_melt.amount - 13],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    ),
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                limitations_solutions=[checker_solution] * 4,
                extra_deltas=[13, -21, 21, -13],
                cost_str="Complex Spend",
            )
        finally:
            await sim.close()
예제 #7
0
    async def test_cat_mod(self, setup_sim):
        sim, sim_client = setup_sim

        try:
            tail = Program.to([])
            checker_solution = Program.to([])
            cat_puzzle: Program = construct_cat_puzzle(CAT_MOD, tail.get_tree_hash(), acs)
            cat_ph: bytes32 = cat_puzzle.get_tree_hash()
            await sim.farm_block(cat_ph)
            starting_coin: Coin = (await sim_client.get_coin_records_by_puzzle_hash(cat_ph))[0].coin

            # Testing the eve spend
            await self.do_spend(
                sim,
                sim_client,
                tail,
                [starting_coin],
                [NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), starting_coin.amount - 3, [b"memo"]],
                            [51, acs.get_tree_hash(), 1],
                            [51, acs.get_tree_hash(), 2],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    )
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                limitations_solutions=[checker_solution],
                cost_str="Eve Spend",
            )

            # There's 4 total coins at this point. A farming reward and the three children of the spend above.

            # Testing a combination of two
            coins: List[Coin] = [
                record.coin
                for record in (await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False))
            ]
            coins = [coins[0], coins[1]]
            await self.do_spend(
                sim,
                sim_client,
                tail,
                coins,
                [NO_LINEAGE_PROOF] * 2,
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), coins[0].amount + coins[1].amount],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    ),
                    Program.to([[51, 0, -113, tail, checker_solution]]),
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                limitations_solutions=[checker_solution] * 2,
                cost_str="Two CATs",
            )

            # Testing a combination of three
            coins = [
                record.coin
                for record in (await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False))
            ]
            total_amount: uint64 = uint64(sum([c.amount for c in coins]))
            await self.do_spend(
                sim,
                sim_client,
                tail,
                coins,
                [NO_LINEAGE_PROOF] * 3,
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), total_amount],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    ),
                    Program.to([[51, 0, -113, tail, checker_solution]]),
                    Program.to([[51, 0, -113, tail, checker_solution]]),
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                limitations_solutions=[checker_solution] * 3,
                cost_str="Three CATs",
            )

            # Spend with a standard lineage proof
            parent_coin: Coin = coins[0]  # The first one is the one we didn't light on fire
            _, curried_args = cat_puzzle.uncurry()
            _, _, innerpuzzle = curried_args.as_iter()
            lineage_proof = LineageProof(parent_coin.parent_coin_info, innerpuzzle.get_tree_hash(), parent_coin.amount)
            await self.do_spend(
                sim,
                sim_client,
                tail,
                [(await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False))[0].coin],
                [lineage_proof],
                [Program.to([[51, acs.get_tree_hash(), total_amount]])],
                (MempoolInclusionStatus.SUCCESS, None),
                reveal_limitations_program=False,
                cost_str="Standard Lineage Check",
            )

            # Melt some value
            await self.do_spend(
                sim,
                sim_client,
                tail,
                [(await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False))[0].coin],
                [NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), total_amount - 1],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    )
                ],
                (MempoolInclusionStatus.SUCCESS, None),
                extra_deltas=[-1],
                limitations_solutions=[checker_solution],
                cost_str="Melting Value",
            )

            # Mint some value
            temp_p = Program.to(1)
            temp_ph: bytes32 = temp_p.get_tree_hash()
            await sim.farm_block(temp_ph)
            acs_coin: Coin = (await sim_client.get_coin_records_by_puzzle_hash(temp_ph, include_spent_coins=False))[
                0
            ].coin
            acs_bundle = SpendBundle(
                [
                    CoinSpend(
                        acs_coin,
                        temp_p,
                        Program.to([]),
                    )
                ],
                G2Element(),
            )
            await self.do_spend(
                sim,
                sim_client,
                tail,
                [(await sim_client.get_coin_records_by_puzzle_hash(cat_ph, include_spent_coins=False))[0].coin],
                [NO_LINEAGE_PROOF],
                [
                    Program.to(
                        [
                            [51, acs.get_tree_hash(), total_amount],
                            [51, 0, -113, tail, checker_solution],
                        ]
                    )
                ],  # We subtracted 1 last time so it's normal now
                (MempoolInclusionStatus.SUCCESS, None),
                extra_deltas=[1],
                additional_spends=[acs_bundle],
                limitations_solutions=[checker_solution],
                cost_str="Mint Value",
            )

        finally:
            await sim.close()
예제 #8
0
    async def generate_coins(
        self,
        sim,
        sim_client,
        requested_coins: Dict[Optional[str], List[uint64]],
    ) -> Dict[Optional[str], List[Coin]]:
        await sim.farm_block(acs_ph)
        parent_coin: Coin = [
            cr.coin for cr in await (
                sim_client.get_coin_records_by_puzzle_hash(acs_ph))
        ][0]

        # We need to gather a list of initial coins to create as well as spends that do the eve spend for every CAT
        payments: List[Payment] = []
        cat_bundles: List[SpendBundle] = []
        for tail_str, amounts in requested_coins.items():
            for amount in amounts:
                if tail_str:
                    tail: Program = str_to_tail(
                        tail_str)  # Making a fake but unique TAIL
                    cat_puzzle: Program = construct_cat_puzzle(
                        CAT_MOD, tail.get_tree_hash(), acs)
                    payments.append(
                        Payment(cat_puzzle.get_tree_hash(), amount, []))
                    cat_bundles.append(
                        unsigned_spend_bundle_for_spendable_cats(
                            CAT_MOD,
                            [
                                SpendableCAT(
                                    Coin(parent_coin.name(),
                                         cat_puzzle.get_tree_hash(), amount),
                                    tail.get_tree_hash(),
                                    acs,
                                    Program.to([[51, acs_ph, amount],
                                                [51, 0, -113, tail, []]]),
                                )
                            ],
                        ))
                else:
                    payments.append(Payment(acs_ph, amount, []))

        # This bundle create all of the initial coins
        parent_bundle = SpendBundle(
            [
                CoinSpend(
                    parent_coin,
                    acs,
                    Program.to([[51, p.puzzle_hash, p.amount]
                                for p in payments]),
                )
            ],
            G2Element(),
        )

        # Then we aggregate it with all of the eve spends
        await sim_client.push_tx(
            SpendBundle.aggregate([parent_bundle, *cat_bundles]))
        await sim.farm_block()

        # Search for all of the coins and put them into a dictionary
        coin_dict: Dict[Optional[str], List[Coin]] = {}
        for tail_str, _ in requested_coins.items():
            if tail_str:
                tail_hash: bytes32 = str_to_tail_hash(tail_str)
                cat_ph: bytes32 = construct_cat_puzzle(CAT_MOD, tail_hash,
                                                       acs).get_tree_hash()
                coin_dict[tail_str] = [
                    cr.coin for cr in await (
                        sim_client.get_coin_records_by_puzzle_hash(
                            cat_ph, include_spent_coins=False))
                ]
            else:
                coin_dict[None] = list(
                    filter(
                        lambda c: c.amount < 250000000000,
                        [
                            cr.coin for cr in await (
                                sim_client.get_coin_records_by_puzzle_hash(
                                    acs_ph, include_spent_coins=False))
                        ],
                    ))

        return coin_dict
예제 #9
0
def str_to_cat_hash(tail_str: str) -> bytes32:
    return construct_cat_puzzle(CAT_MOD, str_to_tail_hash(tail_str),
                                acs).get_tree_hash()