-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
402 additions
and
95 deletions.
There are no files selected for viewing
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,16 +1,16 @@ | ||
mod known_puzzles; | ||
mod m_of_n; | ||
mod member; | ||
mod puzzle_with_restrictions; | ||
mod restriction; | ||
mod vault_info; | ||
mod vault_launcher; | ||
mod vault_layer; | ||
mod vault_primitive; | ||
|
||
pub use known_puzzles::*; | ||
pub use m_of_n::*; | ||
pub use member::*; | ||
pub use puzzle_with_restrictions::*; | ||
pub use restriction::*; | ||
pub use vault_info::*; | ||
|
||
use chia_protocol::Coin; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct Vault { | ||
pub coin: Coin, | ||
} | ||
pub use vault_layer::*; | ||
pub use vault_primitive::*; |
17 changes: 17 additions & 0 deletions
17
crates/chia-sdk-driver/src/primitives/vault/known_puzzles.rs
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,17 @@ | ||
use std::collections::HashMap; | ||
|
||
use clvm_utils::TreeHash; | ||
|
||
use super::{MemberKind, RestrictionKind}; | ||
|
||
#[derive(Debug, Default, Clone)] | ||
pub struct KnownPuzzles { | ||
pub restrictions: HashMap<TreeHash, RestrictionKind>, | ||
pub members: HashMap<TreeHash, MemberKind>, | ||
} | ||
|
||
impl KnownPuzzles { | ||
pub fn new() -> Self { | ||
Self::default() | ||
} | ||
} |
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,55 +1,62 @@ | ||
use clvm_traits::{FromClvm, ToClvm}; | ||
use clvmr::{Allocator, NodePtr}; | ||
use chia_protocol::Bytes32; | ||
use chia_sdk_types::{MerkleTree, Mod, Vault1ofNArgs, VaultMofNArgs, VaultNofNArgs}; | ||
use clvm_utils::TreeHash; | ||
|
||
use crate::DriverError; | ||
|
||
use super::Member; | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, ToClvm, FromClvm)] | ||
#[clvm(list)] | ||
pub struct MofNMemo<T> { | ||
pub required: usize, | ||
pub members: Vec<T>, | ||
} | ||
use super::{KnownPuzzles, Member, PuzzleWithRestrictions, VaultLayer}; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct MofN { | ||
required: usize, | ||
members: Vec<Member>, | ||
members: Vec<PuzzleWithRestrictions<Member>>, | ||
} | ||
|
||
impl MofN { | ||
pub fn new(required: usize, members: Vec<Member>) -> Option<Self> { | ||
pub fn new(required: usize, members: Vec<PuzzleWithRestrictions<Member>>) -> Option<Self> { | ||
if members.len() < required { | ||
return None; | ||
} | ||
Some(Self { required, members }) | ||
} | ||
|
||
pub fn from_memo(allocator: &Allocator, memo: NodePtr) -> Result<Self, DriverError> { | ||
let memo = MofNMemo::from_clvm(allocator, memo)?; | ||
|
||
if memo.members.len() < memo.required { | ||
return Err(DriverError::InvalidMemo); | ||
} | ||
|
||
let mut members = Vec::with_capacity(memo.members.len()); | ||
pub fn required(&self) -> usize { | ||
self.required | ||
} | ||
|
||
for member_memo in memo.members { | ||
members.push(Member::from_memo(allocator, member_memo)?); | ||
} | ||
pub fn members(&self) -> &[PuzzleWithRestrictions<Member>] { | ||
&self.members | ||
} | ||
|
||
Ok(Self { | ||
required: memo.required, | ||
members, | ||
}) | ||
fn merkle_tree(&self) -> MerkleTree { | ||
let leaves: Vec<Bytes32> = self | ||
.members | ||
.iter() | ||
.map(|member| member.puzzle_hash().into()) | ||
.collect(); | ||
MerkleTree::new(&leaves) | ||
} | ||
} | ||
|
||
pub fn required(&self) -> usize { | ||
self.required | ||
impl VaultLayer for MofN { | ||
fn puzzle_hash(&self) -> TreeHash { | ||
if self.required == 1 { | ||
let merkle_tree = self.merkle_tree(); | ||
Vault1ofNArgs::new(merkle_tree.root()).curry_tree_hash() | ||
} else if self.required == self.members.len() { | ||
let members = self.members.iter().map(VaultLayer::puzzle_hash).collect(); | ||
VaultNofNArgs::new(members).curry_tree_hash() | ||
} else { | ||
let merkle_tree = self.merkle_tree(); | ||
VaultMofNArgs::new(self.required, merkle_tree.root()).curry_tree_hash() | ||
} | ||
} | ||
|
||
pub fn members(&self) -> &[Member] { | ||
&self.members | ||
fn replace(self, known_puzzles: &KnownPuzzles) -> Self { | ||
let required = self.required; | ||
let members = self | ||
.members | ||
.into_iter() | ||
.map(|member| member.replace(known_puzzles)) | ||
.collect(); | ||
Self { required, members } | ||
} | ||
} |
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,35 +1,70 @@ | ||
use chia_bls::PublicKey; | ||
use chia_protocol::Bytes32; | ||
use chia_sdk_types::BlsMember; | ||
use clvm_traits::{FromClvm, ToClvm}; | ||
use clvmr::{Allocator, NodePtr}; | ||
use chia_sdk_types::{BlsMember, Mod}; | ||
use clvm_utils::TreeHash; | ||
|
||
use crate::DriverError; | ||
use super::{KnownPuzzles, MofN, VaultLayer}; | ||
|
||
use super::MofN; | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, ToClvm, FromClvm)] | ||
#[clvm(list)] | ||
pub struct MemberMemo<T> { | ||
pub curried_puzzle_hash: Bytes32, | ||
pub member: T, | ||
} | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)] | ||
#[clvm(list)] | ||
pub struct BlsMemberMemo { | ||
pub public_key: PublicKey, | ||
#[derive(Debug, Clone)] | ||
pub struct Member { | ||
puzzle_hash: TreeHash, | ||
kind: MemberKind, | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
pub enum Member { | ||
pub enum MemberKind { | ||
Bls(BlsMember), | ||
// do this last | ||
MofN(MofN), | ||
Unknown, | ||
} | ||
|
||
impl Member { | ||
pub fn from_memo(allocator: &Allocator, memo: NodePtr) -> Result<Self, DriverError> { | ||
todo!() | ||
pub fn bls(public_key: PublicKey) -> Self { | ||
let member = BlsMember::new(public_key); | ||
Self { | ||
puzzle_hash: member.curry_tree_hash(), | ||
kind: MemberKind::Bls(member), | ||
} | ||
} | ||
|
||
pub fn m_of_n(m_of_n: MofN) -> Self { | ||
Self { | ||
puzzle_hash: m_of_n.puzzle_hash(), | ||
kind: MemberKind::MofN(m_of_n), | ||
} | ||
} | ||
|
||
pub fn unknown(puzzle_hash: TreeHash) -> Self { | ||
Self { | ||
puzzle_hash, | ||
kind: MemberKind::Unknown, | ||
} | ||
} | ||
|
||
pub fn kind(&self) -> &MemberKind { | ||
&self.kind | ||
} | ||
} | ||
|
||
impl VaultLayer for Member { | ||
fn puzzle_hash(&self) -> TreeHash { | ||
self.puzzle_hash | ||
} | ||
|
||
fn replace(self, known_puzzles: &KnownPuzzles) -> Self { | ||
let kind = known_puzzles | ||
.members | ||
.get(&self.puzzle_hash) | ||
.cloned() | ||
.unwrap_or(self.kind); | ||
|
||
let kind = match kind { | ||
MemberKind::Bls(..) | MemberKind::Unknown => kind, | ||
MemberKind::MofN(m_of_n) => MemberKind::MofN(m_of_n.replace(known_puzzles)), | ||
}; | ||
|
||
Self { | ||
puzzle_hash: self.puzzle_hash, | ||
kind, | ||
} | ||
} | ||
} |
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,52 @@ | ||
#[derive(Debug, Clone, PartialEq, Eq, ToClvm, FromClvm)] | ||
#[clvm(list)] | ||
pub struct RestrictionMemo<T> { | ||
pub is_morpher: bool, | ||
pub curried_puzzle_hash: Bytes32, | ||
pub restriction: T, | ||
} | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)] | ||
#[clvm(list)] | ||
pub struct TimelockMemo { | ||
pub seconds: u64, | ||
} | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, ToClvm, FromClvm)] | ||
#[clvm(list)] | ||
pub struct MemberMemo<T> { | ||
pub curried_puzzle_hash: Bytes32, | ||
pub member: T, | ||
} | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)] | ||
#[clvm(list)] | ||
pub struct BlsMemberMemo { | ||
pub public_key: PublicKey, | ||
} | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, ToClvm, FromClvm)] | ||
#[clvm(list)] | ||
pub struct MofNMemo<T> { | ||
pub required: usize, | ||
pub members: Vec<T>, | ||
} | ||
|
||
pub fn from_memo(allocator: &Allocator, memo: NodePtr) -> Result<Self, DriverError> { | ||
let memo = MofNMemo::from_clvm(allocator, memo)?; | ||
|
||
if memo.members.len() < memo.required { | ||
return Err(DriverError::InvalidMemo); | ||
} | ||
|
||
let mut members = Vec::with_capacity(memo.members.len()); | ||
|
||
for member_memo in memo.members { | ||
members.push(Member::from_memo(allocator, member_memo)?); | ||
} | ||
|
||
Ok(Self { | ||
required: memo.required, | ||
members, | ||
}) | ||
} |
74 changes: 74 additions & 0 deletions
74
crates/chia-sdk-driver/src/primitives/vault/puzzle_with_restrictions.rs
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,74 @@ | ||
use chia_sdk_types::{DelegatedFeederArgs, IndexWrapperArgs, Mod, RestrictionsArgs}; | ||
use clvm_utils::TreeHash; | ||
|
||
use super::{KnownPuzzles, Restriction, VaultLayer}; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct PuzzleWithRestrictions<T> { | ||
nonce: usize, | ||
restrictions: Vec<Restriction>, | ||
puzzle: T, | ||
has_delegated_feeder: bool, | ||
} | ||
|
||
impl<T> PuzzleWithRestrictions<T> { | ||
pub fn top_level(nonce: usize, restrictions: Vec<Restriction>, puzzle: T) -> Self { | ||
Self { | ||
nonce, | ||
restrictions, | ||
puzzle, | ||
has_delegated_feeder: true, | ||
} | ||
} | ||
|
||
pub fn inner(nonce: usize, restrictions: Vec<Restriction>, puzzle: T) -> Self { | ||
Self { | ||
nonce, | ||
restrictions, | ||
puzzle, | ||
has_delegated_feeder: false, | ||
} | ||
} | ||
} | ||
|
||
impl<T> VaultLayer for PuzzleWithRestrictions<T> | ||
where | ||
T: VaultLayer, | ||
{ | ||
fn puzzle_hash(&self) -> TreeHash { | ||
let mut puzzle_hash = self.puzzle.puzzle_hash(); | ||
|
||
if !self.restrictions.is_empty() { | ||
let mut member_validators = Vec::new(); | ||
let mut delegated_puzzle_validators = Vec::new(); | ||
|
||
for restriction in &self.restrictions { | ||
if restriction.is_member_condition_validator() { | ||
member_validators.push(restriction.puzzle_hash()); | ||
} else { | ||
delegated_puzzle_validators.push(restriction.puzzle_hash()); | ||
} | ||
} | ||
|
||
puzzle_hash = | ||
RestrictionsArgs::new(member_validators, delegated_puzzle_validators, puzzle_hash) | ||
.curry_tree_hash(); | ||
} | ||
|
||
if self.has_delegated_feeder { | ||
puzzle_hash = DelegatedFeederArgs::new(puzzle_hash).curry_tree_hash(); | ||
} | ||
|
||
IndexWrapperArgs::new(self.nonce, puzzle_hash).curry_tree_hash() | ||
} | ||
|
||
fn replace(mut self, known_puzzles: &KnownPuzzles) -> Self { | ||
let mut restrictions = Vec::with_capacity(self.restrictions.len()); | ||
for restriction in self.restrictions { | ||
restrictions.push(restriction.replace(known_puzzles)); | ||
} | ||
self.restrictions = restrictions; | ||
self.puzzle = self.puzzle.replace(known_puzzles); | ||
self | ||
} | ||
} |
Oops, something went wrong.