-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #48 from Rigidity/condition-constructors
Refactor driver code
- Loading branch information
Showing
33 changed files
with
945 additions
and
1,277 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.