pub(crate) mod definition;
#[cfg(all(test, feature = "std"))]
pub(crate) mod proptest_proof;
use crate::{
proof::SparseMerkleNode::{Internal, Leaf},
SimpleHasher,
};
#[cfg(all(test, feature = "std"))]
use proptest_derive::Arbitrary;
pub use self::definition::{SparseMerkleProof, SparseMerkleRangeProof, UpdateMerkleProof};
use crate::{KeyHash, ValueHash, SPARSE_MERKLE_PLACEHOLDER_HASH};
use borsh::{BorshDeserialize, BorshSerialize};
use serde::{Deserialize, Serialize};
pub const LEAF_DOMAIN_SEPARATOR: &[u8] = b"JMT::LeafNode";
pub const INTERNAL_DOMAIN_SEPARATOR: &[u8] = b"JMT::IntrnalNode";
#[cfg_attr(all(test, feature = "std"), derive(Arbitrary))]
#[derive(
Serialize, Deserialize, Clone, Copy, Eq, PartialEq, BorshSerialize, BorshDeserialize, Debug,
)]
pub(crate) enum SparseMerkleNode {
Null,
Internal(SparseMerkleInternalNode),
Leaf(SparseMerkleLeafNode),
}
impl SparseMerkleNode {
pub(crate) fn hash<H: SimpleHasher>(&self) -> [u8; 32] {
match self {
SparseMerkleNode::Null => SPARSE_MERKLE_PLACEHOLDER_HASH,
Internal(node) => node.hash::<H>(),
Leaf(node) => node.hash::<H>(),
}
}
}
#[derive(
Serialize, Deserialize, Clone, Copy, Eq, PartialEq, BorshSerialize, BorshDeserialize, Debug,
)]
#[cfg_attr(all(test, feature = "std"), derive(Arbitrary))]
pub(crate) struct SparseMerkleInternalNode {
left_child: [u8; 32],
right_child: [u8; 32],
}
impl SparseMerkleInternalNode {
pub fn new(left_child: [u8; 32], right_child: [u8; 32]) -> Self {
Self {
left_child,
right_child,
}
}
pub fn hash<H: SimpleHasher>(&self) -> [u8; 32] {
let mut hasher = H::new();
hasher.update(INTERNAL_DOMAIN_SEPARATOR);
hasher.update(&self.left_child);
hasher.update(&self.right_child);
hasher.finalize()
}
}
#[derive(Eq, Copy, Serialize, Deserialize, borsh::BorshSerialize, borsh::BorshDeserialize)]
pub struct SparseMerkleLeafNode {
key_hash: KeyHash,
value_hash: ValueHash,
}
#[cfg(any(test))]
impl proptest::arbitrary::Arbitrary for SparseMerkleLeafNode {
type Parameters = ();
type Strategy = proptest::strategy::BoxedStrategy<Self>;
fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
use proptest::{arbitrary::any, strategy::Strategy};
(any::<KeyHash>(), any::<ValueHash>())
.prop_map(|(key_hash, value_hash)| Self {
key_hash,
value_hash,
})
.boxed()
}
}
impl Clone for SparseMerkleLeafNode {
fn clone(&self) -> Self {
Self {
key_hash: self.key_hash.clone(),
value_hash: self.value_hash.clone(),
}
}
}
impl core::fmt::Debug for SparseMerkleLeafNode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SparseMerkleLeafNode")
.field("key_hash", &self.key_hash)
.field("value_hash", &self.value_hash)
.finish()
}
}
impl PartialEq for SparseMerkleLeafNode {
fn eq(&self, other: &Self) -> bool {
self.key_hash == other.key_hash && self.value_hash == other.value_hash
}
}
impl SparseMerkleLeafNode {
pub(crate) fn new(key_hash: KeyHash, value_hash: ValueHash) -> Self {
SparseMerkleLeafNode {
key_hash,
value_hash,
}
}
pub(crate) fn key_hash(&self) -> KeyHash {
self.key_hash
}
pub(crate) fn hash<H: SimpleHasher>(&self) -> [u8; 32] {
let mut hasher = H::new();
hasher.update(LEAF_DOMAIN_SEPARATOR);
hasher.update(&self.key_hash.0);
hasher.update(&self.value_hash.0);
hasher.finalize()
}
}