Skip to content

Commit

Permalink
DAO wallet todos (#15682)
Browse files Browse the repository at this point in the history
- cleanup dao utils and move get_singleton_struct to singleton.py
- spend the timer coin during proposal self destruct
  • Loading branch information
matt-o-how committed Jul 7, 2023
2 parents 225b5b9 + 6d49421 commit 8dfb947
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 104 deletions.
96 changes: 2 additions & 94 deletions chia/wallet/dao_wallet/dao_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from chia.wallet.dao_wallet.dao_info import DAORules
from chia.wallet.puzzles.load_clvm import load_clvm
from chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle import MOD
from chia.wallet.singleton import create_singleton_puzzle, get_inner_puzzle_from_singleton
from chia.wallet.singleton import create_singleton_puzzle, get_inner_puzzle_from_singleton, get_singleton_struct_for_id
from chia.wallet.uncurried_puzzle import UncurriedPuzzle

SINGLETON_MOD: Program = load_clvm("singleton_top_layer_v1_1.clsp")
Expand Down Expand Up @@ -54,45 +54,15 @@
log = logging.Logger(__name__)


def singleton_struct_for_id(id: bytes32) -> Program:
singleton_struct: Program = Program.to((SINGLETON_MOD_HASH, (id, SINGLETON_LAUNCHER_HASH)))
return singleton_struct


def create_cat_launcher_for_singleton_id(id: bytes32) -> Program:
singleton_struct = singleton_struct_for_id(id)
singleton_struct = get_singleton_struct_for_id(id)
return DAO_CAT_LAUNCHER.curry(singleton_struct)


def curry_cat_eve(next_puzzle_hash: bytes32) -> Program:
return DAO_CAT_EVE.curry(next_puzzle_hash)


def create_new_proposal_puzzle(
proposal_id: bytes32,
cat_tail_hash: bytes32,
treasury_id: bytes32,
proposed_puzzle_hash: bytes32,
) -> Program:
singleton_struct: Program = Program.to((SINGLETON_MOD_HASH, (proposal_id, SINGLETON_LAUNCHER_HASH)))
puzzle: Program = DAO_PROPOSAL_MOD.curry(
singleton_struct,
DAO_PROPOSAL_MOD_HASH,
DAO_PROPOSAL_TIMER_MOD_HASH,
CAT_MOD_HASH,
DAO_FINISHED_STATE_HASH,
DAO_TREASURY_MOD_HASH,
DAO_LOCKUP_MOD_HASH,
cat_tail_hash,
treasury_id,
0,
0,
"s",
proposed_puzzle_hash,
)
return puzzle


def get_treasury_puzzle(dao_rules: DAORules, treasury_id: bytes32, cat_tail_hash: bytes32) -> Program:
# SINGLETON_STRUCT ; (SINGLETON_MOD_HASH (SINGLETON_ID . LAUNCHER_PUZZLE_HASH))
# PROPOSAL_MOD_HASH
Expand Down Expand Up @@ -143,17 +113,6 @@ def get_proposal_validator(treasury_puz: Program) -> Program:
return validator


def create_announcement_condition_for_nft_spend(
# treasury_id: bytes32, TODO: is treasury_id needed here?
nft_id: bytes32,
target_address: bytes32,
) -> Tuple[Program, Program]:
# TODO: this delegated puzzle does not actually work with NFTs - need to copy more of the code later
delegated_puzzle = Program.to([(1, [[51, target_address, 1]])])
announcement_condition = Program.to([62, Program.to([nft_id, delegated_puzzle.get_tree_hash()]).get_tree_hash()])
return announcement_condition, delegated_puzzle


def get_update_proposal_puzzle(dao_rules: DAORules, proposal_validator: Program) -> Program:
update_proposal = DAO_UPDATE_PROPOSAL_MOD.curry(
DAO_TREASURY_MOD_HASH,
Expand Down Expand Up @@ -273,16 +232,6 @@ def get_lockup_puzzle(
return puzzle


def get_latest_lockup_puzzle_for_coin_spend(parent_spend: CoinSpend, inner_puzzle: Optional[Program] = None) -> Program:
puzzle = get_inner_puzzle_from_singleton(parent_spend.puzzle_reveal)
assert isinstance(puzzle, Program)
solution = parent_spend.solution.to_program().rest().rest().first()
if solution.first() == Program.to(0):
return puzzle
new_proposal_id = solution.rest().rest().rest().first().as_atom()
return add_proposal_to_active_list(puzzle, new_proposal_id, inner_puzzle)


def add_proposal_to_active_list(
lockup_puzzle: Program, proposal_id: bytes32, inner_puzzle: Optional[Program] = None
) -> Program:
Expand Down Expand Up @@ -548,35 +497,6 @@ def get_finished_state_puzzle(proposal_id: bytes32) -> Program:
return create_singleton_puzzle(finished_inner_puz, proposal_id)


def get_cat_tail_hash_from_treasury_puzzle(treasury_puzzle: Program) -> bytes32:
curried_args = uncurry_treasury(treasury_puzzle)
(
_DAO_TREASURY_MOD_HASH,
proposal_validator,
proposal_timelock,
soft_close_length,
attendance_required,
pass_percentage,
self_destruct_length,
oracle_spend_delay,
) = curried_args

curried_args = uncurry_proposal_validator(proposal_validator)
(
SINGLETON_STRUCT,
PROPOSAL_MOD_HASH,
PROPOSAL_TIMER_MOD_HASH,
CAT_MOD_HASH,
DAO_FINISHED_STATE_HASH,
LOCKUP_MOD_HASH,
TREASURY_MOD_HASH,
CAT_TAIL_HASH,
PROPOSAL_MINIMUM_AMOUNT,
PAYOUT_PUZHASH,
) = curried_args.as_iter()
return bytes32(CAT_TAIL_HASH.as_atom())


def get_proposed_puzzle_reveal_from_solution(solution: Program) -> Program:
prog = Program.from_bytes(bytes(solution))
return prog.at("rrfrrrrrf")
Expand Down Expand Up @@ -656,18 +576,6 @@ def get_proposal_args(puzzle: Program) -> Tuple[str, Program]:
raise ValueError("Unrecognised proposal type")


def uncurry_spend_p2_singleton(spend_puzzle: Program) -> Program:
try:
mod, curried_args = spend_puzzle.uncurry()
except ValueError as e:
log.debug("Cannot uncurry spend puzzle: error: %s", e)
raise e

if mod != SPEND_P2_SINGLETON_MOD:
raise ValueError("Not a spend p2_singleton mod.")
return curried_args


def generate_cat_tail(genesis_coin_id: bytes32, treasury_id: bytes32) -> Program:
dao_cat_launcher = create_cat_launcher_for_singleton_id(treasury_id).get_tree_hash()
puzzle = DAO_CAT_TAIL.curry(genesis_coin_id, dao_cat_launcher)
Expand Down
6 changes: 3 additions & 3 deletions chia/wallet/dao_wallet/dao_wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
get_treasury_puzzle,
get_treasury_rules_from_puzzle,
get_update_proposal_puzzle,
singleton_struct_for_id,
uncurry_proposal,
uncurry_proposal_validator,
uncurry_treasury,
Expand All @@ -77,6 +76,7 @@
get_inner_puzzle_from_singleton,
get_most_recent_singleton_coin_from_coin_spend,
get_singleton_id_from_puzzle,
get_singleton_struct_for_id,
)
from chia.wallet.singleton_record import SingletonRecord
from chia.wallet.transaction_record import TransactionRecord
Expand Down Expand Up @@ -947,7 +947,7 @@ async def generate_new_dao_spend(
return None
eve_coin = Coin(launcher_coin.name(), full_treasury_puzzle_hash, uint64(1))

inner_sol = Program.to([0, 0, 0, 0, 0, singleton_struct_for_id(launcher_coin.name())])
inner_sol = Program.to([0, 0, 0, 0, 0, get_singleton_struct_for_id(launcher_coin.name())])
fullsol = Program.to(
[
launcher_proof.to_program(),
Expand Down Expand Up @@ -1191,7 +1191,7 @@ async def generate_treasury_eve_spend(
# delegated_solution ; this is not secure unless the delegated puzzle secures it
# my_singleton_struct

inner_sol = Program.to([0, 0, 0, 0, singleton_struct_for_id(launcher_id)])
inner_sol = Program.to([0, 0, 0, 0, get_singleton_struct_for_id(launcher_id)])
fullsol = Program.to(
[
launcher_proof.to_program(),
Expand Down
14 changes: 7 additions & 7 deletions chia/wallet/puzzles/dao_lockup.clsp
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@
(if (= (f (f conditions)) CREATE_COIN) ; this guarantees that the new coin is obeying the rules - other coins are banned to avoid re-voting
(if (= (f (r (f conditions))) vote_added_puzhash)
(if seen_vote ; assert we haven't already made a coin with the new vote included
(x "wut")
(x)
(if (= (f (r (r (f conditions)))) my_amount) ; we vote with all our value
(if seen_change ; assert that we haven't already recreated ourself in some fashion
(x "butt")
(x)
(c (f conditions) (check_conditions (r conditions) vote_added_puzhash my_amount message vote_amount my_inner_puzhash 1 1))
)
(if (= (f (r (r (f conditions)))) vote_amount) ; we vote with part of our power
(c (f conditions) (check_conditions (r conditions) vote_added_puzhash my_amount message vote_amount my_inner_puzhash 1 seen_change))
(x "cut")
(x)
)
)
)
Expand All @@ -75,20 +75,20 @@
(= (f (r (r (f conditions)))) (- my_amount vote_amount))
) ; we recreate ourselves with unused voting power
(c (f conditions) (check_conditions (r conditions) vote_added_puzhash my_amount message vote_amount my_inner_puzhash seen_vote 1))
(x "hut" (f (r (f conditions))) my_inner_puzhash vote_added_puzhash)
(x)
)
)
(if (= (f (f conditions)) CREATE_PUZZLE_ANNOUNCEMENT) ; this secures the values used to generate message - other messages are banned in case of LIES
(if (= (f (r (f conditions))) message)
(c (f conditions) (check_conditions (r conditions) vote_added_puzhash my_amount message vote_amount my_inner_puzhash seen_vote seen_change))
(x "jut")
(x)
)
(c (f conditions) (check_conditions (r conditions) vote_added_puzhash my_amount message vote_amount my_inner_puzhash seen_vote seen_change))
)
)
(if (all seen_vote seen_change) ; check all value is accounted for
()
(x "jart")
(x)
)
)
)
Expand All @@ -110,7 +110,7 @@
)
(if active_votes
(if (= new_vote_id (f active_votes)) ; check new vote id is not equal to an existent vote id
(x "fart")
(x)
(check_not_previously_voted
SINGLETON_MOD_HASH
SINGLETON_LAUNCHER_PUZHASH
Expand Down
5 changes: 5 additions & 0 deletions chia/wallet/singleton.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,8 @@ def get_most_recent_singleton_coin_from_coin_spend(coin_sol: CoinSpend) -> Optio
if coin.amount % 2 == 1:
return coin
return None


def get_singleton_struct_for_id(id: bytes32) -> Program:
singleton_struct: Program = Program.to((SINGLETON_TOP_LAYER_MOD_HASH, (id, SINGLETON_LAUNCHER_PUZZLE_HASH)))
return singleton_struct

0 comments on commit 8dfb947

Please sign in to comment.