Skip to content

Commit

Permalink
Merge pull request #48 from Rigidity/condition-constructors
Browse files Browse the repository at this point in the history
Refactor driver code
  • Loading branch information
Rigidity authored Jun 10, 2024
2 parents a844bb4 + aaf56bf commit 051c828
Show file tree
Hide file tree
Showing 33 changed files with 945 additions and 1,277 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/chia-sdk-driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ clvm-utils = { workspace = true }
clvmr = { workspace = true }
thiserror = { workspace = true }
chia-sdk-types = { workspace = true }
chia-sdk-test = { workspace = true }

[dev-dependencies]
chia-sdk-test = { workspace = true }
anyhow = { workspace = true }
chia-consensus = { workspace = true }
hex = { workspace = true }
Expand Down
227 changes: 227 additions & 0 deletions crates/chia-sdk-driver/src/conditions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
use chia_bls::PublicKey;
use chia_protocol::{Bytes, Bytes32};
use chia_puzzles::standard::{StandardArgs, StandardSolution};
use chia_sdk_types::conditions::{
AssertBeforeHeightAbsolute, AssertBeforeHeightRelative, AssertBeforeSecondsAbsolute,
AssertBeforeSecondsRelative, AssertCoinAnnouncement, AssertHeightAbsolute,
AssertHeightRelative, AssertPuzzleAnnouncement, AssertSecondsAbsolute, AssertSecondsRelative,
Condition, CreateCoin, CreateCoinAnnouncement, CreatePuzzleAnnouncement, ReserveFee,
};

use clvm_traits::{ClvmEncoder, ToClvm, ToClvmError};
use clvm_utils::CurriedProgram;
use clvmr::{
sha2::{Digest, Sha256},
NodePtr,
};

use crate::{Spend, SpendContext, SpendError};

#[derive(Debug, Default, Clone)]
#[must_use]
pub struct Conditions {
conditions: Vec<Condition>,
}

impl Conditions {
pub fn new() -> Self {
Self::default()
}

pub fn condition(mut self, condition: Condition) -> Self {
self.conditions.push(condition);
self
}

pub fn conditions(mut self, conditions: &[Condition]) -> Self {
self.conditions.extend_from_slice(conditions);
self
}

pub fn extend(mut self, conditions: impl IntoIterator<Item = Condition>) -> Self {
self.conditions.extend(conditions);
self
}

pub fn reserve_fee(self, fee: u64) -> Self {
self.condition(Condition::ReserveFee(ReserveFee::new(fee)))
}

pub fn create_coin(self, puzzle_hash: Bytes32, amount: u64) -> Self {
self.condition(Condition::CreateCoin(CreateCoin::new(puzzle_hash, amount)))
}

pub fn create_hinted_coin(self, puzzle_hash: Bytes32, amount: u64, hint: Bytes32) -> Self {
self.condition(Condition::CreateCoin(CreateCoin::with_hint(
puzzle_hash,
amount,
hint,
)))
}

pub fn create_coin_announcement(self, message: Bytes) -> Self {
self.condition(Condition::CreateCoinAnnouncement(
CreateCoinAnnouncement::new(message),
))
}

pub fn assert_raw_coin_announcement(self, announcement_id: Bytes32) -> Self {
self.condition(Condition::AssertCoinAnnouncement(
AssertCoinAnnouncement::new(announcement_id),
))
}

pub fn assert_coin_announcement(self, coin_id: Bytes32, message: impl AsRef<[u8]>) -> Self {
let mut announcement_id = Sha256::new();
announcement_id.update(coin_id);
announcement_id.update(message);
self.assert_raw_coin_announcement(Bytes32::new(announcement_id.finalize().into()))
}

pub fn create_puzzle_announcement(self, message: Bytes) -> Self {
self.condition(Condition::CreatePuzzleAnnouncement(
CreatePuzzleAnnouncement::new(message),
))
}

pub fn assert_raw_puzzle_announcement(self, announcement_id: Bytes32) -> Self {
self.condition(Condition::AssertPuzzleAnnouncement(
AssertPuzzleAnnouncement::new(announcement_id),
))
}

pub fn assert_puzzle_announcement(
self,
puzzle_hash: Bytes32,
message: impl AsRef<[u8]>,
) -> Self {
let mut announcement_id = Sha256::new();
announcement_id.update(puzzle_hash);
announcement_id.update(message);
self.assert_raw_puzzle_announcement(Bytes32::new(announcement_id.finalize().into()))
}

pub fn assert_before_seconds_relative(self, seconds: u64) -> Self {
self.condition(Condition::AssertBeforeSecondsRelative(
AssertBeforeSecondsRelative::new(seconds),
))
}

pub fn assert_seconds_relative(self, seconds: u64) -> Self {
self.condition(Condition::AssertSecondsRelative(
AssertSecondsRelative::new(seconds),
))
}

pub fn assert_seconds_absolute(self, seconds: u64) -> Self {
self.condition(Condition::AssertSecondsAbsolute(
AssertSecondsAbsolute::new(seconds),
))
}

pub fn assert_before_seconds_absolute(self, seconds: u64) -> Self {
self.condition(Condition::AssertBeforeSecondsAbsolute(
AssertBeforeSecondsAbsolute::new(seconds),
))
}

pub fn assert_before_height_relative(self, height: u32) -> Self {
self.condition(Condition::AssertBeforeHeightRelative(
AssertBeforeHeightRelative::new(height),
))
}

pub fn assert_before_height_absolute(self, height: u32) -> Self {
self.condition(Condition::AssertBeforeHeightAbsolute(
AssertBeforeHeightAbsolute::new(height),
))
}

pub fn assert_height_relative(self, height: u32) -> Self {
self.condition(Condition::AssertHeightRelative(AssertHeightRelative::new(
height,
)))
}

pub fn assert_height_absolute(self, height: u32) -> Self {
self.condition(Condition::AssertHeightAbsolute(AssertHeightAbsolute::new(
height,
)))
}

pub fn p2_spend(
self,
ctx: &mut SpendContext<'_>,
synthetic_key: PublicKey,
) -> Result<Spend, SpendError> {
let standard_puzzle = ctx.standard_puzzle()?;

let puzzle = ctx.alloc(&CurriedProgram {
program: standard_puzzle,
args: StandardArgs::new(synthetic_key),
})?;

let solution = ctx.alloc(&StandardSolution::from_conditions(self))?;

Ok(Spend::new(puzzle, solution))
}
}

