chia_sdk_driver/layers/datalayer/
delegation_layer.rsuse chia_protocol::Bytes32;
use clvm_traits::{FromClvm, ToClvm};
use clvm_utils::{CurriedProgram, ToTreeHash, TreeHash};
use clvmr::{Allocator, NodePtr};
use hex_literal::hex;
use crate::{DriverError, Layer, Puzzle, SpendContext};
#[allow(clippy::doc_markdown)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DelegationLayer {
pub launcher_id: Bytes32,
pub owner_puzzle_hash: Bytes32,
pub merkle_root: Bytes32,
}
impl DelegationLayer {
pub fn new(launcher_id: Bytes32, owner_puzzle_hash: Bytes32, merkle_root: Bytes32) -> Self {
Self {
launcher_id,
owner_puzzle_hash,
merkle_root,
}
}
}
impl Layer for DelegationLayer {
type Solution = DelegationLayerSolution<NodePtr, NodePtr>;
fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result<Option<Self>, DriverError> {
let Some(puzzle) = puzzle.as_curried() else {
return Ok(None);
};
if puzzle.mod_hash != DELEGATION_LAYER_PUZZLE_HASH {
return Ok(None);
}
let args = DelegationLayerArgs::from_clvm(allocator, puzzle.args)?;
Ok(Some(Self {
launcher_id: args.launcher_id,
owner_puzzle_hash: args.owner_puzzle_hash,
merkle_root: args.merkle_root,
}))
}
fn parse_solution(
allocator: &Allocator,
solution: NodePtr,
) -> Result<Self::Solution, DriverError> {
Ok(DelegationLayerSolution::<NodePtr, NodePtr>::from_clvm(
allocator, solution,
)?)
}
fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
let curried = CurriedProgram {
program: ctx.delegation_layer_puzzle()?,
args: DelegationLayerArgs::new(
self.launcher_id,
self.owner_puzzle_hash,
self.merkle_root,
),
};
ctx.alloc(&curried)
}
fn construct_solution(
&self,
ctx: &mut SpendContext,
solution: Self::Solution,
) -> Result<NodePtr, DriverError> {
ctx.alloc(&solution)
}
}
pub const DELEGATION_LAYER_PUZZLE: [u8; 1027] = hex!(
"
ff02ffff01ff02ff12ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff
ff04ffff02ff81bfff82017f80ffff04ffff02ff16ffff04ff02ffff04ff81bfff80808080ff8080
8080808080808080ffff04ffff01ffffff3381f3ff02ffffa04bf5122f344554c53bde2ebb8cd2b7
e3d1600ad631c385a5d7cce23c7785459aa09dcf97a184f32623d11a73124ceb99a5709b083721e8
78a16d78f596718ba7b2ffa102a12871fee210fb8619291eaea194581cbd2531e4b23759d225f680
6923f63222a102a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5ff
ffff02ffff03ffff09ff82017fff1780ffff0181bfffff01ff02ffff03ffff09ff2fffff02ff1eff
ff04ff02ffff04ffff0bffff0101ff82017f80ffff04ff5fff808080808080ffff01ff02ff1affff
04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff81bfffff04ffff04ff2fffff04ff0bff8080
80ff8080808080808080ffff01ff088080ff018080ff0180ff02ffff03ff2fffff01ff02ffff03ff
ff09ff818fff1880ffff01ff02ff1affff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff6f
ffff04ff81cfff8080808080808080ffff01ff04ffff02ffff03ffff02ffff03ffff09ff818fffff
0181e880ffff01ff22ffff09ff820acfff8080ffff09ff8214cfffff01a057bfd1cb0adda3d94315
053fda723f2028320faa8338225d99f629e3d46d43a98080ffff01ff010180ff0180ffff014fffff
01ff088080ff0180ffff02ff1affff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff6fffff
04ff5fff80808080808080808080ff0180ffff01ff04ffff04ff10ffff04ffff0bff5cffff0bff14
ffff0bff14ff6cff0580ffff0bff14ffff0bff7cffff0bff14ffff0bff14ff6cffff0bffff0101ff
058080ffff0bff14ffff0bff7cffff0bff14ffff0bff14ff6cffff0bffff0101ff0b8080ffff0bff
14ffff0bff7cffff0bff14ffff0bff14ff6cffff0bffff0101ff178080ffff0bff14ffff0bff7cff
ff0bff14ffff0bff14ff6cffff0bffff0101ff819f8080ffff0bff14ff6cff4c808080ff4c808080
ff4c808080ff4c808080ff4c808080ffff04ffff0101ffff04ff81dfff8080808080ff808080ff01
80ffff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff16ffff04ff02ffff04ff09ff8080
8080ffff02ff16ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff
02ffff03ff1bffff01ff02ff1effff04ff02ffff04ffff02ffff03ffff18ffff0101ff1380ffff01
ff0bffff0102ff2bff0580ffff01ff0bffff0102ff05ff2b8080ff0180ffff04ffff04ffff17ff13
ffff0181ff80ff3b80ff8080808080ffff010580ff0180ff018080
"
);
pub const DELEGATION_LAYER_PUZZLE_HASH: TreeHash = TreeHash::new(hex!(
"
c3b249466cb15c51e5abb5c54ef5077c1624ae2e6a0f8f7a3fa197a943a5d62e
"
));
#[derive(ToClvm, FromClvm, Debug, Clone, Copy, PartialEq, Eq)]
#[clvm(curry)]
pub struct DelegationLayerArgs {
pub mod_hash: Bytes32,
pub launcher_id: Bytes32,
pub owner_puzzle_hash: Bytes32,
pub merkle_root: Bytes32,
}
impl DelegationLayerArgs {
pub fn new(launcher_id: Bytes32, owner_puzzle_hash: Bytes32, merkle_root: Bytes32) -> Self {
Self {
mod_hash: DELEGATION_LAYER_PUZZLE_HASH.into(),
launcher_id,
owner_puzzle_hash,
merkle_root,
}
}
}
impl DelegationLayerArgs {
pub fn curry_tree_hash(
launcher_id: Bytes32,
owner_puzzle_hash: Bytes32,
merkle_root: Bytes32,
) -> TreeHash {
CurriedProgram {
program: DELEGATION_LAYER_PUZZLE_HASH,
args: DelegationLayerArgs {
mod_hash: DELEGATION_LAYER_PUZZLE_HASH.into(),
launcher_id,
owner_puzzle_hash,
merkle_root,
},
}
.tree_hash()
}
}
#[derive(ToClvm, FromClvm, Debug, Clone, PartialEq, Eq)]
#[clvm(list)]
pub struct DelegationLayerSolution<P, S> {
pub merkle_proof: Option<(u32, Vec<Bytes32>)>,
pub puzzle_reveal: P,
pub puzzle_solution: S,
}
impl SpendContext {
pub fn delegation_layer_puzzle(&mut self) -> Result<NodePtr, DriverError> {
self.puzzle(DELEGATION_LAYER_PUZZLE_HASH, &DELEGATION_LAYER_PUZZLE)
}
}