Skip to content

Commit

Permalink
wip: merkle trees
Browse files Browse the repository at this point in the history
  • Loading branch information
mattrltrent committed Dec 17, 2024
1 parent 365d2a3 commit 451a04f
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 93 deletions.
19 changes: 1 addition & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,6 @@
This is a template for creating an end-to-end [SP1](https://github.com/succinctlabs/sp1) project
that can generate a proof of any RISC-V program.

## Short Hands

PROVE:

```sh
cd script
cargo run --release -- --prove
```

JUST EXEC:

```sh
cd script
cargo run --release -- --execute
```


## Requirements

- [Rust](https://rustup.rs/)
Expand Down Expand Up @@ -110,4 +93,4 @@ SP1_PROVER=network SP1_PRIVATE_KEY=... cargo run --release --bin evm

## Debugging Note

If you are running this on MacOS M1 aarch64, don't use `zsh` as your shell. Use `bash` instead; `zsh` throws unintelligible errors.
If you are running this on MacOS M1 aarch64, don't use `zsh` as your shell. Use `bash` instead; `zsh` throws unintelligible errors.
4 changes: 2 additions & 2 deletions lib2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ edition = "2021"

[dependencies]
alloy-sol-types = { workspace = true }
sha2 = "0.10" # For SHA256 hashing
hex = "0.4" # For hex encoding
sha2 = "0.10"
hex = "0.4"
59 changes: 59 additions & 0 deletions lib2/src/hash.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use sha2::{Digest, Sha256};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Hash([u8; 32]);

impl Hash {
pub fn new(data: &[u8]) -> Self {
let mut hasher = Sha256::new();
hasher.update(data);
Hash(hasher.finalize().into())
}

pub fn as_bytes(&self) -> &[u8; 32] {
&self.0
}

pub fn as_hex(&self) -> String {
self.0.iter().map(|b| format!("{:02x}", b)).collect()
}

pub fn combine(left: &Hash, right: &Hash) -> Self {
let mut combined_data = Vec::with_capacity(64);
combined_data.extend_from_slice(left.as_bytes());
combined_data.extend_from_slice(right.as_bytes());
Self::new(&combined_data)
}

pub fn empty() -> Self {
Hash([0u8; 32])
}

pub fn from_hex(hex: &str) -> Result<Self, Box<dyn std::error::Error>> {
if hex.len() != 64 {
// Each byte is represented by 2 hex characters, so 32 bytes = 64 hex chars
return Err("invalid hex string length: expected 64 characters".into());
}

let mut hash = [0u8; 32];
for i in 0..32 {
let byte = u8::from_str_radix(&hex[i * 2..i * 2 + 2], 16)
.map_err(|e| format!("failed to parse hex byte at position {}: {}", i, e))?;
hash[i] = byte;
}

Ok(Hash::new(&hash))
}
}

mod test {
#[test]
fn test_hash() {
let data = b"hello world";
let hash = crate::hash::Hash::new(data);
assert_eq!(
hash.as_hex(),
"b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
);
}
}
3 changes: 3 additions & 0 deletions lib2/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
pub mod hash;
pub mod merkle_proof;
pub mod merkle_tree;
pub mod node;
pub mod solidity;
16 changes: 16 additions & 0 deletions lib2/src/merkle_proof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::{hash::Hash, node::Node};

#[derive(Debug)]
pub struct MerkleProof {
proof: Vec<Hash>,
}

impl MerkleProof {
pub fn new(proof: Vec<Hash>) -> Self {
MerkleProof { proof }
}

pub fn verify(&self, root: Node<T>) -> Result<bool, Box<dyn std::error::Error>> {
Ok(true) // todo: implement
}
}
19 changes: 19 additions & 0 deletions lib2/src/merkle_tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use crate::node::Node;
use crate::hash::Hash;

pub struct MerkleTree<T>
where
T: Clone + AsRef<[u8]>,
{
root: Node<T>,
leaves: Vec<Node<T>>,
}

impl<T> MerkleTree<T>
where
T: Clone + AsRef<[u8]>,
{
// pub fn new()
}


Empty file.
2 changes: 0 additions & 2 deletions lib2/src/merkle_tree/mod.rs

This file was deleted.

71 changes: 0 additions & 71 deletions lib2/src/merkle_tree/node.rs

This file was deleted.

70 changes: 70 additions & 0 deletions lib2/src/node.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use crate::hash::Hash;

/// Represents a node in a Merkle Tree.
#[derive(Debug, Clone)]
pub struct Node<T>
where
T: AsRef<[u8]> + Clone,
{
hash: Hash, // Hash of the node
is_leaf: bool, // Is this node a leaf?
data: Option<T>, // Data for leaf nodes
}

impl<T> Node<T>
where
T: AsRef<[u8]> + Clone,
{
/// Create a new leaf node from the given data.
pub fn new(data: Option<T>) -> Self {
let is_leaf = data.is_some();
let hash = if let Some(ref value) = data {
Hash::new(value.as_ref())
} else {
Hash::empty()
};

Node {
hash,
is_leaf,
data,
}
}

/// Combine two child nodes to create a new parent node.
pub fn new_from_children(left: &Node<T>, right: &Node<T>) -> Self {
let combined_hash = Hash::combine(&left.hash, &right.hash);

Node {
hash: combined_hash,
is_leaf: false,
data: None,
}
}

/// Retrieve the hash of the node.
pub fn hash(&self) -> &Hash {
&self.hash
}

/// Check if the node is a leaf.
pub fn is_leaf(&self) -> bool {
self.is_leaf
}

/// Retrieve the data (if any).
pub fn data(&self) -> Option<T> {
self.data.clone()
}
}


mod tests {
#[test]
fn test_node() {
let data = b"hello world";
let node = crate::node::Node::new(Some(data));
assert_eq!(node.is_leaf(), true);
assert_eq!(node.data(), Some(data));
}
}

0 comments on commit 451a04f

Please sign in to comment.