impl AsRef<[Condition]> for Conditions {
fn as_ref(&self) -> &[Condition] {
&self.conditions
}
}

impl IntoIterator for Conditions {
type Item = Condition;
type IntoIter = std::vec::IntoIter<Condition>;

fn into_iter(self) -> Self::IntoIter {
self.conditions.into_iter()
}
}

impl ToClvm<NodePtr> for Conditions {
fn to_clvm(
&self,
encoder: &mut impl ClvmEncoder<Node = NodePtr>,
) -> Result<NodePtr, ToClvmError> {
self.conditions.to_clvm(encoder)
}
}

#[cfg(test)]
mod tests {
use chia_sdk_test::{test_transaction, Simulator};
use clvmr::Allocator;

use super::*;

#[tokio::test]
async fn test_standard_spend() -> anyhow::Result<()> {
let sim = Simulator::new().await?;
let peer = sim.connect().await?;

let sk = sim.secret_key().await?;
let pk = sk.public_key();

let puzzle_hash = StandardArgs::curry_tree_hash(pk).into();
let coin = sim.mint_coin(puzzle_hash, 1).await;

let mut allocator = Allocator::new();
let ctx = &mut SpendContext::new(&mut allocator);

ctx.spend_p2_coin(coin, pk, Conditions::new().create_coin(puzzle_hash, 1))?;

test_transaction(
&peer,
ctx.take_spends(),
&[sk],
sim.config().genesis_challenge,
)
.await;

Ok(())
}
}
6 changes: 4 additions & 2 deletions crates/chia-sdk-driver/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod conditions;
mod puzzles;
mod spend_builder;
mod spend;
mod spend_context;
mod spend_error;

pub use conditions::*;
pub use puzzles::*;
pub use spend_builder::*;
pub use spend::*;
pub use spend_context::*;
pub use spend_error::*;
2 changes: 0 additions & 2 deletions crates/chia-sdk-driver/src/puzzles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ mod cat;
mod did;
mod nft;
mod singleton;
mod standard;

pub use cat::*;
pub use did::*;
pub use nft::*;
pub use singleton::*;
pub use standard::*;
Loading

0 comments on commit 051c828

Please sign in to comment.