Files
chia-blockchain/chia/wallet/outer_puzzles.py
Matt HauffandGitHub 40db4635a8 [LABS-245] Enable PEP604 Ruff rules (#20269)
* Enable PEP604 Ruff rules

* Fix harcoded signature in test

* Hack CLVMStreamable test with note to fast follow
2025-11-18 12:34:00 -08:00

90 lines
4.2 KiB
Python

from __future__ import annotations
from enum import Enum
from chia_rs.sized_bytes import bytes32
from chia.types.blockchain_format.program import Program
from chia.wallet.cat_wallet.cat_outer_puzzle import CATOuterPuzzle
from chia.wallet.driver_protocol import DriverProtocol
from chia.wallet.nft_wallet.metadata_outer_puzzle import MetadataOuterPuzzle
from chia.wallet.nft_wallet.ownership_outer_puzzle import OwnershipOuterPuzzle
from chia.wallet.nft_wallet.singleton_outer_puzzle import SingletonOuterPuzzle
from chia.wallet.nft_wallet.transfer_program_puzzle import TransferProgramPuzzle
from chia.wallet.puzzle_drivers import PuzzleInfo, Solver
from chia.wallet.uncurried_puzzle import UncurriedPuzzle
from chia.wallet.vc_wallet.cr_outer_puzzle import CROuterPuzzle
from chia.wallet.vc_wallet.vc_drivers import RevocationOuterPuzzle
"""
This file provides a central location for acquiring drivers for outer puzzles like CATs, NFTs, etc.
A driver for a puzzle must include the following functions:
- match(self, puzzle: UncurriedPuzzle) -> Optional[PuzzleInfo]
- Given a puzzle reveal, return a PuzzleInfo object that can be used to reconstruct it later
- get_inner_puzzle(self, constructor: PuzzleInfo, puzzle_reveal: UncurriedPuzzle) -> Optional[Program]:
- Given a PuzzleInfo object and a puzzle reveal, pull out this outer puzzle's inner puzzle
- asset_id(self, constructor: PuzzleInfo) -> Optional[bytes32]
- Given a PuzzleInfo object, generate a 32 byte ID for use in dictionaries, etc.
- construct(self, constructor: PuzzleInfo, inner_puzzle: Program) -> Program
- Given a PuzzleInfo object and an innermost puzzle, construct a puzzle reveal for a coin spend
- solve(self, constructor: PuzzleInfo, solver: Solver, inner_puzzle: Program, inner_solution: Program) -> Program
- Given a PuzzleInfo object, a Solver object, and an innermost puzzle and its solution return a solution for a spend
- The "Solver" object can contain any dictionary, it's up to the driver to enforce the needed elements of the API
- Some classes that wish to integrate with a driver may not have access to all of the info it needs so the driver
needs to raise errors appropriately
"""
class AssetType(Enum):
CAT = "CAT"
SINGLETON = "singleton"
METADATA = "metadata"
OWNERSHIP = "ownership"
ROYALTY_TRANSFER_PROGRAM = "royalty transfer program"
CR = "credential restricted"
REVOCATION_LAYER = "revocation layer"
def match_puzzle(puzzle: UncurriedPuzzle) -> PuzzleInfo | None:
for driver in driver_lookup.values():
potential_info: PuzzleInfo | None = driver.match(puzzle)
if potential_info is not None:
return potential_info
return None
def construct_puzzle(constructor: PuzzleInfo, inner_puzzle: Program) -> Program:
return driver_lookup[AssetType(constructor.type())].construct(constructor, inner_puzzle)
def solve_puzzle(constructor: PuzzleInfo, solver: Solver, inner_puzzle: Program, inner_solution: Program) -> Program:
return driver_lookup[AssetType(constructor.type())].solve(constructor, solver, inner_puzzle, inner_solution)
def get_inner_puzzle(
constructor: PuzzleInfo, puzzle_reveal: UncurriedPuzzle, solution: Program | None = None
) -> Program | None:
return driver_lookup[AssetType(constructor.type())].get_inner_puzzle(constructor, puzzle_reveal, solution)
def get_inner_solution(constructor: PuzzleInfo, solution: Program) -> Program | None:
return driver_lookup[AssetType(constructor.type())].get_inner_solution(constructor, solution)
def create_asset_id(constructor: PuzzleInfo) -> bytes32 | None:
return driver_lookup[AssetType(constructor.type())].asset_id(constructor)
function_args = (match_puzzle, construct_puzzle, solve_puzzle, get_inner_puzzle, get_inner_solution)
driver_lookup: dict[AssetType, DriverProtocol] = {
AssetType.CAT: CATOuterPuzzle(*function_args),
AssetType.SINGLETON: SingletonOuterPuzzle(*function_args),
AssetType.METADATA: MetadataOuterPuzzle(*function_args),
AssetType.OWNERSHIP: OwnershipOuterPuzzle(*function_args),
AssetType.ROYALTY_TRANSFER_PROGRAM: TransferProgramPuzzle(*function_args),
AssetType.CR: CROuterPuzzle(*function_args),
AssetType.REVOCATION_LAYER: RevocationOuterPuzzle(),
}