Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
GCdePaula committed Aug 9, 2024
1 parent 2c1047f commit 5ec33b3
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 58 deletions.
5 changes: 3 additions & 2 deletions common-rs/merkle/src/digest/keccak.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Keccak256 hash for the Digest Type. It's used to hash the data in the Digest.

use sha3::{Keccak256, Digest as Keccak256Digest};
use sha3::{Digest as Keccak256Digest, Keccak256};

use super::Digest;

Expand All @@ -21,4 +21,5 @@ impl Digest {
let digest: [u8; 32] = keccak.finalize().into();
Digest::from(digest)
}
}
}

11 changes: 4 additions & 7 deletions common-rs/merkle/src/digest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ pub struct Digest {
}

impl Digest {
pub const ZERO: Digest = Digest::new([0; HASH_SIZE]);

/// Creates a new [Digest] with the provided 32-byte data.
pub fn new(data: [u8; HASH_SIZE]) -> Self {
pub const fn new(data: [u8; HASH_SIZE]) -> Self {
Digest { data }
}

Expand All @@ -45,7 +47,7 @@ impl Digest {

/// Attempts to create a [Digest] from a hexadecimal string.
pub fn from_digest_hex(digest_hex: &str) -> Result<Digest, DigestError> {
let data = Vec::from_hex(digest_hex)?;
let data = Vec::from_hex(&digest_hex[2..])?;
Self::from_digest(&data)
}

Expand All @@ -58,11 +60,6 @@ impl Digest {
hex::encode(self.data)
}

/// Creates a [Digest] with all bytes set to zero.
pub fn zeroed() -> Self {
Digest::new([0; HASH_SIZE])
}

/// Checks if the [Digest] is zeroed.
pub fn is_zeroed(&self) -> bool {
self.data.iter().all(|&x| x == 0)
Expand Down
5 changes: 3 additions & 2 deletions common-rs/merkle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
//! use cartesi_dave_merkle::{Digest, MerkleBuilder};
//!
//! let mut builder = MerkleBuilder::default();
//! builder.add_leaf_with_repetition(Digest::zeroed(), 2);
//! builder.add_leaf_with_repetition(Digest::zeroed(), 6);
//! builder.append(Digest::ZERO);
//! builder.append_repeated(Digest::ZERO, 2);
//! builder.append_repeated(Digest::ZERO, 5);
//! let merkle = builder.build();
//! ```
//!
Expand Down
57 changes: 42 additions & 15 deletions common-rs/merkle/src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ pub struct MerkleTree {

impl PartialEq for MerkleTree {
fn eq(&self, other: &Self) -> bool {
self.root_hash == other.root_hash
self.height == other.height && self.root_hash == other.root_hash
}
}

#[derive(Clone, Debug)]
pub enum InnerNode {
enum InnerNode {
Pair {
left: Arc<MerkleTree>,
right: Arc<MerkleTree>,
Expand All @@ -56,14 +56,20 @@ pub enum InnerNode {
}

impl InnerNode {
pub fn children(&self) -> (Arc<MerkleTree>, Arc<MerkleTree>) {
fn children(&self) -> (Arc<MerkleTree>, Arc<MerkleTree>) {
match &self {
InnerNode::Pair { left, right } => (Arc::clone(left), Arc::clone(right)),
InnerNode::Iterated { child } => (Arc::clone(child), Arc::clone(child)),
}
}
}

impl From<Digest> for Arc<MerkleTree> {
fn from(value: Digest) -> Self {
MerkleTree::leaf(value)
}
}

impl MerkleTree {
pub fn leaf(hash: Digest) -> Arc<Self> {
Arc::new(Self {
Expand All @@ -74,21 +80,24 @@ impl MerkleTree {
}

pub fn zeroed() -> Arc<Self> {
Self::leaf(Digest::zeroed())
Self::leaf(Digest::ZERO)
}

pub fn root_hash(&self) -> Digest {
self.root_hash
}

pub fn subtrees(&self) -> Option<InnerNode> {
self.subtrees.clone()
}

pub fn height(&self) -> u32 {
self.height
}

pub fn subtrees(&self) -> Option<(Arc<MerkleTree>, Arc<MerkleTree>)> {
match self.subtrees {
None => None,
Some(ref x) => Some(x.children()),
}
}

pub fn find_child(self: &Arc<Self>, digest: &Digest) -> Option<Arc<Self>> {
if self.root_hash == *digest {
return Some(Arc::clone(self));
Expand Down Expand Up @@ -183,23 +192,41 @@ impl MerkleTree {

#[cfg(test)]
mod tests {
use crate::Digest;
use crate::{Digest, MerkleTree};

#[test]
pub fn simple_tree() {
let zero_tree = MerkleTree::leaf(Digest::ZERO);
assert_eq!(zero_tree, MerkleTree::zeroed());
assert_eq!(zero_tree.root_hash(), Digest::ZERO);
assert_eq!(zero_tree.height(), 0);
assert!(zero_tree.subtrees().is_none());

let one_digest = Digest::from_digest_hex(
"0x0000000000000000000000000000000000000000000000000000000000000001",
)
.unwrap();
let one_tree = MerkleTree::leaf(one_digest);
assert_eq!(one_tree.root_hash(), one_digest);
assert_eq!(one_tree.height(), 0);
assert!(one_tree.subtrees().is_none());
}

#[test]
pub fn test_tree() {
let mut builder = crate::MerkleBuilder::default();
builder.add_leaf_with_repetition(Digest::zeroed(), 2);
builder.add_leaf_with_repetition(Digest::zeroed(), 2u128.pow(64) - 2);
builder.append_repeated(Digest::ZERO, 2);
builder.append_repeated(Digest::ZERO, 2u128.pow(64) - 2);
let tree = builder.build();

let proof = tree.prove_leaf(0);
assert_eq!(proof.node, Digest::zeroed());
assert_eq!(proof.node, Digest::ZERO);
}

#[test]
pub fn proof_test() {
let mut builder = crate::MerkleBuilder::default();
builder.add_leaf_with_repetition(Digest::zeroed(), 8);
builder.append_repeated(Digest::ZERO, 8);
let tree = builder.build();

let proof = tree.prove_leaf(0);
Expand All @@ -216,8 +243,8 @@ mod tests {
#[test]
pub fn last_proof_test() {
let mut builder = crate::MerkleBuilder::default();
builder.add_leaf_with_repetition(Digest::zeroed(), 2);
builder.add_leaf_with_repetition(Digest::zeroed(), 2u128.pow(64) - 2);
builder.append_repeated(Digest::ZERO, 2);
builder.append_repeated(Digest::ZERO, 2u128.pow(64) - 2);
let tree = builder.build();

let proof = tree.prove_last();
Expand Down
Loading

0 comments on commit 5ec33b3

Please sign in to comment.