Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clvm-traits rewrite with Encoder #317

Merged
merged 5 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 21 additions & 19 deletions chia-bls/src/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use crate::secret_key::is_all_zero;
use crate::{DerivableKey, Error, Result};
use blst::*;
use chia_traits::{read_bytes, Streamable};
use clvm_traits::{FromClvm, ToClvm};
use clvmr::allocator::{Allocator, NodePtr, SExp};
use clvm_traits::{ClvmDecoder, ClvmEncoder, FromClvm, FromClvmError, ToClvm, ToClvmError};
use sha2::{digest::FixedOutput, Digest, Sha256};
use std::fmt;
use std::hash::{Hash, Hasher};
Expand Down Expand Up @@ -385,25 +384,27 @@ impl DerivableKey for PublicKey {
}
}

impl FromClvm for PublicKey {
fn from_clvm(a: &Allocator, ptr: NodePtr) -> clvm_traits::Result<Self> {
let blob = match a.sexp(ptr) {
SExp::Atom => a.atom(ptr),
_ => {
return Err(clvm_traits::Error::ExpectedAtom(ptr));
}
};
Self::from_bytes(
blob.try_into()
.map_err(|_error| clvm_traits::Error::Custom("invalid size".to_string()))?,
)
.map_err(|error| clvm_traits::Error::Custom(error.to_string()))
impl<N> FromClvm<N> for PublicKey {
fn from_clvm(
decoder: &impl ClvmDecoder<Node = N>,
node: N,
) -> std::result::Result<Self, FromClvmError> {
let bytes = decoder.decode_atom(&node)?;
let error = Err(FromClvmError::WrongAtomLength {
expected: 48,
found: bytes.len(),
});
let bytes = bytes.try_into().or(error)?;
Self::from_bytes(bytes).map_err(|error| FromClvmError::Custom(error.to_string()))
}
}

impl ToClvm for PublicKey {
fn to_clvm(&self, a: &mut Allocator) -> clvm_traits::Result<NodePtr> {
Ok(a.new_atom(&self.to_bytes())?)
impl<N> ToClvm<N> for PublicKey {
fn to_clvm(
&self,
encoder: &mut impl ClvmEncoder<Node = N>,
) -> std::result::Result<N, ToClvmError> {
encoder.encode_atom(&self.to_bytes())
}
}

Expand Down Expand Up @@ -434,6 +435,7 @@ pub fn hash_to_g1_with_dst(msg: &[u8], dst: &[u8]) -> PublicKey {
mod tests {
use super::*;
use crate::SecretKey;
use clvmr::Allocator;
use hex::FromHex;
use rand::rngs::StdRng;
use rand::{Rng, SeedableRng};
Expand Down Expand Up @@ -622,7 +624,7 @@ mod tests {
let ptr = a.new_pair(a.one(), a.one()).expect("new_pair");
assert_eq!(
PublicKey::from_clvm(&a, ptr).unwrap_err(),
clvm_traits::Error::ExpectedAtom(ptr)
FromClvmError::ExpectedAtom
);
}

Expand Down
40 changes: 21 additions & 19 deletions chia-bls/src/signature.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::{Error, GTElement, PublicKey, Result, SecretKey};
use blst::*;
use chia_traits::{read_bytes, Streamable};
use clvm_traits::{FromClvm, ToClvm};
use clvmr::allocator::{Allocator, NodePtr, SExp};
use clvm_traits::{ClvmDecoder, ClvmEncoder, FromClvm, FromClvmError, ToClvm, ToClvmError};
use sha2::{Digest, Sha256};
use std::borrow::Borrow;
use std::convert::AsRef;
Expand Down Expand Up @@ -248,25 +247,27 @@ impl FromJsonDict for Signature {
}
}

impl FromClvm for Signature {
fn from_clvm(a: &Allocator, ptr: NodePtr) -> clvm_traits::Result<Self> {
let blob = match a.sexp(ptr) {
SExp::Atom => a.atom(ptr),
_ => {
return Err(clvm_traits::Error::ExpectedAtom(ptr));
}
};
Self::from_bytes(
blob.try_into()
.map_err(|_error| clvm_traits::Error::Custom("invalid size".to_string()))?,
)
.map_err(|error| clvm_traits::Error::Custom(error.to_string()))
impl<N> FromClvm<N> for Signature {
fn from_clvm(
decoder: &impl ClvmDecoder<Node = N>,
node: N,
) -> std::result::Result<Self, FromClvmError> {
let bytes = decoder.decode_atom(&node)?;
let error = Err(FromClvmError::WrongAtomLength {
expected: 96,
found: bytes.len(),
});
let bytes = bytes.try_into().or(error)?;
Self::from_bytes(bytes).map_err(|error| FromClvmError::Custom(error.to_string()))
}
}

impl ToClvm for Signature {
fn to_clvm(&self, a: &mut Allocator) -> clvm_traits::Result<NodePtr> {
Ok(a.new_atom(&self.to_bytes())?)
impl<N> ToClvm<N> for Signature {
fn to_clvm(
&self,
encoder: &mut impl ClvmEncoder<Node = N>,
) -> std::result::Result<N, ToClvmError> {
encoder.encode_atom(&self.to_bytes())
}
}

Expand Down Expand Up @@ -529,6 +530,7 @@ pub fn sign<Msg: AsRef<[u8]>>(sk: &SecretKey, msg: Msg) -> Signature {
#[cfg(test)]
mod tests {
use super::*;
use clvmr::Allocator;
use hex::FromHex;
use rand::rngs::StdRng;
use rand::{Rng, SeedableRng};
Expand Down Expand Up @@ -1077,7 +1079,7 @@ mod tests {
let ptr = a.new_pair(a.one(), a.one()).expect("new_pair");
assert_eq!(
Signature::from_clvm(&a, ptr).unwrap_err(),
clvm_traits::Error::ExpectedAtom(ptr)
FromClvmError::ExpectedAtom
);
}

Expand Down
63 changes: 27 additions & 36 deletions chia-protocol/src/bytes.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use chia_traits::chia_error;
use chia_traits::{read_bytes, Streamable};
use clvm_traits::{FromClvm, ToClvm};
use clvmr::allocator::{NodePtr, SExp};
use clvmr::Allocator;
use clvm_traits::{ClvmDecoder, ClvmEncoder, FromClvm, FromClvmError, ToClvm, ToClvmError};
use core::fmt::Formatter;
use sha2::{Digest, Sha256};
use std::convert::AsRef;
Expand Down Expand Up @@ -95,19 +93,16 @@ impl FromJsonDict for Bytes {
}
}

impl ToClvm for Bytes {
fn to_clvm(&self, a: &mut Allocator) -> clvm_traits::Result<NodePtr> {
Ok(a.new_atom(self.0.as_slice())?)
impl<N> ToClvm<N> for Bytes {
fn to_clvm(&self, encoder: &mut impl ClvmEncoder<Node = N>) -> Result<N, ToClvmError> {
encoder.encode_atom(self.0.as_slice())
}
}

impl FromClvm for Bytes {
fn from_clvm(a: &Allocator, ptr: NodePtr) -> clvm_traits::Result<Self> {
if let SExp::Atom = a.sexp(ptr) {
Ok(Self(a.atom(ptr).to_vec()))
} else {
Err(clvm_traits::Error::ExpectedAtom(ptr))
}
impl<N> FromClvm<N> for Bytes {
fn from_clvm(decoder: &impl ClvmDecoder<Node = N>, node: N) -> Result<Self, FromClvmError> {
let bytes = decoder.decode_atom(&node)?;
Ok(Self(bytes.to_vec()))
}
}

Expand Down Expand Up @@ -201,26 +196,22 @@ impl<const N: usize> Streamable for BytesImpl<N> {
}
}

impl<const N: usize> ToClvm for BytesImpl<N> {
fn to_clvm(&self, a: &mut Allocator) -> clvm_traits::Result<NodePtr> {
Ok(a.new_atom(self.0.as_slice())?)
impl<N, const LEN: usize> ToClvm<N> for BytesImpl<LEN> {
fn to_clvm(&self, encoder: &mut impl ClvmEncoder<Node = N>) -> Result<N, ToClvmError> {
encoder.encode_atom(self.0.as_slice())
}
}

impl<const N: usize> FromClvm for BytesImpl<N> {
fn from_clvm(a: &Allocator, ptr: NodePtr) -> clvm_traits::Result<Self> {
let blob = match a.sexp(ptr) {
SExp::Atom => {
if a.atom_len(ptr) != N {
return Err(clvm_traits::Error::Custom("invalid size".to_string()));
}
a.atom(ptr)
}
_ => {
return Err(clvm_traits::Error::ExpectedAtom(ptr));
}
};
Ok(Self::from(blob))
impl<N, const LEN: usize> FromClvm<N> for BytesImpl<LEN> {
fn from_clvm(decoder: &impl ClvmDecoder<Node = N>, node: N) -> Result<Self, FromClvmError> {
let bytes = decoder.decode_atom(&node)?;
if bytes.len() != LEN {
return Err(FromClvmError::WrongAtomLength {
expected: LEN,
found: bytes.len(),
});
}
Ok(Self::from(bytes))
}
}

Expand Down Expand Up @@ -425,7 +416,10 @@ impl<'py> FromPyObject<'py> for Bytes {
mod tests {
use super::*;

use clvmr::serde::{node_from_bytes, node_to_bytes};
use clvmr::{
serde::{node_from_bytes, node_to_bytes},
Allocator,
};
use rstest::rstest;

#[rstest]
Expand Down Expand Up @@ -690,15 +684,12 @@ mod tests {
let bytes =
hex::decode("f07522495060c066f66f32acc2a77e3a3e737aca8baea4d1a64ea4cdc13da9").unwrap();
let ptr = a.new_atom(&bytes).unwrap();
assert_eq!(
Bytes32::from_clvm(a, ptr).unwrap_err(),
clvm_traits::Error::Custom("invalid size".to_string())
);
assert!(Bytes32::from_clvm(a, ptr).is_err());

let ptr = a.new_pair(a.one(), a.one()).unwrap();
assert_eq!(
Bytes32::from_clvm(a, ptr).unwrap_err(),
clvm_traits::Error::ExpectedAtom(ptr)
FromClvmError::ExpectedAtom
);
}
}
24 changes: 14 additions & 10 deletions chia-protocol/src/coin.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::streamable_struct;
use crate::{bytes::Bytes32, BytesImpl};
use chia_streamable_macro::Streamable;
use clvm_traits::{clvm_list, destructure_list, match_list, FromClvm, ToClvm};
use clvmr::allocator::NodePtr;
use clvmr::Allocator;
use clvm_traits::{
clvm_list, destructure_list, match_list, ClvmDecoder, ClvmEncoder, FromClvm, FromClvmError,
ToClvm, ToClvmError,
};
use sha2::{Digest, Sha256};
use std::convert::TryInto;

Expand Down Expand Up @@ -53,16 +54,16 @@ impl Coin {
}
}

impl ToClvm for Coin {
fn to_clvm(&self, a: &mut Allocator) -> clvm_traits::Result<NodePtr> {
clvm_list!(self.parent_coin_info, self.puzzle_hash, self.amount).to_clvm(a)
impl<N> ToClvm<N> for Coin {
fn to_clvm(&self, encoder: &mut impl ClvmEncoder<Node = N>) -> Result<N, ToClvmError> {
clvm_list!(self.parent_coin_info, self.puzzle_hash, self.amount).to_clvm(encoder)
}
}

impl FromClvm for Coin {
fn from_clvm(a: &Allocator, ptr: NodePtr) -> clvm_traits::Result<Self> {
impl<N> FromClvm<N> for Coin {
fn from_clvm(decoder: &impl ClvmDecoder<Node = N>, node: N) -> Result<Self, FromClvmError> {
let destructure_list!(parent_coin_info, puzzle_hash, amount) =
<match_list!(BytesImpl<32>, BytesImpl<32>, u64)>::from_clvm(a, ptr)?;
<match_list!(BytesImpl<32>, BytesImpl<32>, u64)>::from_clvm(decoder, node)?;
Ok(Coin {
parent_coin_info,
puzzle_hash,
Expand All @@ -74,7 +75,10 @@ impl FromClvm for Coin {
#[cfg(test)]
mod tests {
use super::*;
use clvmr::serde::{node_from_bytes, node_to_bytes};
use clvmr::{
serde::{node_from_bytes, node_to_bytes},
Allocator,
};
use rstest::rstest;

#[rstest]
Expand Down
21 changes: 10 additions & 11 deletions chia-protocol/src/program.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::bytes::Bytes;
use chia_traits::chia_error::{Error, Result};
use chia_traits::Streamable;
use clvm_traits::{FromClvm, ToClvm};
use clvm_traits::{FromClvmError, FromNodePtr, ToClvmError, ToNodePtr};
use clvmr::allocator::NodePtr;
use clvmr::serde::{node_from_bytes, node_to_bytes, serialized_length_from_bytes};
use clvmr::Allocator;
Expand Down Expand Up @@ -105,20 +105,19 @@ impl FromJsonDict for Program {
}
}

impl FromClvm for Program {
fn from_clvm(a: &Allocator, ptr: NodePtr) -> clvm_traits::Result<Self> {
impl FromNodePtr for Program {
fn from_node_ptr(a: &Allocator, node: NodePtr) -> std::result::Result<Self, FromClvmError> {
Ok(Self(
node_to_bytes(a, ptr)
.map_err(|error| clvm_traits::Error::Custom(error.to_string()))?
node_to_bytes(a, node)
.map_err(|error| FromClvmError::Custom(error.to_string()))?
.into(),
))
}
}

impl ToClvm for Program {
fn to_clvm(&self, a: &mut Allocator) -> clvm_traits::Result<NodePtr> {
node_from_bytes(a, self.0.as_ref())
.map_err(|error| clvm_traits::Error::Custom(error.to_string()))
impl ToNodePtr for Program {
fn to_node_ptr(&self, a: &mut Allocator) -> std::result::Result<NodePtr, ToClvmError> {
node_from_bytes(a, self.0.as_ref()).map_err(|error| ToClvmError::Custom(error.to_string()))
}
}

Expand All @@ -139,9 +138,9 @@ mod tests {
let expected_bytes = hex::decode(expected).unwrap();

let ptr = node_from_bytes(a, &expected_bytes).unwrap();
let program = Program::from_clvm(a, ptr).unwrap();
let program = Program::from_node_ptr(a, ptr).unwrap();

let round_trip = program.to_clvm(a).unwrap();
let round_trip = program.to_node_ptr(a).unwrap();
assert_eq!(expected, hex::encode(node_to_bytes(a, round_trip).unwrap()));
}
}
8 changes: 4 additions & 4 deletions chia-tools/src/bin/fast-forward-spend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use chia::fast_forward::fast_forward_singleton;
use chia_protocol::bytes::Bytes32;
use chia_protocol::{coin::Coin, coin_spend::CoinSpend, program::Program};
use chia_traits::streamable::Streamable;
use clvm_traits::{FromClvm, ToClvm};
use clvm_traits::{FromNodePtr, ToNodePtr};
use clvm_utils::tree_hash;
use clvmr::allocator::Allocator;

Expand Down Expand Up @@ -39,8 +39,8 @@ fn main() {
.into();

let mut a = Allocator::new_limited(500000000, 62500000, 62500000);
let puzzle = spend.puzzle_reveal.to_clvm(&mut a).expect("to_clvm");
let solution = spend.solution.to_clvm(&mut a).expect("to_clvm");
let puzzle = spend.puzzle_reveal.to_node_ptr(&mut a).expect("to_clvm");
let solution = spend.solution.to_node_ptr(&mut a).expect("to_clvm");
let puzzle_hash = Bytes32::from(tree_hash(&a, puzzle));

let new_parent_coin = Coin {
Expand Down Expand Up @@ -68,7 +68,7 @@ fn main() {
let new_spend = CoinSpend {
coin: new_parent_coin,
puzzle_reveal: spend.puzzle_reveal,
solution: Program::from_clvm(&a, new_solution).expect("new solution"),
solution: Program::from_node_ptr(&a, new_solution).expect("new solution"),
};
let mut bytes = Vec::<u8>::new();
new_spend.stream(&mut bytes).expect("stream CoinSpend");
Expand Down
Loading
Loading