Skip to content

Commit

Permalink
Merge pull request #142 from xch-dev/vault-members-restrictions
Browse files Browse the repository at this point in the history
Vault members restrictions
  • Loading branch information
Rigidity authored Dec 16, 2024
2 parents 605dabb + 6b7359e commit 3001ce3
Show file tree
Hide file tree
Showing 23 changed files with 769 additions and 10 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ workspace = true

[features]
chip-0035 = ["chia-sdk-driver/chip-0035", "chia-sdk-types/chip-0035"]
vault = ["chia-sdk-driver/vault", "chia-sdk-types/vault"]
experimental-vaults = [
"chia-sdk-driver/experimental-vaults",
"chia-sdk-types/experimental-vaults",
]
offers = ["chia-sdk-driver/offers"]
native-tls = ["chia-sdk-client/native-tls"]
rustls = ["chia-sdk-client/rustls"]
Expand Down
3 changes: 2 additions & 1 deletion crates/chia-sdk-driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ workspace = true

[features]
chip-0035 = ["chia-sdk-types/chip-0035"]
vault = ["chia-sdk-types/vault"]
experimental-vaults = ["chia-sdk-types/experimental-vaults"]
offers = [
"dep:bech32",
"dep:chia-traits",
Expand All @@ -30,6 +30,7 @@ offers = [

[dependencies]
chia-bls = { workspace = true }
chia-secp = { workspace = true }
chia-protocol = { workspace = true }
chia-puzzles = { workspace = true }
clvm-traits = { workspace = true }
Expand Down
4 changes: 2 additions & 2 deletions crates/chia-sdk-driver/src/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ mod datalayer;
#[cfg(feature = "chip-0035")]
pub use datalayer::*;

#[cfg(feature = "vault")]
#[cfg(feature = "experimental-vaults")]
mod vault;

#[cfg(feature = "vault")]
#[cfg(feature = "experimental-vaults")]
pub use vault::*;
116 changes: 114 additions & 2 deletions crates/chia-sdk-driver/src/primitives/vault/member.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
use chia_bls::PublicKey;
use chia_sdk_types::{BlsMember, Mod};
use chia_protocol::Bytes32;
use chia_sdk_types::{
BlsMember, BlsTaprootMember, FixedPuzzleMember, Mod, PasskeyMember, PasskeyMemberPuzzleAssert,
Secp256k1Member, Secp256k1MemberPuzzleAssert, Secp256r1Member, Secp256r1MemberPuzzleAssert,
SingletonMember,
};
use chia_secp::{K1PublicKey, R1PublicKey};
use clvm_utils::TreeHash;
use clvmr::NodePtr;

Expand All @@ -16,6 +22,15 @@ pub struct Member {
#[derive(Debug, Clone)]
pub enum MemberKind {
Bls(BlsMember),
BlsTaproot(BlsTaprootMember),
FixedPuzzle(FixedPuzzleMember),
Passkey(PasskeyMember),
PasskeyPuzzleAssert(PasskeyMemberPuzzleAssert),
Secp256k1(Secp256k1Member),
Secp256k1PuzzleAssert(Secp256k1MemberPuzzleAssert),
Secp256r1(Secp256r1Member),
Secp256r1PuzzleAssert(Secp256r1MemberPuzzleAssert),
Singleton(SingletonMember),
MofN(MofN),
Unknown,
}
Expand All @@ -29,6 +44,78 @@ impl Member {
}
}

pub fn bls_taproot(synthetic_key: PublicKey) -> Self {
let member = BlsTaprootMember::new(synthetic_key);
Self {
puzzle_hash: member.curry_tree_hash(),
kind: MemberKind::BlsTaproot(member),
}
}

pub fn fixed_puzzle(fixed_puzzle_hash: Bytes32) -> Self {
let member = FixedPuzzleMember::new(fixed_puzzle_hash);
Self {
puzzle_hash: member.curry_tree_hash(),
kind: MemberKind::FixedPuzzle(member),
}
}

pub fn passkey(genesis_challenge: Bytes32, public_key: R1PublicKey) -> Self {
let member = PasskeyMember::new(genesis_challenge, public_key);
Self {
puzzle_hash: member.curry_tree_hash(),
kind: MemberKind::Passkey(member),
}
}

pub fn passkey_puzzle_assert(genesis_challenge: Bytes32, public_key: R1PublicKey) -> Self {
let member = PasskeyMemberPuzzleAssert::new(genesis_challenge, public_key);
Self {
puzzle_hash: member.curry_tree_hash(),
kind: MemberKind::PasskeyPuzzleAssert(member),
}
}

pub fn secp256k1(public_key: K1PublicKey) -> Self {
let member = Secp256k1Member::new(public_key);
Self {
puzzle_hash: member.curry_tree_hash(),
kind: MemberKind::Secp256k1(member),
}
}

pub fn secp256k1_puzzle_assert(public_key: K1PublicKey) -> Self {
let member = Secp256k1MemberPuzzleAssert::new(public_key);
Self {
puzzle_hash: member.curry_tree_hash(),
kind: MemberKind::Secp256k1PuzzleAssert(member),
}
}

pub fn secp256r1(public_key: R1PublicKey) -> Self {
let member = Secp256r1Member::new(public_key);
Self {
puzzle_hash: member.curry_tree_hash(),
kind: MemberKind::Secp256r1(member),
}
}

pub fn secp256r1_puzzle_assert(public_key: R1PublicKey) -> Self {
let member = Secp256r1MemberPuzzleAssert::new(public_key);
Self {
puzzle_hash: member.curry_tree_hash(),
kind: MemberKind::Secp256r1PuzzleAssert(member),
}
}

pub fn singleton(launcher_id: Bytes32) -> Self {
let member = SingletonMember::new(launcher_id);
Self {
puzzle_hash: member.curry_tree_hash(),
kind: MemberKind::Singleton(member),
}
}

pub fn m_of_n(required: usize, members: Vec<PuzzleWithRestrictions<Member>>) -> Self {
let m_of_n = MofN::new(required, members).expect("invalid m_of_n");
Self {
Expand Down Expand Up @@ -57,6 +144,21 @@ impl VaultLayer for Member {
fn puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
match &self.kind {
MemberKind::Bls(bls) => ctx.curry(bls),
MemberKind::BlsTaproot(bls_taproot) => ctx.curry(bls_taproot),
MemberKind::FixedPuzzle(fixed_puzzle) => ctx.curry(fixed_puzzle),
MemberKind::Passkey(passkey) => ctx.curry(passkey),
MemberKind::PasskeyPuzzleAssert(passkey_puzzle_assert) => {
ctx.curry(passkey_puzzle_assert)
}
MemberKind::Secp256k1(secp256k1) => ctx.curry(secp256k1),
MemberKind::Secp256k1PuzzleAssert(secp256k1_puzzle_assert) => {
ctx.curry(secp256k1_puzzle_assert)
}
MemberKind::Secp256r1(secp256r1) => ctx.curry(secp256r1),
MemberKind::Secp256r1PuzzleAssert(secp256r1_puzzle_assert) => {
ctx.curry(secp256r1_puzzle_assert)
}
MemberKind::Singleton(singleton) => ctx.curry(singleton),
MemberKind::MofN(m_of_n) => m_of_n.puzzle(ctx),
MemberKind::Unknown => Err(DriverError::UnknownPuzzle),
}
Expand All @@ -70,7 +172,17 @@ impl VaultLayer for Member {
.unwrap_or(self.kind);

let kind = match kind {
MemberKind::Bls(..) | MemberKind::Unknown => kind,
MemberKind::Bls(..)
| MemberKind::BlsTaproot(..)
| MemberKind::FixedPuzzle(..)
| MemberKind::Passkey(..)
| MemberKind::PasskeyPuzzleAssert(..)
| MemberKind::Secp256k1(..)
| MemberKind::Secp256k1PuzzleAssert(..)
| MemberKind::Secp256r1(..)
| MemberKind::Secp256r1PuzzleAssert(..)
| MemberKind::Singleton(..)
| MemberKind::Unknown => kind,
MemberKind::MofN(m_of_n) => MemberKind::MofN(m_of_n.replace(known_puzzles)),
};

Expand Down
10 changes: 9 additions & 1 deletion crates/chia-sdk-driver/src/primitives/vault/restriction.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use chia_sdk_types::Timelock;
use chia_sdk_types::{Force1of2RestrictedVariable, Timelock};
use clvm_utils::TreeHash;
use clvmr::NodePtr;

Expand All @@ -16,6 +16,9 @@ pub struct Restriction {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RestrictionKind {
Timelock(Timelock),
ForceCoinMessage,
ForceAssertCoinAnnouncement,
Force1of2RestrictedVariable(Force1of2RestrictedVariable),
Unknown,
}

Expand Down Expand Up @@ -49,6 +52,11 @@ impl VaultLayer for Restriction {
fn puzzle(&self, ctx: &mut SpendContext) -> Result<NodePtr, DriverError> {
match &self.kind {
RestrictionKind::Timelock(timelock) => ctx.curry(timelock),
RestrictionKind::ForceCoinMessage => ctx.force_coin_message_puzzle(),
RestrictionKind::ForceAssertCoinAnnouncement => {
ctx.force_assert_coin_announcement_puzzle()
}
RestrictionKind::Force1of2RestrictedVariable(restriction) => ctx.curry(restriction),
RestrictionKind::Unknown => Err(DriverError::UnknownPuzzle),
}
}
Expand Down
19 changes: 19 additions & 0 deletions crates/chia-sdk-driver/src/spend_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ use clvm_traits::{FromClvm, ToClvm};
use clvm_utils::{tree_hash, CurriedProgram, TreeHash};
use clvmr::{serde::node_from_bytes, Allocator, NodePtr};

#[cfg(feature = "experimental-vaults")]
use chia_sdk_types::{
FORCE_ASSERT_COIN_ANNOUNCEMENT_PUZZLE, FORCE_ASSERT_COIN_ANNOUNCEMENT_PUZZLE_HASH,
FORCE_COIN_MESSAGE_PUZZLE, FORCE_COIN_MESSAGE_PUZZLE_HASH,
};

use crate::{DriverError, Spend};

/// A wrapper around [`Allocator`] that caches puzzles and keeps track of a list of [`CoinSpend`].
Expand Down Expand Up @@ -128,6 +134,19 @@ impl SpendContext {
self.puzzle(SETTLEMENT_PAYMENTS_PUZZLE_HASH, &SETTLEMENT_PAYMENTS_PUZZLE)
}

#[cfg(feature = "experimental-vaults")]
pub fn force_coin_message_puzzle(&mut self) -> Result<NodePtr, DriverError> {
self.puzzle(FORCE_COIN_MESSAGE_PUZZLE_HASH, &FORCE_COIN_MESSAGE_PUZZLE)
}

#[cfg(feature = "experimental-vaults")]
pub fn force_assert_coin_announcement_puzzle(&mut self) -> Result<NodePtr, DriverError> {
self.puzzle(
FORCE_ASSERT_COIN_ANNOUNCEMENT_PUZZLE_HASH,
&FORCE_ASSERT_COIN_ANNOUNCEMENT_PUZZLE,
)
}

/// Preload a puzzle into the cache.
pub fn preload(&mut self, puzzle_hash: TreeHash, ptr: NodePtr) {
self.puzzles.insert(puzzle_hash, ptr);
Expand Down
3 changes: 2 additions & 1 deletion crates/chia-sdk-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ workspace = true

[features]
chip-0035 = []
vault = []
experimental-vaults = []

[dependencies]
chia-sdk-derive = { workspace = true }
chia-bls = { workspace = true }
chia-secp = { workspace = true }
chia-protocol = { workspace = true }
chia-consensus = { workspace = true }
chia-puzzles = { workspace = true }
Expand Down
4 changes: 2 additions & 2 deletions crates/chia-sdk-types/src/puzzles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ mod datalayer;
#[cfg(feature = "chip-0035")]
pub use datalayer::*;

#[cfg(feature = "vault")]
#[cfg(feature = "experimental-vaults")]
mod vault;

#[cfg(feature = "vault")]
#[cfg(feature = "experimental-vaults")]
pub use vault::*;

#[cfg(test)]
Expand Down
18 changes: 18 additions & 0 deletions crates/chia-sdk-types/src/puzzles/vault/members.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
mod bls_member;
mod bls_taproot_member;
mod fixed_puzzle_member;
mod passkey_member;
mod passkey_member_puzzle_assert;
mod secp256k1_member;
mod secp256k1_member_puzzle_assert;
mod secp256r1_member;
mod secp256r1_member_puzzle_assert;
mod singleton_member;

pub use bls_member::*;
pub use bls_taproot_member::*;
pub use fixed_puzzle_member::*;
pub use passkey_member::*;
pub use passkey_member_puzzle_assert::*;
pub use secp256k1_member::*;
pub use secp256k1_member_puzzle_assert::*;
pub use secp256r1_member::*;
pub use secp256r1_member_puzzle_assert::*;
pub use singleton_member::*;
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use chia_bls::PublicKey;
use clvm_traits::{FromClvm, ToClvm};
use clvm_utils::TreeHash;
use hex_literal::hex;

use crate::Mod;

#[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(curry)]
pub struct BlsTaprootMember {
pub synthetic_key: PublicKey,
}

impl BlsTaprootMember {
pub fn new(synthetic_key: PublicKey) -> Self {
Self { synthetic_key }
}
}

impl Mod for BlsTaprootMember {
const MOD_REVEAL: &[u8] = &BLS_TAPROOT_MEMBER;
const MOD_HASH: TreeHash = BLS_TAPROOT_MEMBER_HASH;
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(solution)]
pub struct BlsTaprootMemberSolution {
pub original_public_key: Option<PublicKey>,
}

impl BlsTaprootMemberSolution {
pub fn new(original_public_key: Option<PublicKey>) -> Self {
Self {
original_public_key,
}
}
}

pub const BLS_TAPROOT_MEMBER: [u8; 99] = hex!(
"
ff02ffff01ff02ffff03ff17ffff01ff02ffff03ffff09ff05ffff1dff17ffff
1effff0bff17ff0b80808080ff80ffff01ff088080ff0180ffff01ff04ffff04
ff02ffff04ff05ffff04ff0bff80808080ff808080ff0180ffff04ffff0132ff
018080
"
);

pub const BLS_TAPROOT_MEMBER_HASH: TreeHash = TreeHash::new(hex!(
"35d2ad31aaf0df91c965909e5112294c57a18354ee4a5aae80572080ec3b6842"
));
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use chia_protocol::Bytes32;
use clvm_traits::{FromClvm, ToClvm};
use clvm_utils::TreeHash;
use hex_literal::hex;

use crate::Mod;

#[derive(Debug, Clone, Copy, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(curry)]
pub struct FixedPuzzleMember {
pub fixed_puzzle_hash: Bytes32,
}

impl FixedPuzzleMember {
pub fn new(fixed_puzzle_hash: Bytes32) -> Self {
Self { fixed_puzzle_hash }
}
}

impl Mod for FixedPuzzleMember {
const MOD_REVEAL: &[u8] = &FIXED_PUZZLE_MEMBER;
const MOD_HASH: TreeHash = FIXED_PUZZLE_MEMBER_HASH;
}

pub const FIXED_PUZZLE_MEMBER: [u8; 25] =
hex!("ff02ffff03ffff09ff02ff0580ff80ffff01ff088080ff0180");

pub const FIXED_PUZZLE_MEMBER_HASH: TreeHash = TreeHash::new(hex!(
"34ede3eadc52ed750e405f2b9dea9891506547f651290bb606356d997c64f219"
));
Loading

0 comments on commit 3001ce3

Please sign in to comment.