mirror of
https://github.com/Chia-Network/chia-blockchain.git
synced 2026-08-29 02:24:35 -05:00
* Enable PEP604 Ruff rules * Fix harcoded signature in test * Hack CLVMStreamable test with note to fast follow
112 lines
3.9 KiB
Python
112 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
from chia_puzzles_py.programs import (
|
|
SINGLETON_LAUNCHER,
|
|
SINGLETON_LAUNCHER_HASH,
|
|
SINGLETON_TOP_LAYER_V1_1,
|
|
SINGLETON_TOP_LAYER_V1_1_HASH,
|
|
)
|
|
from chia_rs import CoinSpend
|
|
from chia_rs.sized_bytes import bytes32
|
|
|
|
from chia.types.blockchain_format.coin import Coin
|
|
from chia.types.blockchain_format.program import Program, uncurry
|
|
from chia.types.blockchain_format.serialized_program import SerializedProgram
|
|
from chia.wallet.util.compute_additions import compute_additions
|
|
from chia.wallet.util.curry_and_treehash import (
|
|
calculate_hash_of_quoted_mod_hash,
|
|
curry_and_treehash,
|
|
shatree_atom,
|
|
shatree_pair,
|
|
)
|
|
|
|
SINGLETON_TOP_LAYER_MOD = Program.from_bytes(SINGLETON_TOP_LAYER_V1_1)
|
|
SINGLETON_TOP_LAYER_MOD_HASH = bytes32(SINGLETON_TOP_LAYER_V1_1_HASH)
|
|
SINGLETON_TOP_LAYER_MOD_HASH_TREE_HASH = shatree_atom(SINGLETON_TOP_LAYER_MOD_HASH)
|
|
SINGLETON_TOP_LAYER_MOD_HASH_QUOTED = calculate_hash_of_quoted_mod_hash(SINGLETON_TOP_LAYER_MOD_HASH)
|
|
SINGLETON_LAUNCHER_PUZZLE = Program.from_bytes(SINGLETON_LAUNCHER)
|
|
SINGLETON_LAUNCHER_PUZZLE_HASH = bytes32(SINGLETON_LAUNCHER_HASH)
|
|
SINGLETON_LAUNCHER_PUZZLE_HASH_TREE_HASH = shatree_atom(SINGLETON_LAUNCHER_PUZZLE_HASH)
|
|
|
|
|
|
def get_inner_puzzle_from_singleton(puzzle: Program | SerializedProgram) -> Program | None:
|
|
"""
|
|
Extract the inner puzzle of a singleton
|
|
:param puzzle: Singleton puzzle
|
|
:return: Inner puzzle
|
|
"""
|
|
r = uncurry(puzzle)
|
|
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 get_singleton_id_from_puzzle(puzzle: Program | SerializedProgram) -> bytes32 | None:
|
|
"""
|
|
Extract the singleton ID from a singleton puzzle
|
|
:param puzzle: Singleton puzzle
|
|
:return: Inner puzzle
|
|
"""
|
|
r = uncurry(puzzle)
|
|
if r is None:
|
|
return None # pragma: no cover
|
|
inner_f, args = r
|
|
if not is_singleton(inner_f):
|
|
return None
|
|
SINGLETON_STRUCT, _INNER_PUZZLE = list(args.as_iter())
|
|
return bytes32(Program(SINGLETON_STRUCT).rest().first().as_atom())
|
|
|
|
|
|
def is_singleton(inner_f: Program | SerializedProgram) -> bool:
|
|
"""
|
|
Check if a puzzle is a singleton mod
|
|
:param inner_f: puzzle
|
|
:return: Boolean
|
|
"""
|
|
return inner_f == SINGLETON_TOP_LAYER_MOD
|
|
|
|
|
|
def create_singleton_puzzle_hash(innerpuz_hash: bytes32, launcher_id: bytes32) -> bytes32:
|
|
"""
|
|
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))
|
|
singleton_struct = shatree_pair(
|
|
SINGLETON_TOP_LAYER_MOD_HASH_TREE_HASH,
|
|
shatree_pair(shatree_atom(launcher_id), SINGLETON_LAUNCHER_PUZZLE_HASH_TREE_HASH),
|
|
)
|
|
|
|
return curry_and_treehash(SINGLETON_TOP_LAYER_MOD_HASH_QUOTED, singleton_struct, innerpuz_hash)
|
|
|
|
|
|
def create_singleton_puzzle(innerpuz: Program | SerializedProgram, launcher_id: bytes32) -> Program:
|
|
"""
|
|
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))
|
|
singleton_struct = Program.to((SINGLETON_TOP_LAYER_MOD_HASH, (launcher_id, SINGLETON_LAUNCHER_PUZZLE_HASH)))
|
|
return SINGLETON_TOP_LAYER_MOD.curry(singleton_struct, innerpuz)
|
|
|
|
|
|
def get_most_recent_singleton_coin_from_coin_spend(coin_sol: CoinSpend) -> Coin | None:
|
|
additions: list[Coin] = compute_additions(coin_sol)
|
|
for coin in additions:
|
|
if coin.amount % 2 == 1:
|
|
return coin
|
|
return None # pragma: no cover
|
|
|
|
|
|
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
|