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 optional borsh serialization #84

Merged
merged 2 commits into from
Mar 16, 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
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ publish = true

[features]
default = ["ics23"]
borsh = ["dep:borsh"]
preston-evans98 marked this conversation as resolved.
Show resolved Hide resolved

[dependencies]
ics23 = { git = "https://github.com/penumbra-zone/ics23", branch = "compare-prehashed-keys", optional = true }
anyhow = "1.0.38"
borsh = { version = "0.10.0", optional = true}
byteorder = "1.4.3"
itertools = { version = "0.10.0", default-features = false }
mirai-annotations = "1.10.1"
Expand Down
12 changes: 12 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,18 @@ pub struct RootHash(pub [u8; 32]);
/// keys can be converted to a [`KeyHash`] using the provided `From` impl.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct KeyHash(pub [u8; 32]);

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
// This needs to be public for the fuzzing/Arbitrary feature, but we don't
// really want it to be, so #[doc(hidden)] is the next best thing.
#[doc(hidden)]
Expand Down Expand Up @@ -244,6 +252,10 @@ pub trait SimpleHasher: Sized {
/// structs to derive these traits even if the concrete hasher does not
/// implement them.
#[derive(Clone, Eq, Serialize, Deserialize)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct PhantomHasher<H: SimpleHasher>(std::marker::PhantomData<H>);

impl<H: SimpleHasher> Debug for PhantomHasher<H> {
Expand Down
28 changes: 28 additions & 0 deletions src/node_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ use crate::SimpleHasher;
/// The unique key of each node.
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct NodeKey {
// The version at which the node is created.
version: Version,
Expand Down Expand Up @@ -138,6 +142,10 @@ impl NodeKey {
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub enum NodeType {
Leaf,
/// A internal node that haven't been finished the leaf count migration, i.e. None or not all
Expand Down Expand Up @@ -166,6 +174,10 @@ impl Arbitrary for NodeType {
/// Each child of [`InternalNode`] encapsulates a nibble forking at this node.
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct Child {
/// The hash value of this child node.
pub hash: [u8; 32],
Expand Down Expand Up @@ -203,6 +215,10 @@ impl Child {
/// [`Children`] is just a collection of children belonging to a [`InternalNode`], indexed from 0 to
/// 15, inclusive.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct Children {
/// The actual children. We box this array to avoid stack overflows, since the space consumed
/// is somewhat large
Expand Down Expand Up @@ -311,6 +327,10 @@ impl Children {
/// computation logic is similar to a 4-level sparse Merkle tree except for some customizations. See
/// the `CryptoHash` trait implementation below for details.
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct InternalNode {
/// Up to 16 children.
children: Children,
Expand Down Expand Up @@ -802,6 +822,10 @@ pub(crate) fn get_child_half_start(n: Nibble, height: u8) -> u8 {
///
/// Note: this does not store the key itself.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct LeafNode {
/// The hash of the key for this entry.
key_hash: KeyHash,
Expand Down Expand Up @@ -850,6 +874,10 @@ enum NodeTag {

/// The concrete node type of [`JellyfishMerkleTree`](crate::JellyfishMerkleTree).
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub enum Node {
/// Represents `null`.
Null,
Expand Down
4 changes: 4 additions & 0 deletions src/types/nibble/nibble_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ use crate::types::nibble::{Nibble, ROOT_NIBBLE_HEIGHT};

/// NibblePath defines a path in Merkle tree in the unit of nibble (4 bits).
#[derive(Clone, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct NibblePath {
/// Indicates the total number of nibbles in bytes. Either `bytes.len() * 2 - 1` or
/// `bytes.len() * 2`.
Expand Down
4 changes: 4 additions & 0 deletions src/types/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ impl SparseMerkleInternalNode {

#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct SparseMerkleLeafNode {
key_hash: KeyHash,
value_hash: ValueHash,
Expand Down
8 changes: 8 additions & 0 deletions src/types/proof/definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ use crate::{
/// A proof that can be used to authenticate an element in a Sparse Merkle Tree given trusted root
/// hash. For example, `TransactionInfoToAccountProof` can be constructed on top of this structure.
#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct SparseMerkleProof<H: SimpleHasher> {
/// This proof can be used to authenticate whether a given leaf exists in the tree or not.
/// - If this is `Some(leaf_node)`
Expand Down Expand Up @@ -231,6 +235,10 @@ impl<H: SimpleHasher> SparseMerkleProof<H> {
/// if the proof wants show that `[a, b, c, d, e]` exists in the tree, it would need the siblings
/// `X` and `h` on the right.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct SparseMerkleRangeProof {
/// The vector of siblings on the right of the path from root to last leaf. The ones near the
/// bottom are at the beginning of the vector. In the above example, it's `[X, h]`.
Expand Down
16 changes: 16 additions & 0 deletions src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ pub trait TreeWriter {

/// Node batch that will be written into db atomically with other batches.
#[derive(Debug, Clone, PartialEq, Default, Eq)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct NodeBatch {
nodes: BTreeMap<NodeKey, Node>,
values: BTreeMap<(Version, KeyHash), Option<OwnedValue>>,
Expand Down Expand Up @@ -82,6 +86,10 @@ impl NodeBatch {
pub type StaleNodeIndexBatch = BTreeSet<StaleNodeIndex>;

#[derive(Clone, Debug, Default, Eq, PartialEq)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct NodeStats {
pub new_nodes: usize,
pub new_leaves: usize,
Expand All @@ -92,6 +100,10 @@ pub struct NodeStats {
/// Indicates a node becomes stale since `stale_since_version`.
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct StaleNodeIndex {
/// The version since when the node is overwritten and becomes stale.
pub stale_since_version: Version,
Expand All @@ -105,6 +117,10 @@ pub struct StaleNodeIndex {
/// the incremental updates of a tree and pruning indices after applying a write set,
/// which is a vector of `hashed_account_address` and `new_value` pairs.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
pub struct TreeUpdateBatch {
pub node_batch: NodeBatch,
pub stale_node_index_batch: StaleNodeIndexBatch,
Expand Down