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

add dependency on clvm-traits #352

Merged
merged 1 commit into from
Dec 6, 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
31 changes: 31 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ lazy_static = "=1.4.0"
num-bigint = "=0.4.3"
num-traits = "=0.2.15"
num-integer = "=0.1.45"
clvm-traits = "0.3.0"
# the experimental feature enables hashing to curves
bls12_381 = { version = "=0.8.0", features = ["experimental"] }
# the newer sha2 crate doesn't implement the digest traits required by HKDF
Expand Down
37 changes: 37 additions & 0 deletions src/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::err_utils::err;
use crate::number::{node_from_number, number_from_u8, Number};
use crate::reduction::EvalErr;
use bls12_381::{G1Affine, G1Projective, G2Affine, G2Projective};
use clvm_traits::{ClvmDecoder, ClvmEncoder, FromClvmError, ToClvmError};

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct NodePtr(pub i32);
Expand Down Expand Up @@ -334,6 +335,42 @@ impl Allocator {
}
}

impl ClvmEncoder for Allocator {
type Node = NodePtr;

fn encode_atom(&mut self, bytes: &[u8]) -> Result<Self::Node, ToClvmError> {
self.new_atom(bytes).or(Err(ToClvmError::OutOfMemory))
}

fn encode_pair(
&mut self,
first: Self::Node,
rest: Self::Node,
) -> Result<Self::Node, ToClvmError> {
self.new_pair(first, rest).or(Err(ToClvmError::OutOfMemory))
}
}

impl ClvmDecoder for Allocator {
type Node = NodePtr;

fn decode_atom(&self, node: &Self::Node) -> Result<&[u8], FromClvmError> {
if let SExp::Atom = self.sexp(*node) {
Ok(self.atom(*node))
} else {
Err(FromClvmError::ExpectedAtom)
}
}

fn decode_pair(&self, node: &Self::Node) -> Result<(Self::Node, Self::Node), FromClvmError> {
if let SExp::Pair(first, rest) = self.sexp(*node) {
Ok((first, rest))
} else {
Err(FromClvmError::ExpectedPair)
}
}
}

