Skip to content

Commit 3bac29f

Browse files
committed
feat: migrate to lambdaworks merkle tree in sdk
1 parent 04d8f78 commit 3bac29f

File tree

1 file changed

+42
-26
lines changed

1 file changed

+42
-26
lines changed

batcher/aligned-sdk/src/sdk/aggregation.rs

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use ethers::{
66
providers::{Http, Middleware, Provider},
77
types::Filter,
88
};
9+
use lambdaworks_crypto::merkle_tree::{merkle::MerkleTree, traits::IsMerkleTreeBackend};
910
use sha3::{Digest, Keccak256};
1011

1112
/// How much to go back from current block if from_block is not provided
@@ -24,6 +25,12 @@ pub enum AggregationModeVerificationData {
2425
},
2526
}
2627

28+
impl Default for AggregationModeVerificationData {
29+
fn default() -> Self {
30+
todo!()
31+
}
32+
}
33+
2734
impl AggregationModeVerificationData {
2835
fn commitment(&self) -> [u8; 32] {
2936
match self {
@@ -46,6 +53,33 @@ impl AggregationModeVerificationData {
4653
}
4754
}
4855

56+
// We use a newtype wrapper around `[u8; 32]` because Rust's orphan rule
57+
// prevents implementing a foreign trait (`IsMerkleTreeBackend`) for a foreign type (`[u8; 32]`).
58+
#[derive(Default, PartialEq, Eq)]
59+
struct Hash32([u8; 32]);
60+
61+
impl IsMerkleTreeBackend for Hash32 {
62+
type Data = Hash32;
63+
type Node = [u8; 32];
64+
65+
fn hash_data(leaf: &Self::Data) -> Self::Node {
66+
let mut hasher = Keccak256::new();
67+
hasher.update(leaf.0);
68+
hasher.finalize().into()
69+
}
70+
71+
fn hash_leaves(leaves: &[Self::Data]) -> Vec<Self::Node> {
72+
leaves.iter().map(|l| l.0).collect()
73+
}
74+
75+
fn hash_new_parent(child_1: &Self::Node, child_2: &Self::Node) -> Self::Node {
76+
let mut hasher = Keccak256::new();
77+
hasher.update(child_1);
78+
hasher.update(child_2);
79+
hasher.finalize().into()
80+
}
81+
}
82+
4983
#[derive(Debug)]
5084
pub enum ProofVerificationAggModeError {
5185
ProvingSystemNotSupportedInAggMode,
@@ -158,10 +192,14 @@ pub async fn is_proof_verified_in_aggregation_mode(
158192

159193
let blob_bytes =
160194
hex::decode(blob_data.blob.replace("0x", "")).expect("A valid hex encoded data");
161-
let proof_commitments = decoded_blob(blob_bytes);
162-
163-
if proof_commitments.contains(&verification_data.commitment()) {
164-
return if verify_blob_merkle_root(proof_commitments, merkle_root) {
195+
let proof_commitments: Vec<Hash32> = decoded_blob(blob_bytes)
196+
.iter()
197+
.map(|p| Hash32(*p))
198+
.collect();
199+
let merkle_tree: MerkleTree<Hash32> = MerkleTree::build(&proof_commitments).unwrap();
200+
201+
if proof_commitments.contains(&Hash32(verification_data.commitment())) {
202+
return if merkle_tree.root == merkle_root {
165203
Ok(merkle_root)
166204
} else {
167205
Err(ProofVerificationAggModeError::UnmatchedBlobAndEventMerkleRoot)
@@ -206,25 +244,3 @@ fn decoded_blob(blob_data: Vec<u8>) -> Vec<[u8; 32]> {
206244

207245
proof_hashes
208246
}
209-
210-
pub fn combine_hashes(hash_a: &[u8; 32], hash_b: &[u8; 32]) -> [u8; 32] {
211-
let mut hasher = Keccak256::new();
212-
hasher.update(hash_a);
213-
hasher.update(hash_b);
214-
hasher.finalize().into()
215-
}
216-
217-
fn verify_blob_merkle_root(mut commitments: Vec<[u8; 32]>, merkle_root: [u8; 32]) -> bool {
218-
while commitments.len() > 1 {
219-
commitments = commitments
220-
.chunks(2)
221-
.map(|chunk| match chunk {
222-
[a, b] => combine_hashes(a, b),
223-
[a] => combine_hashes(a, a),
224-
_ => panic!("Unexpected chunk size in leaves"),
225-
})
226-
.collect()
227-
}
228-
229-
commitments[0] == merkle_root
230-
}

0 commit comments

Comments
 (0)