Skip to content

Commit

Permalink
Implement Arbitrary (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelsproul authored Apr 12, 2023
1 parent 373b601 commit 4035d25
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 16 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ triomphe = "0.1.5"
typenum = "1.14.0"
vec_map = "0.8.2"
smallvec = "1.8.0"
arbitrary = { version = "1.2.3", features = ["derive"] }
ethereum-types = { version = "0.14.1", features = ["arbitrary"] }

[dev-dependencies]
ssz_types = "0.5.0"
Expand Down
3 changes: 2 additions & 1 deletion src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{
iter::Iter,
Cow, Error,
};
use arbitrary::Arbitrary;
use std::collections::BTreeMap;
use std::marker::PhantomData;
use tree_hash::{Hash256, TreeHash};
Expand Down Expand Up @@ -37,7 +38,7 @@ where
) -> Result<(), Error>;
}

#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq, Clone, Arbitrary)]
pub struct Interface<T, B, U>
where
T: TreeHash + Clone,
Expand Down
10 changes: 8 additions & 2 deletions src/leaf.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
use crate::Arc;
use crate::{
utils::{arb_arc, arb_rwlock},
Arc,
};
use arbitrary::Arbitrary;
use derivative::Derivative;
use parking_lot::RwLock;
use tree_hash::Hash256;

#[derive(Debug, Derivative)]
#[derive(Debug, Derivative, Arbitrary)]
#[derivative(PartialEq, Hash)]
pub struct Leaf<T> {
#[derivative(PartialEq = "ignore", Hash = "ignore")]
#[arbitrary(with = arb_rwlock)]
pub hash: RwLock<Hash256>,
#[arbitrary(with = arb_arc)]
pub value: Arc<T>,
}

Expand Down
12 changes: 9 additions & 3 deletions src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use crate::interface_iter::{InterfaceIter, InterfaceIterCow};
use crate::iter::Iter;
use crate::serde::ListVisitor;
use crate::update_map::MaxMap;
use crate::utils::{int_log, opt_packing_depth, updated_length, Length};
use crate::utils::{arb_arc, int_log, opt_packing_depth, updated_length, Length};
use crate::{Arc, Cow, Error, Tree, UpdateMap};
use arbitrary::Arbitrary;
use derivative::Derivative;
use itertools::process_results;
use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};
Expand All @@ -16,20 +17,25 @@ use tree_hash::{Hash256, PackedEncoding, TreeHash};
use typenum::Unsigned;
use vec_map::VecMap;

#[derive(Debug, Clone, Derivative)]
#[derive(Debug, Clone, Derivative, Arbitrary)]
#[derivative(PartialEq(
bound = "T: TreeHash + PartialEq + Clone, N: Unsigned, U: UpdateMap<T> + PartialEq"
))]
#[arbitrary(bound = "T: Arbitrary<'arbitrary> + TreeHash + PartialEq + Clone")]
#[arbitrary(bound = "N: Unsigned, U: Arbitrary<'arbitrary> + UpdateMap<T> + PartialEq")]
pub struct List<T: TreeHash + Clone, N: Unsigned, U: UpdateMap<T> = MaxMap<VecMap<T>>> {
pub(crate) interface: Interface<T, ListInner<T, N>, U>,
}

#[derive(Debug, Clone, Derivative)]
#[derive(Debug, Clone, Derivative, Arbitrary)]
#[derivative(PartialEq(bound = "T: TreeHash + PartialEq + Clone, N: Unsigned"))]
#[arbitrary(bound = "T: Arbitrary<'arbitrary> + TreeHash + PartialEq + Clone, N: Unsigned")]
pub struct ListInner<T: TreeHash + Clone, N: Unsigned> {
#[arbitrary(with = arb_arc)]
pub(crate) tree: Arc<Tree<T>>,
pub(crate) length: Length,
pub(crate) depth: usize,
#[arbitrary(default)]
_phantom: PhantomData<N>,
}

Expand Down
6 changes: 4 additions & 2 deletions src/packed_leaf.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use crate::{Error, UpdateMap};
use crate::{utils::arb_rwlock, Error, UpdateMap};
use arbitrary::Arbitrary;
use derivative::Derivative;
use parking_lot::RwLock;
use std::ops::ControlFlow;
use tree_hash::{Hash256, TreeHash, BYTES_PER_CHUNK};

#[derive(Debug, Derivative)]
#[derive(Debug, Derivative, Arbitrary)]
#[derivative(PartialEq, Hash)]
pub struct PackedLeaf<T: TreeHash + Clone> {
#[derivative(PartialEq = "ignore", Hash = "ignore")]
#[arbitrary(with = arb_rwlock)]
pub hash: RwLock<Hash256>,
pub(crate) values: Vec<T>,
}
Expand Down
8 changes: 6 additions & 2 deletions src/tree.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::utils::{opt_hash, opt_packing_depth, opt_packing_factor};
use crate::utils::{arb_arc, arb_rwlock, opt_hash, opt_packing_depth, opt_packing_factor};
use crate::{Arc, Error, Leaf, PackedLeaf, UpdateMap};
use arbitrary::Arbitrary;
use derivative::Derivative;
use ethereum_hashing::{hash32_concat, ZERO_HASHES};
use parking_lot::RwLock;
Expand All @@ -10,15 +11,18 @@ use std::collections::BTreeMap;
use std::ops::ControlFlow;
use tree_hash::{Hash256, TreeHash};

