2023-01-28 02:09:13 +03:00
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
from chia.types.blockchain_format.program import Program
|
|
|
|
from chia.types.blockchain_format.sized_bytes import bytes32
|
|
|
|
from chia.wallet.puzzles.load_clvm import load_clvm_maybe_recompile
|
|
|
|
from chia.wallet.util.curry_and_treehash import calculate_hash_of_quoted_mod_hash, curry_and_treehash
|
|
|
|
|
2023-04-18 19:27:17 +03:00
|
|
|
SINGLETON_TOP_LAYER_MOD = load_clvm_maybe_recompile("singleton_top_layer_v1_1.clsp")
|
2023-01-28 02:09:13 +03:00
|
|
|
SINGLETON_TOP_LAYER_MOD_HASH = SINGLETON_TOP_LAYER_MOD.get_tree_hash()
|
|
|
|
SINGLETON_TOP_LAYER_MOD_HASH_QUOTED = calculate_hash_of_quoted_mod_hash(SINGLETON_TOP_LAYER_MOD_HASH)
|
2023-04-18 19:27:17 +03:00
|
|
|
SINGLETON_LAUNCHER_PUZZLE = load_clvm_maybe_recompile("singleton_launcher.clsp")
|
2023-04-12 20:34:08 +03:00
|
|
|
SINGLETON_LAUNCHER_PUZZLE_HASH = SINGLETON_LAUNCHER_PUZZLE.get_tree_hash()
|
2023-01-28 02:09:13 +03:00
|
|
|
|
|
|
|
|
2023-04-12 20:34:08 +03:00
|
|
|
def get_inner_puzzle_from_singleton(puzzle: Program) -> Optional[Program]:
|
2023-01-28 02:09:13 +03:00
|
|
|
"""
|
|
|
|
Extract the inner puzzle of a singleton
|
|
|
|
:param puzzle: Singleton puzzle
|
|
|
|
:return: Inner puzzle
|
|
|
|
"""
|
|
|
|
r = puzzle.uncurry()
|
|
|
|
if r is None:
|
|
|
|
return None
|
|
|
|
inner_f, args = r
|
|
|
|
if not is_singleton(inner_f):
|
|
|
|
return None
|
|
|
|
SINGLETON_STRUCT, INNER_PUZZLE = list(args.as_iter())
|
|
|
|
return Program(INNER_PUZZLE)
|
|
|
|
|
|
|
|
|
|
|
|
def is_singleton(inner_f: Program) -> bool:
|
|
|
|
"""
|
|
|
|
Check if a puzzle is a singleton mod
|
|
|
|
:param inner_f: puzzle
|
|
|
|
:return: Boolean
|
|
|
|
"""
|
|
|
|
return inner_f == SINGLETON_TOP_LAYER_MOD
|
|
|
|
|
|
|
|
|
2023-04-12 20:34:08 +03:00
|
|
|
def create_singleton_puzzle_hash(innerpuz_hash: bytes32, launcher_id: bytes32) -> bytes32:
|
2023-01-28 02:09:13 +03:00
|
|
|
"""
|
|
|
|
Return Hash ID of the whole Singleton Puzzle
|
|
|
|
:param innerpuz_hash: Singleton inner puzzle tree hash
|
|
|
|
:param launcher_id: launcher coin name
|
|
|
|
:return: Singleton full puzzle hash
|
|
|
|
"""
|
|
|
|
# singleton_struct = (MOD_HASH . (LAUNCHER_ID . LAUNCHER_PUZZLE_HASH))
|
2023-04-12 20:34:08 +03:00
|
|
|
singleton_struct = Program.to((SINGLETON_TOP_LAYER_MOD_HASH, (launcher_id, SINGLETON_LAUNCHER_PUZZLE_HASH)))
|
2023-01-28 02:09:13 +03:00
|
|
|
|
|
|
|
return curry_and_treehash(SINGLETON_TOP_LAYER_MOD_HASH_QUOTED, singleton_struct.get_tree_hash(), innerpuz_hash)
|
|
|
|
|
|
|
|
|
2023-04-12 20:34:08 +03:00
|
|
|
def create_singleton_puzzle(innerpuz: Program, launcher_id: bytes32) -> Program:
|
2023-01-28 02:09:13 +03:00
|
|
|
"""
|
|
|
|
Create a full Singleton puzzle
|
|
|
|
:param innerpuz: Singleton inner puzzle
|
|
|
|
:param launcher_id:
|
|
|
|
:return: Singleton full puzzle
|
|
|
|
"""
|
|
|
|
# singleton_struct = (MOD_HASH . (LAUNCHER_ID . LAUNCHER_PUZZLE_HASH))
|
2023-04-12 20:34:08 +03:00
|
|
|
singleton_struct = Program.to((SINGLETON_TOP_LAYER_MOD_HASH, (launcher_id, SINGLETON_LAUNCHER_PUZZLE_HASH)))
|
2023-01-28 02:09:13 +03:00
|
|
|
return SINGLETON_TOP_LAYER_MOD.curry(singleton_struct, innerpuz)
|