From 7d9808494963d9743756692ba6e4aa4710513c7f Mon Sep 17 00:00:00 2001 From: Matthew Howard Date: Wed, 6 Nov 2024 15:37:05 +0000 Subject: [PATCH] add shape of test --- chia/_tests/clvm/test_member_puzzles.py | 138 +++++++++++++++++- .../custody/member_puzzles/member_puzzles.py | 2 +- 2 files changed, 137 insertions(+), 3 deletions(-) diff --git a/chia/_tests/clvm/test_member_puzzles.py b/chia/_tests/clvm/test_member_puzzles.py index 3cc3de31b1d5..d91f87a68b1a 100644 --- a/chia/_tests/clvm/test_member_puzzles.py +++ b/chia/_tests/clvm/test_member_puzzles.py @@ -3,6 +3,7 @@ import itertools from typing import List +from chia.util.hash import std_hash import pytest from chia_rs import AugSchemeMPL, G2Element @@ -10,8 +11,9 @@ from chia.clvm.spend_sim import CostLogger, sim_and_client from chia.consensus.default_constants import DEFAULT_CONSTANTS from chia.types.blockchain_format.program import Program -from chia.types.coin_spend import make_spend +from chia.types.coin_spend import CoinSpend, make_spend from chia.types.mempool_inclusion_status import MempoolInclusionStatus +from chia.types.spend_bundle import SpendBundle from chia.wallet.conditions import CreateCoinAnnouncement from chia.wallet.puzzles.custody.custody_architecture import ( DelegatedPuzzleAndSolution, @@ -23,7 +25,11 @@ Restriction, ) from chia.wallet.puzzles.custody.member_puzzles.member_puzzles import BLSMember, SingletonMember +from chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle import puzzle_for_synthetic_public_key +from chia.types.blockchain_format.coin import Coin +from chia.wallet.singleton import SINGLETON_LAUNCHER_PUZZLE, SINGLETON_LAUNCHER_PUZZLE_HASH, SINGLETON_TOP_LAYER_MOD from chia.wallet.wallet_spend_bundle import WalletSpendBundle +from chia.wallet.wallet import make_spend @pytest.mark.anyio @@ -95,7 +101,6 @@ async def test_bls_member(cost_logger: CostLogger) -> None: assert result == (MempoolInclusionStatus.SUCCESS, None) await sim.farm_block() await sim.rewind(block_height) - breakpoint() @pytest.mark.anyio @pytest.mark.parametrize( @@ -198,3 +203,132 @@ async def test_2_of_4_bls_members(cost_logger: CostLogger, with_restrictions: bo assert result == (MempoolInclusionStatus.SUCCESS, None) await sim.farm_block() await sim.rewind(block_height) + +@pytest.mark.anyio +async def test_singleton_member(cost_logger: CostLogger) -> None: + async with sim_and_client() as (sim, client): + delegated_puzzle = Program.to(1) + + sk = AugSchemeMPL.key_gen(bytes.fromhex(str(0) * 64)) + pk = sk.public_key() + puz = puzzle_for_synthetic_public_key(pk) + # Farm and find coin + await sim.farm_block(puz.get_tree_hash()) + coin = (await client.get_coin_records_by_puzzle_hashes([puz.get_tree_hash()], include_spent_coins=False))[ + 0 + ].coin + eve_coin = Coin(coin.name(), SINGLETON_LAUNCHER_PUZZLE_HASH, 1) + singleton_struct = (SINGLETON_TOP_LAYER_MOD.get_tree_hash(), (eve_coin.name(), SINGLETON_LAUNCHER_PUZZLE_HASH)) + singleton_innerpuz = Program.to(( + 1, + [ + [51, Program.to(1).get_tree_hash(), 1], + [66, 0x07, delegated_puzzle.get_tree_hash(), coin.name()] + ], # create approval message to singleton member puzzle + )) + singleton_puzzle = SINGLETON_TOP_LAYER_MOD.curry([singleton_struct, singleton_innerpuz]) + launcher_solution = Program.to([singleton_puzzle.get_tree_hash(), 1, 0]) + + conditions_list = [ + [51, SINGLETON_LAUNCHER_PUZZLE_HASH, 1], + [61, std_hash(eve_coin.name() + launcher_solution.get_tree_hash())] + ] + solution = Program.to([0, (1, conditions_list), 0]) + + msg = bytes(solution.rest().first().get_tree_hash()) + coin.name() + DEFAULT_CONSTANTS.AGG_SIG_ME_ADDITIONAL_DATA + sig = sk.sign(msg) + sb = WalletSpendBundle( + [ + make_spend(coin, puz, solution), + make_spend(eve_coin, SINGLETON_LAUNCHER_PUZZLE, launcher_solution), + ], + sig + ) + result = await client.push_tx( + cost_logger.add_cost( + "BLSMember spendbundle", + sb, + ) + ) + assert result == (MempoolInclusionStatus.SUCCESS, None) + + await sim.farm_block(singleton_puzzle.get_tree_hash()) + + singleton_coin = (await client.get_coin_records_by_puzzle_hashes([singleton_puzzle.get_tree_hash()], include_spent_coins=False))[ + 0 + ].coin + + singleton_member_puzzle = PuzzleWithRestrictions(0, [], SingletonMember(eve_coin.name())) + memo = PuzzleHint( + singleton_member_puzzle.puzzle.puzzle_hash(0), + singleton_member_puzzle.puzzle.memo(0), + ) + + assert singleton_member_puzzle.memo() == Program.to( + ( + singleton_member_puzzle.spec_namespace, + [ + singleton_member_puzzle.nonce, + [], + 0, + memo.to_program(), + ], + ) + ) + + # Farm and find coin + await sim.farm_block(singleton_member_puzzle.puzzle_hash()) + coin = (await client.get_coin_records_by_puzzle_hashes([singleton_member_puzzle.puzzle_hash()], include_spent_coins=False))[ + 0 + ].coin + block_height = sim.block_height + + # Create an announcements to be asserted in the delegated puzzle + announcement = CreateCoinAnnouncement(msg=b"foo", coin_id=coin.name()) + + # Make solution for singleton + fullsol = Program.to( + [ + [eve_coin.parent_coin_info, 1], + 1, + 0 + ] + ) + + sb = WalletSpendBundle( + [ + make_spend( + coin, + singleton_member_puzzle.puzzle_reveal(), + singleton_member_puzzle.solve( + [], + [], + Program.to([[singleton_coin.parent_coin_info, singleton_innerpuz.get_tree_hash(), 1]]), # singleton member puzzle only requires singleton's current innerpuz + DelegatedPuzzleAndSolution( + delegated_puzzle, + Program.to( + [ + announcement.to_program(), + announcement.corresponding_assertion().to_program(), + ] + ), + ), + ), + ), + make_spend( + singleton_coin, + singleton_puzzle, + fullsol, + ) + ], + G2Element(), + ) + result = await client.push_tx( + cost_logger.add_cost( + "BLSMember spendbundle", + sb, + ) + ) + assert result == (MempoolInclusionStatus.SUCCESS, None) + await sim.farm_block() + await sim.rewind(block_height) \ No newline at end of file diff --git a/chia/wallet/puzzles/custody/member_puzzles/member_puzzles.py b/chia/wallet/puzzles/custody/member_puzzles/member_puzzles.py index ca8c7a0464fd..5b660fa2a913 100644 --- a/chia/wallet/puzzles/custody/member_puzzles/member_puzzles.py +++ b/chia/wallet/puzzles/custody/member_puzzles/member_puzzles.py @@ -42,7 +42,7 @@ def memo(self, nonce: int) -> Program: def puzzle(self, nonce: int) -> Program: singleton_struct = (SINGLETON_TOP_LAYER_MOD_HASH, (self.singleton_id, SINGLETON_LAUNCHER_PUZZLE_HASH)) - return BLS_MEMBER_MOD.curry(singleton_struct) + return SINGLETON_MEMBER_MOD.curry(singleton_struct) def puzzle_hash(self, nonce: int) -> bytes32: return self.puzzle(nonce).get_tree_hash()