diff --git a/crates/chia-sdk-driver/src/driver_error.rs b/crates/chia-sdk-driver/src/driver_error.rs index 90c91c79..bcdcbe85 100644 --- a/crates/chia-sdk-driver/src/driver_error.rs +++ b/crates/chia-sdk-driver/src/driver_error.rs @@ -47,7 +47,4 @@ pub enum DriverError { #[error("custom driver error: {0}")] Custom(String), - - #[error("invalid merkle proof")] - InvalidMerkleProof, } diff --git a/crates/chia-sdk-driver/src/layers.rs b/crates/chia-sdk-driver/src/layers.rs index 2b3b1346..12612475 100644 --- a/crates/chia-sdk-driver/src/layers.rs +++ b/crates/chia-sdk-driver/src/layers.rs @@ -1,28 +1,24 @@ -mod augmented_condition_layer; mod cat_layer; mod did_layer; mod nft_ownership_layer; mod nft_state_layer; -mod p2_curried_layer; mod p2_delegated_conditions_layer; mod p2_delegated_singleton_layer; -mod p2_one_of_many_layer; -mod p2_singleton_layer; +mod p2_one_of_many; +mod p2_singleton; mod royalty_transfer_layer; mod settlement_layer; mod singleton_layer; mod standard_layer; -pub use augmented_condition_layer::*; pub use cat_layer::*; pub use did_layer::*; pub use nft_ownership_layer::*; pub use nft_state_layer::*; -pub use p2_curried_layer::*; pub use p2_delegated_conditions_layer::*; pub use p2_delegated_singleton_layer::*; -pub use p2_one_of_many_layer::*; -pub use p2_singleton_layer::*; +pub use p2_one_of_many::*; +pub use p2_singleton::*; pub use royalty_transfer_layer::*; pub use settlement_layer::*; pub use singleton_layer::*; diff --git a/crates/chia-sdk-driver/src/layers/augmented_condition_layer.rs b/crates/chia-sdk-driver/src/layers/augmented_condition_layer.rs deleted file mode 100644 index c64611e5..00000000 --- a/crates/chia-sdk-driver/src/layers/augmented_condition_layer.rs +++ /dev/null @@ -1,117 +0,0 @@ -use chia_sdk_types::Condition; -use clvm_traits::{FromClvm, ToClvm}; -use clvm_utils::{CurriedProgram, TreeHash}; -use clvmr::{Allocator, NodePtr}; -use hex_literal::hex; - -use crate::{DriverError, Layer, Puzzle, SpendContext}; - -/// The augmented condition [`Layer`] allows for adding a condition to a puzzle's output. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct AugmentedConditionLayer { - pub condition: Condition, - pub inner_puzzle: I, -} - -impl Layer for AugmentedConditionLayer -where - T: ToClvm + FromClvm + Clone, - I: Layer, -{ - type Solution = AugmentedConditionSolution; - - fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result, DriverError> { - let Some(puzzle) = puzzle.as_curried() else { - return Ok(None); - }; - - if puzzle.mod_hash != AUGMENTED_CONDITION_PUZZLE_HASH { - return Ok(None); - } - - let args = AugmentedConditionArgs::::from_clvm(allocator, puzzle.args)?; - let Some(inner_layer) = I::parse_puzzle(allocator, args.inner_puzzle)? else { - return Ok(None); - }; - - Ok(Some(Self { - condition: args.condition, - inner_puzzle: inner_layer, - })) - } - - fn parse_solution( - allocator: &Allocator, - solution: NodePtr, - ) -> Result { - Ok(AugmentedConditionSolution::::from_clvm( - allocator, solution, - )?) - } - - fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result { - let curried = CurriedProgram { - program: ctx.augmented_condition_puzzle()?, - args: AugmentedConditionArgs { - condition: self.condition.clone(), - inner_puzzle: self.inner_puzzle.construct_puzzle(ctx)?, - }, - }; - ctx.alloc(&curried) - } - - fn construct_solution( - &self, - ctx: &mut SpendContext, - solution: Self::Solution, - ) -> Result { - ctx.alloc(&solution) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, ToClvm, FromClvm)] -#[clvm(curry)] -pub struct AugmentedConditionArgs { - pub condition: Condition, - pub inner_puzzle: I, -} - -impl AugmentedConditionArgs { - pub fn new(condition: Condition, inner_puzzle: I) -> Self { - Self { - condition, - inner_puzzle, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)] -#[clvm(list)] -pub struct AugmentedConditionSolution { - pub inner_solution: I, -} - -impl AugmentedConditionSolution { - pub fn new(inner_solution: I) -> Self { - Self { inner_solution } - } -} - -pub const AUGMENTED_CONDITION_PUZZLE: [u8; 13] = hex!("ff04ff02ffff02ff05ff0b8080"); - -pub const AUGMENTED_CONDITION_PUZZLE_HASH: TreeHash = TreeHash::new(hex!( - "d303eafa617bedf0bc05850dd014e10fbddf622187dc07891a2aacba9d8a93f6" -)); - -#[cfg(test)] -mod tests { - use super::*; - - use crate::assert_puzzle_hash; - - #[test] - fn test_puzzle_hash() -> anyhow::Result<()> { - assert_puzzle_hash!(AUGMENTED_CONDITION_PUZZLE => AUGMENTED_CONDITION_PUZZLE_HASH); - Ok(()) - } -} diff --git a/crates/chia-sdk-driver/src/layers/datalayer/delegation_layer.rs b/crates/chia-sdk-driver/src/layers/datalayer/delegation_layer.rs index 7a6c0390..5b5fce08 100644 --- a/crates/chia-sdk-driver/src/layers/datalayer/delegation_layer.rs +++ b/crates/chia-sdk-driver/src/layers/datalayer/delegation_layer.rs @@ -4,7 +4,7 @@ use clvm_utils::{CurriedProgram, ToTreeHash, TreeHash}; use clvmr::{Allocator, NodePtr}; use hex_literal::hex; -use crate::{DriverError, Layer, MerkleProof, Puzzle, SpendContext}; +use crate::{DriverError, Layer, Puzzle, SpendContext}; #[allow(clippy::doc_markdown)] /// The Delegation [`Layer`] is used to enable DataLayer delegation capabilities @@ -159,7 +159,7 @@ impl DelegationLayerArgs { #[derive(ToClvm, FromClvm, Debug, Clone, PartialEq, Eq)] #[clvm(list)] pub struct DelegationLayerSolution { - pub merkle_proof: Option, + pub merkle_proof: Option<(u32, Vec)>, pub puzzle_reveal: P, pub puzzle_solution: S, } diff --git a/crates/chia-sdk-driver/src/layers/p2_curried_layer.rs b/crates/chia-sdk-driver/src/layers/p2_curried_layer.rs deleted file mode 100644 index 78dcf231..00000000 --- a/crates/chia-sdk-driver/src/layers/p2_curried_layer.rs +++ /dev/null @@ -1,112 +0,0 @@ -use chia_protocol::Bytes32; -use clvm_traits::{FromClvm, ToClvm}; -use clvm_utils::{CurriedProgram, TreeHash}; -use clvmr::{Allocator, NodePtr}; -use hex_literal::hex; - -use crate::{DriverError, Layer, Puzzle, SpendContext}; - -/// The p2 curried [`Layer`] allows for . -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct P2CurriedLayer { - pub puzzle_hash: Bytes32, -} - -impl Layer for P2CurriedLayer { - type Solution = P2CurriedSolution; - - fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result, DriverError> { - let Some(puzzle) = puzzle.as_curried() else { - return Ok(None); - }; - - if puzzle.mod_hash != P2_CURRIED_PUZZLE_HASH { - return Ok(None); - } - - let args = P2CurriedArgs::from_clvm(allocator, puzzle.args)?; - - Ok(Some(Self { - puzzle_hash: args.puzzle_hash, - })) - } - - fn parse_solution( - allocator: &Allocator, - solution: NodePtr, - ) -> Result { - Ok(P2CurriedSolution::::from_clvm( - allocator, solution, - )?) - } - - fn construct_puzzle(&self, ctx: &mut SpendContext) -> Result { - let curried = CurriedProgram { - program: ctx.p2_curried_puzzle()?, - args: P2CurriedArgs { - puzzle_hash: self.puzzle_hash, - }, - }; - ctx.alloc(&curried) - } - - fn construct_solution( - &self, - ctx: &mut SpendContext, - solution: Self::Solution, - ) -> Result { - ctx.alloc(&solution) - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)] -#[clvm(curry)] -pub struct P2CurriedArgs { - pub puzzle_hash: Bytes32, -} - -impl P2CurriedArgs { - pub fn new(puzzle_hash: Bytes32) -> Self { - Self { puzzle_hash } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)] -#[clvm(list)] -pub struct P2CurriedSolution { - pub puzzle: P, - pub solution: S, -} - -impl P2CurriedSolution { - pub fn new(puzzle: P, solution: S) -> Self { - Self { puzzle, solution } - } -} - -pub const P2_CURRIED_PUZZLE: [u8; 143] = hex!( - " - ff02ffff01ff02ffff03ffff09ff05ffff02ff02ffff04ff02ffff04ff0bff80 - 80808080ffff01ff02ff0bff1780ffff01ff088080ff0180ffff04ffff01ff02 - ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff02ffff04ff02ffff04ff - 09ff80808080ffff02ff02ffff04ff02ffff04ff0dff8080808080ffff01ff0b - ffff0101ff058080ff0180ff018080 - " -); - -pub const P2_CURRIED_PUZZLE_HASH: TreeHash = TreeHash::new(hex!( - "13e29a62b42cd2ef72a79e4bacdc59733ca6310d65af83d349360d36ec622363" -)); - -#[cfg(test)] -mod tests { - use super::*; - - use crate::assert_puzzle_hash; - - #[test] - fn test_puzzle_hash() -> anyhow::Result<()> { - assert_puzzle_hash!(P2_CURRIED_PUZZLE => P2_CURRIED_PUZZLE_HASH); - Ok(()) - } -} diff --git a/crates/chia-sdk-driver/src/layers/p2_one_of_many_layer.rs b/crates/chia-sdk-driver/src/layers/p2_one_of_many.rs similarity index 75% rename from crates/chia-sdk-driver/src/layers/p2_one_of_many_layer.rs rename to crates/chia-sdk-driver/src/layers/p2_one_of_many.rs index 1a831cbb..fd638432 100644 --- a/crates/chia-sdk-driver/src/layers/p2_one_of_many_layer.rs +++ b/crates/chia-sdk-driver/src/layers/p2_one_of_many.rs @@ -1,25 +1,19 @@ use chia_protocol::Bytes32; use clvm_traits::{FromClvm, ToClvm}; -use clvm_utils::{CurriedProgram, ToTreeHash, TreeHash}; +use clvm_utils::{CurriedProgram, TreeHash}; use clvmr::{Allocator, NodePtr}; use hex_literal::hex; -use crate::{DriverError, Layer, MerkleProof, Puzzle, SpendContext}; +use crate::{DriverError, Layer, Puzzle, SpendContext}; /// The p2 1 of n [`Layer`] allows for picking from several delegated puzzles at runtime without revealing up front. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct P2OneOfManyLayer { +pub struct P2OneOfMany { /// The merkle root used to lookup the delegated puzzle as part of the solution. pub merkle_root: Bytes32, } -impl P2OneOfManyLayer { - pub fn new(merkle_root: Bytes32) -> Self { - Self { merkle_root } - } -} - -impl Layer for P2OneOfManyLayer { +impl Layer for P2OneOfMany { type Solution = P2OneOfManySolution; fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result, DriverError> { @@ -66,46 +60,20 @@ impl Layer for P2OneOfManyLayer { } } -impl ToTreeHash for P2OneOfManyLayer { - fn tree_hash(&self) -> TreeHash { - CurriedProgram { - program: P2_ONE_OF_MANY_PUZZLE_HASH, - args: P2OneOfManyArgs::new(self.merkle_root), - } - .tree_hash() - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)] #[clvm(curry)] pub struct P2OneOfManyArgs { pub merkle_root: Bytes32, } -impl P2OneOfManyArgs { - pub fn new(merkle_root: Bytes32) -> Self { - Self { merkle_root } - } -} - -#[derive(Debug, Clone, PartialEq, Eq, ToClvm, FromClvm)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)] #[clvm(list)] pub struct P2OneOfManySolution { - pub merkle_proof: MerkleProof, + pub merkle_proof: Bytes32, pub puzzle: P, pub solution: S, } -impl P2OneOfManySolution { - pub fn new(merkle_proof: MerkleProof, puzzle: P, solution: S) -> Self { - Self { - merkle_proof, - puzzle, - solution, - } - } -} - pub const P2_ONE_OF_MANY_PUZZLE: [u8; 280] = hex!( " ff02ffff01ff02ffff03ffff09ff05ffff02ff06ffff04ff02ffff04ffff0bff diff --git a/crates/chia-sdk-driver/src/layers/p2_singleton_layer.rs b/crates/chia-sdk-driver/src/layers/p2_singleton.rs similarity index 97% rename from crates/chia-sdk-driver/src/layers/p2_singleton_layer.rs rename to crates/chia-sdk-driver/src/layers/p2_singleton.rs index 24a4e21b..ac8da523 100644 --- a/crates/chia-sdk-driver/src/layers/p2_singleton_layer.rs +++ b/crates/chia-sdk-driver/src/layers/p2_singleton.rs @@ -10,11 +10,11 @@ use crate::{DriverError, Layer, Puzzle, Spend, SpendContext}; /// The p2 singleton [`Layer`] allows for requiring that a /// singleton be spent alongside this coin to authorize it. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct P2SingletonLayer { +pub struct P2Singleton { pub launcher_id: Bytes32, } -impl P2SingletonLayer { +impl P2Singleton { pub fn new(launcher_id: Bytes32) -> Self { Self { launcher_id } } @@ -55,7 +55,7 @@ impl P2SingletonLayer { } } -impl Layer for P2SingletonLayer { +impl Layer for P2Singleton { type Solution = P2SingletonSolution; fn parse_puzzle(allocator: &Allocator, puzzle: Puzzle) -> Result, DriverError> { @@ -104,7 +104,7 @@ impl Layer for P2SingletonLayer { } } -impl ToTreeHash for P2SingletonLayer { +impl ToTreeHash for P2Singleton { fn tree_hash(&self) -> TreeHash { P2SingletonArgs::curry_tree_hash(self.launcher_id) } @@ -194,7 +194,7 @@ mod tests { let launcher_id = launcher.coin().coin_id(); let (create_singleton, singleton) = launcher.spend(ctx, puzzle_hash, ())?; - let p2_singleton = P2SingletonLayer::new(launcher_id); + let p2_singleton = P2Singleton::new(launcher_id); let p2_singleton_hash = p2_singleton.tree_hash().into(); p2.spend( diff --git a/crates/chia-sdk-driver/src/merkle_tree.rs b/crates/chia-sdk-driver/src/merkle_tree.rs index 6d700bdf..951fadd0 100644 --- a/crates/chia-sdk-driver/src/merkle_tree.rs +++ b/crates/chia-sdk-driver/src/merkle_tree.rs @@ -1,8 +1,6 @@ use std::collections::HashMap; -use std::fmt::Debug; use chia_protocol::Bytes32; -use clvm_traits::{FromClvm, ToClvm}; use clvmr::sha2::Sha256; const HASH_TREE_PREFIX: &[u8] = &[2]; @@ -10,23 +8,11 @@ const HASH_LEAF_PREFIX: &[u8] = &[1]; #[derive(Debug, Clone)] pub struct MerkleTree { - root: Bytes32, - proofs: HashMap, -} - -#[derive(Debug, Clone, PartialEq, Eq, ToClvm, FromClvm)] -#[clvm(list)] -pub struct MerkleProof { - pub path: u32, - #[clvm(rest)] - pub proof: Vec, + pub root: Bytes32, + pub proofs: HashMap)>, } -impl MerkleProof { - pub fn new(path: u32, proof: Vec) -> Self { - Self { path, proof } - } -} +use std::fmt::Debug; #[derive(Debug, Clone)] pub enum BinaryTree { @@ -47,15 +33,7 @@ impl MerkleTree { Self { root, proofs } } - pub fn proof(&self, leaf: Bytes32) -> Option { - self.proofs.get(&leaf).cloned() - } - - pub fn root(&self) -> Bytes32 { - self.root - } - - fn build_merkle_tree(leaves: &[Bytes32]) -> (Bytes32, HashMap) { + fn build_merkle_tree(leaves: &[Bytes32]) -> (Bytes32, HashMap)>) { let binary_tree = MerkleTree::list_to_binary_tree(leaves); MerkleTree::build_merkle_tree_from_binary_tree(&binary_tree) } @@ -85,12 +63,12 @@ impl MerkleTree { fn build_merkle_tree_from_binary_tree( tuples: &BinaryTree, - ) -> (Bytes32, HashMap) { + ) -> (Bytes32, HashMap)>) { match tuples { BinaryTree::Leaf(t) => { let hash = MerkleTree::sha256(&[HASH_LEAF_PREFIX, t]); let mut proof = HashMap::new(); - proof.insert(*t, MerkleProof::new(0, vec![])); + proof.insert(*t, (0, vec![])); (hash, proof) } BinaryTree::Node(left, right) => { @@ -101,21 +79,25 @@ impl MerkleTree { let new_root = MerkleTree::sha256(&[HASH_TREE_PREFIX, &left_root, &right_root]); let mut new_proofs = HashMap::new(); - for (name, MerkleProof { path, mut proof }) in left_proofs { + for (name, (path, mut proof)) in left_proofs { proof.push(right_root); - new_proofs.insert(name, MerkleProof::new(path, proof)); + new_proofs.insert(name, (path, proof)); } - for (name, MerkleProof { path, mut proof }) in right_proofs { + for (name, (path, mut proof)) in right_proofs { let path = path | (1 << proof.len()); proof.push(left_root); - new_proofs.insert(name, MerkleProof::new(path, proof)); + new_proofs.insert(name, (path, proof)); } (new_root, new_proofs) } } } + + pub fn get_proof(&self, leaf: Bytes32) -> Option<(u32, Vec)> { + self.proofs.get(&leaf).cloned() + } } #[cfg(test)] @@ -180,10 +162,10 @@ mod tests { ) { let merkle_tree = MerkleTree::new(leaves); - assert_eq!(merkle_tree.root(), expected_root); + assert_eq!(merkle_tree.root, expected_root); for (leaf, path, proof) in expected_proofs { - assert_eq!(merkle_tree.proof(leaf), Some(MerkleProof::new(path, proof))); + assert_eq!(merkle_tree.get_proof(leaf), Some((path, proof))); } } } diff --git a/crates/chia-sdk-driver/src/primitives.rs b/crates/chia-sdk-driver/src/primitives.rs index 481857b5..84593409 100644 --- a/crates/chia-sdk-driver/src/primitives.rs +++ b/crates/chia-sdk-driver/src/primitives.rs @@ -1,12 +1,10 @@ mod cat; -mod clawback; mod did; mod intermediate_launcher; mod launcher; mod nft; pub use cat::*; -pub use clawback::*; pub use did::*; pub use intermediate_launcher::*; pub use launcher::*; diff --git a/crates/chia-sdk-driver/src/primitives/clawback.rs b/crates/chia-sdk-driver/src/primitives/clawback.rs deleted file mode 100644 index 2bd0f15e..00000000 --- a/crates/chia-sdk-driver/src/primitives/clawback.rs +++ /dev/null @@ -1,193 +0,0 @@ -use std::num::NonZeroU64; - -use chia_protocol::Bytes32; -use chia_sdk_types::Condition; -use clvm_utils::{CurriedProgram, ToTreeHash, TreeHash}; -use clvmr::NodePtr; - -use crate::{ - AugmentedConditionArgs, AugmentedConditionSolution, DriverError, Layer, MerkleTree, - P2CurriedArgs, P2CurriedSolution, P2OneOfManyLayer, P2OneOfManySolution, Spend, SpendContext, - AUGMENTED_CONDITION_PUZZLE_HASH, P2_CURRIED_PUZZLE_HASH, -}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Clawback { - /// The number of seconds until this clawback can be claimed by the recipient. - pub timelock: NonZeroU64, - /// The original sender of the coin, who can claw it back until claimed. - pub sender_puzzle_hash: Bytes32, - /// The intended recipient who can claim after the timelock period is up. - pub recipient_puzzle_hash: Bytes32, -} - -impl Clawback { - pub fn claim_path_puzzle_hash(&self) -> TreeHash { - CurriedProgram { - program: AUGMENTED_CONDITION_PUZZLE_HASH, - args: AugmentedConditionArgs::new( - Condition::::assert_seconds_relative(self.timelock.into()), - TreeHash::from(self.recipient_puzzle_hash), - ), - } - .tree_hash() - } - - pub fn claim_path_puzzle( - &self, - ctx: &mut SpendContext, - inner_puzzle: NodePtr, - ) -> Result { - let mod_puzzle = ctx.augmented_condition_puzzle()?; - - ctx.alloc(&CurriedProgram { - program: mod_puzzle, - args: AugmentedConditionArgs::new( - Condition::::assert_seconds_relative(self.timelock.into()), - inner_puzzle, - ), - }) - } - - pub fn clawback_path_puzzle_hash(&self) -> TreeHash { - CurriedProgram { - program: P2_CURRIED_PUZZLE_HASH, - args: P2CurriedArgs::new(self.sender_puzzle_hash), - } - .tree_hash() - } - - pub fn clawback_path_puzzle(&self, ctx: &mut SpendContext) -> Result { - let mod_puzzle = ctx.p2_curried_puzzle()?; - - ctx.alloc(&CurriedProgram { - program: mod_puzzle, - args: P2CurriedArgs::new(self.sender_puzzle_hash), - }) - } - - pub fn merkle_tree(&self) -> MerkleTree { - MerkleTree::new(&[ - self.claim_path_puzzle_hash().into(), - self.clawback_path_puzzle_hash().into(), - ]) - } - - pub fn to_layer(&self) -> P2OneOfManyLayer { - P2OneOfManyLayer::new(self.merkle_tree().root()) - } - - pub fn claim_spend(&self, ctx: &mut SpendContext, spend: Spend) -> Result { - let merkle_tree = self.merkle_tree(); - - let puzzle = self.claim_path_puzzle(ctx, spend.puzzle)?; - let solution = ctx.alloc(&AugmentedConditionSolution::new(spend.solution))?; - - let proof = merkle_tree - .proof(ctx.tree_hash(puzzle).into()) - .ok_or(DriverError::InvalidMerkleProof)?; - - P2OneOfManyLayer::new(merkle_tree.root()) - .construct_spend(ctx, P2OneOfManySolution::new(proof, puzzle, solution)) - } - - pub fn clawback_spend( - &self, - ctx: &mut SpendContext, - spend: Spend, - ) -> Result { - let merkle_tree = self.merkle_tree(); - - let puzzle = self.clawback_path_puzzle(ctx)?; - let solution = ctx.alloc(&P2CurriedSolution::new(spend.puzzle, spend.solution))?; - - let proof = merkle_tree - .proof(ctx.tree_hash(puzzle).into()) - .ok_or(DriverError::InvalidMerkleProof)?; - - P2OneOfManyLayer::new(merkle_tree.root()) - .construct_spend(ctx, P2OneOfManySolution::new(proof, puzzle, solution)) - } -} - -#[cfg(test)] -mod tests { - use chia_protocol::Coin; - use chia_sdk_test::Simulator; - use chia_sdk_types::Conditions; - - use crate::{SpendWithConditions, StandardLayer}; - - use super::*; - - #[test] - #[allow(clippy::similar_names)] - fn test_clawback_coin_claim() -> anyhow::Result<()> { - let mut sim = Simulator::new(); - let ctx = &mut SpendContext::new(); - - let (alice_sk, alice_pk, alice_puzzle_hash, alice_coin) = sim.child_p2(1, 0)?; - let alice = StandardLayer::new(alice_pk); - - let (bob_sk, bob_pk, bob_puzzle_hash, _) = sim.child_p2(1, 1)?; - let bob = StandardLayer::new(bob_pk); - - let clawback = Clawback { - timelock: NonZeroU64::MIN, - sender_puzzle_hash: alice_puzzle_hash, - recipient_puzzle_hash: bob_puzzle_hash, - }; - let clawback_puzzle_hash = clawback.to_layer().tree_hash().into(); - - alice.spend( - ctx, - alice_coin, - Conditions::new().create_coin(clawback_puzzle_hash, 1, Vec::new()), - )?; - let clawback_coin = Coin::new(alice_coin.coin_id(), clawback_puzzle_hash, 1); - - sim.spend_coins(ctx.take(), &[alice_sk])?; - - let bob_inner = bob.spend_with_conditions(ctx, Conditions::new().reserve_fee(1))?; - let claim_spend = clawback.claim_spend(ctx, bob_inner)?; - ctx.spend(clawback_coin, claim_spend)?; - - sim.spend_coins(ctx.take(), &[bob_sk])?; - - Ok(()) - } - - #[test] - #[allow(clippy::similar_names)] - fn test_clawback_coin_clawback() -> anyhow::Result<()> { - let mut sim = Simulator::new(); - let ctx = &mut SpendContext::new(); - - let (sk, pk, puzzle_hash, coin) = sim.new_p2(1)?; - let p2 = StandardLayer::new(pk); - - let clawback = Clawback { - timelock: NonZeroU64::MAX, - sender_puzzle_hash: puzzle_hash, - recipient_puzzle_hash: Bytes32::default(), - }; - let clawback_puzzle_hash = clawback.to_layer().tree_hash().into(); - - p2.spend( - ctx, - coin, - Conditions::new().create_coin(clawback_puzzle_hash, 1, Vec::new()), - )?; - let clawback_coin = Coin::new(coin.coin_id(), clawback_puzzle_hash, 1); - - sim.spend_coins(ctx.take(), &[sk.clone()])?; - - let inner = p2.spend_with_conditions(ctx, Conditions::new().reserve_fee(1))?; - let clawback_spend = clawback.clawback_spend(ctx, inner)?; - ctx.spend(clawback_coin, clawback_spend)?; - - sim.spend_coins(ctx.take(), &[sk])?; - - Ok(()) - } -} diff --git a/crates/chia-sdk-driver/src/primitives/datalayer/datastore.rs b/crates/chia-sdk-driver/src/primitives/datalayer/datastore.rs index 5687a790..6324b771 100644 --- a/crates/chia-sdk-driver/src/primitives/datalayer/datastore.rs +++ b/crates/chia-sdk-driver/src/primitives/datalayer/datastore.rs @@ -76,7 +76,7 @@ where let inner_solution = DelegationLayerSolution { // if running owner puzzle, the line below will return 'None', thus ensuring correct puzzle behavior - merkle_proof: tree.proof(delegated_puzzle_hash.into()), + merkle_proof: tree.get_proof(delegated_puzzle_hash.into()), puzzle_reveal: inner_spend.puzzle, puzzle_solution: inner_spend.solution, }; @@ -534,7 +534,7 @@ impl DataStore { let new_puzzle_hash = if new_delegated_puzzles.is_empty() { new_inner_puzzle_hash } else { - let new_merkle_root = get_merkle_tree(ctx, new_delegated_puzzles.clone())?.root(); + let new_merkle_root = get_merkle_tree(ctx, new_delegated_puzzles.clone())?.root; DelegationLayerArgs::curry_tree_hash( launcher_id, new_inner_puzzle_hash, @@ -821,7 +821,7 @@ pub mod tests { // admin: remove writer from delegated puzzles let delegated_puzzles = vec![admin_delegated_puzzle, oracle_delegated_puzzle]; let new_merkle_tree = get_merkle_tree(ctx, delegated_puzzles.clone())?; - let new_merkle_root = new_merkle_tree.root(); + let new_merkle_root = new_merkle_tree.root; let new_merkle_root_condition = UpdateDataStoreMerkleRoot { new_merkle_root, @@ -1038,7 +1038,7 @@ pub mod tests { let new_merkle_tree = get_merkle_tree(ctx, dst_delegated_puzzles.clone())?; let new_merkle_root_condition = UpdateDataStoreMerkleRoot { - new_merkle_root: new_merkle_tree.root(), + new_merkle_root: new_merkle_tree.root, memos: DataStore::::get_recreation_memos( src_datastore.info.launcher_id, owner_puzzle_hash.into(), @@ -1948,7 +1948,7 @@ pub mod tests { let merkle_tree = get_merkle_tree(ctx, delegated_puzzles.clone())?; let delegation_layer = - DelegationLayer::new(Bytes32::default(), Bytes32::default(), merkle_tree.root()); + DelegationLayer::new(Bytes32::default(), Bytes32::default(), merkle_tree.root); let puzzle_ptr = delegation_layer.construct_puzzle(ctx)?; @@ -1956,7 +1956,7 @@ pub mod tests { let solution_ptr = delegation_layer.construct_solution( ctx, DelegationLayerSolution { - merkle_proof: merkle_tree.proof(delegated_puzzle_hash.into()), + merkle_proof: merkle_tree.get_proof(delegated_puzzle_hash.into()), puzzle_reveal: inner_spend.puzzle, puzzle_solution: inner_spend.solution, }, diff --git a/crates/chia-sdk-driver/src/primitives/datalayer/datastore_info.rs b/crates/chia-sdk-driver/src/primitives/datalayer/datastore_info.rs index 274b0006..88224816 100644 --- a/crates/chia-sdk-driver/src/primitives/datalayer/datastore_info.rs +++ b/crates/chia-sdk-driver/src/primitives/datalayer/datastore_info.rs @@ -208,7 +208,7 @@ impl DataStoreInfo { DelegationLayer::new( self.launcher_id, self.owner_puzzle_hash, - get_merkle_tree(ctx, self.delegated_puzzles)?.root(), + get_merkle_tree(ctx, self.delegated_puzzles)?.root, ), ), )) @@ -244,7 +244,7 @@ impl DataStoreInfo { mod_hash: DELEGATION_LAYER_PUZZLE_HASH.into(), launcher_id: self.launcher_id, owner_puzzle_hash: self.owner_puzzle_hash, - merkle_root: get_merkle_tree(ctx, self.delegated_puzzles.clone())?.root(), + merkle_root: get_merkle_tree(ctx, self.delegated_puzzles.clone())?.root, }, } .tree_hash(), diff --git a/crates/chia-sdk-driver/src/primitives/datalayer/datastore_launcher.rs b/crates/chia-sdk-driver/src/primitives/datalayer/datastore_launcher.rs index b8ae4fe2..c2f0c3c4 100644 --- a/crates/chia-sdk-driver/src/primitives/datalayer/datastore_launcher.rs +++ b/crates/chia-sdk-driver/src/primitives/datalayer/datastore_launcher.rs @@ -34,7 +34,7 @@ impl Launcher { DelegationLayerArgs::curry_tree_hash( launcher_id, owner_puzzle_hash.into(), - get_merkle_tree(ctx, delegated_puzzles.clone())?.root(), + get_merkle_tree(ctx, delegated_puzzles.clone())?.root, ) }; diff --git a/crates/chia-sdk-driver/src/puzzle.rs b/crates/chia-sdk-driver/src/puzzle.rs index ee1ba305..5a464d90 100644 --- a/crates/chia-sdk-driver/src/puzzle.rs +++ b/crates/chia-sdk-driver/src/puzzle.rs @@ -1,4 +1,4 @@ -use clvm_traits::{FromClvm, FromClvmError}; +use clvm_traits::FromClvm; use clvm_utils::{tree_hash, CurriedProgram, ToTreeHash, TreeHash}; use clvmr::{Allocator, NodePtr}; @@ -75,12 +75,6 @@ impl PartialEq for Puzzle { impl Eq for Puzzle {} -impl FromClvm for Puzzle { - fn from_clvm(allocator: &Allocator, puzzle: NodePtr) -> Result { - Ok(Self::parse(allocator, puzzle)) - } -} - #[derive(Debug, Clone, Copy)] pub struct CurriedPuzzle { pub curried_puzzle_hash: TreeHash, diff --git a/crates/chia-sdk-driver/src/spend_context.rs b/crates/chia-sdk-driver/src/spend_context.rs index eedaf15f..b0be1d14 100644 --- a/crates/chia-sdk-driver/src/spend_context.rs +++ b/crates/chia-sdk-driver/src/spend_context.rs @@ -27,11 +27,9 @@ use clvm_utils::{tree_hash, TreeHash}; use clvmr::{serde::node_from_bytes, Allocator, NodePtr}; use crate::{ - DriverError, Spend, AUGMENTED_CONDITION_PUZZLE, AUGMENTED_CONDITION_PUZZLE_HASH, - P2_CURRIED_PUZZLE, P2_CURRIED_PUZZLE_HASH, P2_DELEGATED_CONDITIONS_PUZZLE, - P2_DELEGATED_CONDITIONS_PUZZLE_HASH, P2_DELEGATED_SINGLETON_PUZZLE, - P2_DELEGATED_SINGLETON_PUZZLE_HASH, P2_ONE_OF_MANY_PUZZLE, P2_ONE_OF_MANY_PUZZLE_HASH, - P2_SINGLETON_PUZZLE, P2_SINGLETON_PUZZLE_HASH, + DriverError, Spend, P2_DELEGATED_CONDITIONS_PUZZLE, P2_DELEGATED_CONDITIONS_PUZZLE_HASH, + P2_DELEGATED_SINGLETON_PUZZLE, P2_DELEGATED_SINGLETON_PUZZLE_HASH, P2_ONE_OF_MANY_PUZZLE, + P2_ONE_OF_MANY_PUZZLE_HASH, P2_SINGLETON_PUZZLE, P2_SINGLETON_PUZZLE_HASH, }; /// A wrapper around [`Allocator`] that caches puzzles and keeps track of a list of [`CoinSpend`]. @@ -211,16 +209,6 @@ impl SpendContext { ) } - /// Allocate the augmented condition puzzle and return its pointer. - pub fn augmented_condition_puzzle(&mut self) -> Result { - self.puzzle(AUGMENTED_CONDITION_PUZZLE_HASH, &AUGMENTED_CONDITION_PUZZLE) - } - - /// Allocate the p2 curried puzzle and return its pointer. - pub fn p2_curried_puzzle(&mut self) -> Result { - self.puzzle(P2_CURRIED_PUZZLE_HASH, &P2_CURRIED_PUZZLE) - } - /// Preload a puzzle into the cache. pub fn preload(&mut self, puzzle_hash: TreeHash, ptr: NodePtr) { self.puzzles.insert(puzzle_hash, ptr); diff --git a/crates/chia-sdk-test/src/simulator.rs b/crates/chia-sdk-test/src/simulator.rs index 80576a8e..96da6e1b 100644 --- a/crates/chia-sdk-test/src/simulator.rs +++ b/crates/chia-sdk-test/src/simulator.rs @@ -178,36 +178,6 @@ impl Simulator { let mut added_hints = IndexMap::new(); let mut puzzle_solutions = IndexMap::new(); - if self.height < conds.height_absolute { - return Err(SimulatorError::Validation( - ErrorCode::AssertHeightAbsoluteFailed, - )); - } - - // TODO: Tick time differently? - if u64::from(self.height) < conds.seconds_absolute { - return Err(SimulatorError::Validation( - ErrorCode::AssertSecondsAbsoluteFailed, - )); - } - - if let Some(height) = conds.before_height_absolute { - if height < self.height { - return Err(SimulatorError::Validation( - ErrorCode::AssertBeforeHeightAbsoluteFailed, - )); - } - } - - // TODO: Tick time differently? - if let Some(seconds) = conds.before_seconds_absolute { - if seconds < self.height.into() { - return Err(SimulatorError::Validation( - ErrorCode::AssertBeforeSecondsAbsoluteFailed, - )); - } - } - for coin_spend in spend_bundle.coin_spends { puzzle_solutions.insert( coin_spend.coin.coin_id(), @@ -247,64 +217,6 @@ impl Simulator { .copied() .unwrap_or(CoinState::new(coin, None, Some(self.height))); - if let Some(relative_height) = spend.height_relative { - let Some(created_height) = coin_state.created_height else { - return Err(SimulatorError::Validation( - ErrorCode::EphemeralRelativeCondition, - )); - }; - - if self.height < created_height + relative_height { - return Err(SimulatorError::Validation( - ErrorCode::AssertHeightRelativeFailed, - )); - } - } - - // TODO: Tick time differently? - if let Some(relative_seconds) = spend.seconds_relative { - let Some(created_height) = coin_state.created_height else { - return Err(SimulatorError::Validation( - ErrorCode::EphemeralRelativeCondition, - )); - }; - - if u64::from(self.height) < u64::from(created_height) + relative_seconds { - return Err(SimulatorError::Validation( - ErrorCode::AssertSecondsRelativeFailed, - )); - } - } - - if let Some(relative_height) = spend.before_height_relative { - let Some(created_height) = coin_state.created_height else { - return Err(SimulatorError::Validation( - ErrorCode::EphemeralRelativeCondition, - )); - }; - - if created_height + relative_height < self.height { - return Err(SimulatorError::Validation( - ErrorCode::AssertBeforeHeightRelativeFailed, - )); - } - } - - // TODO: Tick time differently? - if let Some(relative_seconds) = spend.before_seconds_relative { - let Some(created_height) = coin_state.created_height else { - return Err(SimulatorError::Validation( - ErrorCode::EphemeralRelativeCondition, - )); - }; - - if u64::from(created_height) + relative_seconds < u64::from(self.height) { - return Err(SimulatorError::Validation( - ErrorCode::AssertBeforeSecondsRelativeFailed, - )); - } - } - removed_coins.insert(spend.coin_id, coin_state); } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index b0c4ac2b..3a3c2eb9 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,10 +1,4 @@ [toolchain] -channel = "1.82.0" +channel = "1.81.0" components = ["rustfmt", "clippy"] -targets = [ - "x86_64-apple-darwin", - "x86_64-pc-windows-msvc", - "x86_64-unknown-linux-gnu", - "aarch64-apple-darwin", - "aarch64-unknown-linux-gnu", -] +targets = ["x86_64-apple-darwin", "x86_64-pc-windows-msvc", "x86_64-unknown-linux-gnu", "aarch64-apple-darwin", "aarch64-unknown-linux-gnu"]