#[test]
fn test_atom_eq() {
let mut a = Allocator::new();
Expand Down
115 changes: 115 additions & 0 deletions src/from_node_ptr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use crate::{allocator::NodePtr, Allocator};

use clvm_traits::{ClvmDecoder, FromClvm, FromClvmError};

pub trait FromNodePtr {
fn from_node_ptr(a: &Allocator, node: NodePtr) -> Result<Self, FromClvmError>
where
Self: Sized;
}

impl<T> FromNodePtr for T
where
T: FromClvm<NodePtr>,
{
fn from_node_ptr(a: &Allocator, node: NodePtr) -> Result<Self, FromClvmError>
where
Self: Sized,
{
T::from_clvm(a, node)
}
}

impl FromClvm<NodePtr> for NodePtr {
fn from_clvm(
_decoder: &impl ClvmDecoder<Node = NodePtr>,
node: NodePtr,
) -> Result<Self, FromClvmError> {
Ok(node)
}
}

#[cfg(test)]
mod tests {
use crate::{allocator::NodePtr, serde::node_from_bytes, Allocator};

use super::*;

fn decode<T>(a: &mut Allocator, hex: &str) -> Result<T, FromClvmError>
where
T: FromClvm<NodePtr>,
{
let bytes = hex::decode(hex).unwrap();
let actual = node_from_bytes(a, &bytes).unwrap();
T::from_clvm(a, actual)
}

#[test]
fn test_nodeptr() {
let a = &mut Allocator::new();
let ptr = a.one();
assert_eq!(NodePtr::from_clvm(a, ptr).unwrap(), ptr);
}

#[test]
fn test_primitives() {
let a = &mut Allocator::new();
assert_eq!(decode(a, "80"), Ok(0u8));
assert_eq!(decode(a, "80"), Ok(0i8));
assert_eq!(decode(a, "05"), Ok(5u8));
assert_eq!(decode(a, "05"), Ok(5u32));
assert_eq!(decode(a, "05"), Ok(5i32));
assert_eq!(decode(a, "81e5"), Ok(-27i32));
assert_eq!(decode(a, "80"), Ok(-0));
assert_eq!(decode(a, "8180"), Ok(-128i8));
}

#[test]
fn test_pair() {
let a = &mut Allocator::new();
assert_eq!(decode(a, "ff0502"), Ok((5, 2)));
assert_eq!(decode(a, "ff81b8ff8301600980"), Ok((-72, (90121, ()))));
assert_eq!(
decode(a, "ffff80ff80ff80ffff80ff80ff80808080"),
Ok((((), ((), ((), (((), ((), ((), ()))), ())))), ()))
);
}

#[test]
fn test_nil() {
let a = &mut Allocator::new();
assert_eq!(decode(a, "80"), Ok(()));
}

#[test]
fn test_array() {
let a = &mut Allocator::new();
assert_eq!(decode(a, "ff01ff02ff03ff0480"), Ok([1, 2, 3, 4]));
assert_eq!(decode(a, "80"), Ok([] as [i32; 0]));
}

#[test]
fn test_vec() {
let a = &mut Allocator::new();
assert_eq!(decode(a, "ff01ff02ff03ff0480"), Ok(vec![1, 2, 3, 4]));
assert_eq!(decode(a, "80"), Ok(Vec::<i32>::new()));
}

#[test]
fn test_option() {
let a = &mut Allocator::new();
assert_eq!(decode(a, "8568656c6c6f"), Ok(Some("hello".to_string())));
assert_eq!(decode(a, "80"), Ok(None::<String>));

// Empty strings get decoded as None instead, since both values are represented by nil bytes.
// This could be considered either intended behavior or not, depending on the way it's used.
assert_ne!(decode(a, "80"), Ok(Some("".to_string())));
}

#[test]
fn test_string() {
let a = &mut Allocator::new();
assert_eq!(decode(a, "8568656c6c6f"), Ok("hello".to_string()));
assert_eq!(decode(a, "80"), Ok("".to_string()));
}
}
8 changes: 7 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ pub mod serde;
pub mod sha2;
pub mod traverse_path;

pub use allocator::Allocator;
pub mod from_node_ptr;
pub mod to_node_ptr;

pub use from_node_ptr::FromNodePtr;
pub use to_node_ptr::ToNodePtr;

pub use allocator::{Allocator, NodePtr};
pub use chia_dialect::ChiaDialect;
pub use run_program::run_program;

Expand Down
143 changes: 143 additions & 0 deletions src/to_node_ptr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
use crate::{allocator::NodePtr, Allocator};

use clvm_traits::{ClvmEncoder, ToClvm, ToClvmError};

pub trait ToNodePtr {
fn to_node_ptr(&self, a: &mut Allocator) -> Result<NodePtr, ToClvmError>;
}

impl<T> ToNodePtr for T
where
T: ToClvm<NodePtr>,
{
fn to_node_ptr(&self, a: &mut Allocator) -> Result<NodePtr, ToClvmError> {
self.to_clvm(a)
}
}

impl ToClvm<NodePtr> for NodePtr {
fn to_clvm(
&self,
_encoder: &mut impl ClvmEncoder<Node = NodePtr>,
) -> Result<NodePtr, ToClvmError> {
Ok(*self)
}
}

#[cfg(test)]
mod tests {
use crate::{serde::node_to_bytes, Allocator};
use hex::ToHex;

use super::*;

fn encode<T>(a: &mut Allocator, value: T) -> Result<String, ToClvmError>
where
T: ToClvm<NodePtr>,
{
let actual = value.to_clvm(a).unwrap();
let actual_bytes = node_to_bytes(a, actual).unwrap();
Ok(actual_bytes.encode_hex())
}

#[test]
fn test_nodeptr() {
let a = &mut Allocator::new();
let ptr = a.one();
assert_eq!(ptr.to_clvm(a).unwrap(), ptr);
}

#[test]
fn test_primitives() {
let a = &mut Allocator::new();
assert_eq!(encode(a, 0u8), Ok("80".to_owned()));
assert_eq!(encode(a, 0i8), Ok("80".to_owned()));
assert_eq!(encode(a, 5u8), Ok("05".to_owned()));
assert_eq!(encode(a, 5u32), Ok("05".to_owned()));
assert_eq!(encode(a, 5i32), Ok("05".to_owned()));
assert_eq!(encode(a, -27i32), Ok("81e5".to_owned()));
assert_eq!(encode(a, -0), Ok("80".to_owned()));
assert_eq!(encode(a, -128i8), Ok("8180".to_owned()));
}

#[test]
fn test_reference() {
let a = &mut Allocator::new();
assert_eq!(encode(a, [1, 2, 3]), encode(a, [1, 2, 3]));
assert_eq!(encode(a, Some(42)), encode(a, Some(42)));
assert_eq!(encode(a, Some(&42)), encode(a, Some(42)));
assert_eq!(encode(a, Some(&42)), encode(a, Some(42)));
}

#[test]
fn test_pair() {
let a = &mut Allocator::new();
assert_eq!(encode(a, (5, 2)), Ok("ff0502".to_owned()));
assert_eq!(
encode(a, (-72, (90121, ()))),
Ok("ff81b8ff8301600980".to_owned())
);
assert_eq!(
encode(a, (((), ((), ((), (((), ((), ((), ()))), ())))), ())),
Ok("ffff80ff80ff80ffff80ff80ff80808080".to_owned())
);
}

#[test]
fn test_nil() {
let a = &mut Allocator::new();
assert_eq!(encode(a, ()), Ok("80".to_owned()));
}

#[test]
fn test_slice() {
let a = &mut Allocator::new();
assert_eq!(
encode(a, [1, 2, 3, 4].as_slice()),
Ok("ff01ff02ff03ff0480".to_owned())
);
assert_eq!(encode(a, [0; 0].as_slice()), Ok("80".to_owned()));
}

#[test]
fn test_array() {
let a = &mut Allocator::new();
assert_eq!(encode(a, [1, 2, 3, 4]), Ok("ff01ff02ff03ff0480".to_owned()));
assert_eq!(encode(a, [0; 0]), Ok("80".to_owned()));
}

#[test]
fn test_vec() {
let a = &mut Allocator::new();
assert_eq!(
encode(a, vec![1, 2, 3, 4]),
Ok("ff01ff02ff03ff0480".to_owned())
);
assert_eq!(encode(a, vec![0; 0]), Ok("80".to_owned()));
}

#[test]
fn test_option() {
let a = &mut Allocator::new();
assert_eq!(encode(a, Some("hello")), Ok("8568656c6c6f".to_owned()));
assert_eq!(encode(a, None::<&str>), Ok("80".to_owned()));
assert_eq!(encode(a, Some("")), Ok("80".to_owned()));
}

#[test]
fn test_str() {
let a = &mut Allocator::new();
assert_eq!(encode(a, "hello"), Ok("8568656c6c6f".to_owned()));
assert_eq!(encode(a, ""), Ok("80".to_owned()));
}

#[test]
fn test_string() {
let a = &mut Allocator::new();
assert_eq!(
encode(a, "hello".to_string()),
Ok("8568656c6c6f".to_owned())
);
assert_eq!(encode(a, "".to_string()), Ok("80".to_owned()));
}
}
Loading