#[derive(Debug, Derivative)]
#[derive(Debug, Derivative, Arbitrary)]
#[derivative(PartialEq, Hash)]
pub enum Tree<T: TreeHash + Clone> {
Leaf(Leaf<T>),
PackedLeaf(PackedLeaf<T>),
Node {
#[derivative(PartialEq = "ignore", Hash = "ignore")]
#[arbitrary(with = arb_rwlock)]
hash: RwLock<Hash256>,
#[arbitrary(with = arb_arc)]
left: Arc<Self>,
#[arbitrary(with = arb_arc)]
right: Arc<Self>,
},
Zero(usize),
Expand Down
5 changes: 4 additions & 1 deletion src/update_map.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::cow::{BTreeCow, Cow, VecCow};
use crate::utils::max_btree_index;
use arbitrary::Arbitrary;
use std::collections::{btree_map::Entry, BTreeMap};
use std::ops::ControlFlow;
use vec_map::VecMap;
Expand Down Expand Up @@ -162,8 +163,10 @@ impl<T: Clone> UpdateMap<T> for VecMap<T> {
}
}

#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, PartialEq, Arbitrary)]
#[arbitrary(bound = "M: Default")]
pub struct MaxMap<M> {
#[arbitrary(default)]
inner: M,
max_key: usize,
}
Expand Down
18 changes: 16 additions & 2 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::UpdateMap;
use crate::{Arc, UpdateMap};
use arbitrary::Arbitrary;
use parking_lot::RwLock;
use std::collections::BTreeMap;
use tree_hash::{Hash256, TreeHash, TreeHashType};

/// Length type, to avoid confusion with depth and other `usize` parameters.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Arbitrary)]
pub struct Length(pub usize);

impl Length {
Expand Down Expand Up @@ -60,3 +62,15 @@ pub fn opt_hash(
) -> Option<Hash256> {
hashes?.get(&(depth, prefix)).copied()
}

pub fn arb_arc<'a, T: Arbitrary<'a>>(
u: &mut arbitrary::Unstructured<'a>,
) -> arbitrary::Result<Arc<T>> {
T::arbitrary(u).map(Arc::new)
}

pub fn arb_rwlock<'a, T: Arbitrary<'a>>(
u: &mut arbitrary::Unstructured<'a>,
) -> arbitrary::Result<RwLock<T>> {
T::arbitrary(u).map(RwLock::new)
}
12 changes: 9 additions & 3 deletions src/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use crate::interface::{ImmList, Interface, MutList};
use crate::interface_iter::InterfaceIter;
use crate::iter::Iter;
use crate::update_map::MaxMap;
use crate::utils::Length;
use crate::utils::{arb_arc, Length};
use crate::{Arc, Cow, Error, List, Tree, UpdateMap};
use arbitrary::Arbitrary;
use derivative::Derivative;
use serde::{Deserialize, Serialize};
use ssz::{Decode, Encode, SszEncoder, TryFromIter, BYTES_PER_LENGTH_OFFSET};
Expand All @@ -14,7 +15,7 @@ use tree_hash::{Hash256, PackedEncoding, TreeHash};
use typenum::Unsigned;
use vec_map::VecMap;

#[derive(Debug, Derivative, Clone, Serialize, Deserialize)]
#[derive(Debug, Derivative, Clone, Serialize, Deserialize, Arbitrary)]
#[derivative(PartialEq(
bound = "T: TreeHash + Clone + PartialEq, N: Unsigned, U: UpdateMap<T> + PartialEq"
))]
Expand All @@ -24,15 +25,20 @@ use vec_map::VecMap;
#[serde(bound(
deserialize = "T: TreeHash + Clone + Deserialize<'de>, N: Unsigned, U: UpdateMap<T>"
))]
#[arbitrary(bound = "T: Arbitrary<'arbitrary> + TreeHash + Clone")]
#[arbitrary(bound = "N: Unsigned, U: Arbitrary<'arbitrary> + UpdateMap<T>")]
pub struct Vector<T: TreeHash + Clone, N: Unsigned, U: UpdateMap<T> = MaxMap<VecMap<T>>> {
pub(crate) interface: Interface<T, VectorInner<T, N>, U>,
}

#[derive(Debug, Derivative, Clone)]
#[derive(Debug, Derivative, Clone, Arbitrary)]
#[derivative(PartialEq(bound = "T: TreeHash + Clone + PartialEq, N: Unsigned"))]
#[arbitrary(bound = "T: Arbitrary<'arbitrary> + TreeHash + Clone, N: Unsigned")]
pub struct VectorInner<T: TreeHash + Clone, N: Unsigned> {
#[arbitrary(with = arb_arc)]
pub(crate) tree: Arc<Tree<T>>,
pub(crate) depth: usize,
#[arbitrary(default)]
_phantom: PhantomData<N>,
}

Expand Down

0 comments on commit 4035d25

Please sign in to comment.