Skip to content

Commit

Permalink
[feat] Draft: Da Verifier (#126)
Browse files Browse the repository at this point in the history
* Initial work for DA verifier and rollup inclusion proof test

* cleanup todos

* Scarb fmt

* feat: da verifier (#129)

* Added doc

* test_verifier WIP

* test_verifier done

* Update

* Added doc

* test_rollup_inclusion_proofs WIP

* test_rollup_inclusion_proofs done

* TODOs comments

* Scarb fmt

* Fix types on indexes and things to reduce number of felts needed, cleaned up TODOs

* Use sol_abi encode_packed

---------

Co-authored-by: 0xK2 <[email protected]>
  • Loading branch information
b-j-roberts and thomas192 committed Mar 27, 2024
1 parent 7702154 commit ea5ba8a
Show file tree
Hide file tree
Showing 17 changed files with 1,666 additions and 201 deletions.
1 change: 0 additions & 1 deletion src/blobstreamx.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ mod blobstreamx {
.encode_packed(data_root.data_root);

let (is_proof_valid, _) = merkle_tree::verify(root, @proof, @data_root_bytes);

is_proof_valid
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ mod tree {
mod hasher;
mod merkle_tree;
mod namespace;
use namespace::Namespace;
use namespace::{Namespace, NamespaceValueTrait};
#[cfg(test)]
mod tests {
mod test_hasher;
Expand All @@ -47,9 +47,11 @@ mod tree {
}

mod verifier {
mod da_verifier;
mod types;
#[cfg(test)]
mod tests {
mod test_rollup_inclusion_proofs;
mod test_verifier;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/tests/test_blobstreamx.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ fn test_verify_attestation() {
0xb5d4d27ec6b206a205bf09dde3371ffba62e5b53d27bbec4255b7f4f27ef5d90,
0x406e22ba94989ca721453057a1391fc531edb342c86a0ab4cc722276b54036ec,
];
let key: u256 = 2;
let num_leaves: u256 = 4;
let key: u32 = 2;
let num_leaves: u32 = 4;
let proof = BinaryMerkleProof { side_nodes, key, num_leaves, };

let is_proof_valid: bool = bsx.verify_attestation(proof_nonce, data, proof);
Expand Down
6 changes: 3 additions & 3 deletions src/tree/binary/hasher.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn node_digest(left: u256, right: u256) -> u256 {
}

fn leaf_digest(data: @Bytes) -> u256 {
let mut bytes = BytesTrait::new_empty().encode_packed(LEAF_PREFIX);
bytes.concat(data);
bytes.sha256()
let mut digest: Bytes = BytesTrait::new_empty().encode_packed(LEAF_PREFIX);
digest.concat(data);
digest.sha256()
}
4 changes: 2 additions & 2 deletions src/tree/binary/merkle_proof.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ struct BinaryMerkleProof {
// list of side nodes to verify and calculate tree
side_nodes: Array<u256>,
// key of the leaf to verify
key: u256,
key: u32,
// number of leaves in the tree
num_leaves: u256,
num_leaves: u32,
}
11 changes: 4 additions & 7 deletions src/tree/binary/merkle_tree.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use blobstream_sn::tree::binary::hasher::{leaf_digest, node_digest};
use blobstream_sn::tree::binary::merkle_proof::BinaryMerkleProof;
use blobstream_sn::tree::utils::{path_length_from_key, get_split_point};

#[derive(Copy, Drop, PartialEq)]
#[derive(Copy, Drop, PartialEq, Debug)]
enum ErrorCodes {
NoError,
InvalidNumberOfSideNodes,
Expand All @@ -20,10 +20,7 @@ fn verify(root: u256, proof: @BinaryMerkleProof, data: @Bytes) -> (bool, ErrorCo
if (proof.side_nodes.len() != 0) {
return (false, ErrorCodes::InvalidNumberOfSideNodes);
}
} else if (proof
.side_nodes
.len()
.into() != path_length_from_key(*proof.key, *proof.num_leaves)) {
} else if (proof.side_nodes.len() != path_length_from_key(*proof.key, *proof.num_leaves)) {
return (false, ErrorCodes::InvalidNumberOfSideNodes);
}

Expand Down Expand Up @@ -57,7 +54,7 @@ fn verify(root: u256, proof: @BinaryMerkleProof, data: @Bytes) -> (bool, ErrorCo

// Use the `leaf_hash` and `side_nodes` to recusively compute the root hash of the Merkle tree.
fn compute_root_hash(
key: u256, num_leaves: u256, leaf_hash: u256, side_nodes: Span<u256>
key: u32, num_leaves: u32, leaf_hash: u256, side_nodes: Span<u256>
) -> (u256, ErrorCodes) {
// Handle the base case(s) of the recursion.
if (num_leaves == 0) {
Expand All @@ -74,7 +71,7 @@ fn compute_root_hash(
}

// Recursively compute the hashes of the subtrees.
let num_left: u256 = get_split_point(num_leaves);
let num_left: u32 = get_split_point(num_leaves);
let side_nodes_left: Span<u256> = side_nodes.slice(0, side_nodes.len() - 1);
if (key < num_left) {
// Left subtree
Expand Down
74 changes: 37 additions & 37 deletions src/tree/binary/tests/test_merkle_proof.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use blobstream_sn::tree::binary::merkle_tree;
fn verify_none_test() {
let root: u256 = BytesTrait::new_empty().sha256();
let side_nodes: Array<u256> = array![];
let key: u256 = 0;
let num_leaves: u256 = 0;
let key: u32 = 0;
let num_leaves: u32 = 0;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty();
let (is_valid, _) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -20,8 +20,8 @@ fn verify_none_test() {
fn verify_one_leaf_empty_test() {
let root: u256 = 0x6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d;
let side_nodes: Array<u256> = array![];
let key: u256 = 0;
let num_leaves: u256 = 1;
let key: u32 = 0;
let num_leaves: u32 = 1;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty();
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -33,8 +33,8 @@ fn verify_one_leaf_empty_test() {
fn verify_one_leaf_test() {
let root: u256 = 0x48c90c8ae24688d6bef5d48a30c2cc8b6754335a8db21793cc0a8e3bed321729;
let side_nodes: Array<u256> = array![];
let key: u256 = 0;
let num_leaves: u256 = 1;
let key: u32 = 0;
let num_leaves: u32 = 1;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0xdeadbeef_u32);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -46,8 +46,8 @@ fn verify_one_leaf_test() {
fn verify_one_leaf_01_test() {
let root: u256 = 0xb413f47d13ee2fe6c845b2ee141af81de858df4ec549a58b7970bb96645bc8d2;
let side_nodes: Array<u256> = array![];
let key: u256 = 0;
let num_leaves: u256 = 1;
let key: u32 = 0;
let num_leaves: u32 = 1;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x01_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -63,8 +63,8 @@ fn verify_leaf_one_of_eight_test() {
0x78850a5ab36238b076dd99fd258c70d523168704247988a94caa8c9ccd056b8d,
0x4301a067262bbb18b4919742326f6f6d706099f9c0e8b0f2db7b88f204b2cf09
];
let key: u256 = 0;
let num_leaves: u256 = 8;
let key: u32 = 0;
let num_leaves: u32 = 8;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x01_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -80,8 +80,8 @@ fn verify_leaf_two_of_eight_test() {
0x78850a5ab36238b076dd99fd258c70d523168704247988a94caa8c9ccd056b8d,
0x4301a067262bbb18b4919742326f6f6d706099f9c0e8b0f2db7b88f204b2cf09
];
let key: u256 = 1;
let num_leaves: u256 = 8;
let key: u32 = 1;
let num_leaves: u32 = 8;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x02_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -97,8 +97,8 @@ fn verify_leaf_three_of_eight_test() {
0x6bcf0e2e93e0a18e22789aee965e6553f4fbe93f0acfc4a705d691c8311c4965,
0x4301a067262bbb18b4919742326f6f6d706099f9c0e8b0f2db7b88f204b2cf09
];
let key: u256 = 2;
let num_leaves: u256 = 8;
let key: u32 = 2;
let num_leaves: u32 = 8;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x03_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -114,8 +114,8 @@ fn verify_leaf_seven_of_eight_test() {
0x90eeb2c4a04ec33ee4dd2677593331910e4203db4fcc120a6cdb95b13cfe83f0,
0xfa02d31a63cc11cc624881e52af14af7a1c6ab745efa71021cb24086b9b1793f
];
let key: u256 = 6;
let num_leaves: u256 = 8;
let key: u32 = 6;
let num_leaves: u32 = 8;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x07_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -131,8 +131,8 @@ fn verify_leaf_eight_of_eight_test() {
0x90eeb2c4a04ec33ee4dd2677593331910e4203db4fcc120a6cdb95b13cfe83f0,
0xfa02d31a63cc11cc624881e52af14af7a1c6ab745efa71021cb24086b9b1793f
];
let key: u256 = 7;
let num_leaves: u256 = 8;
let key: u32 = 7;
let num_leaves: u32 = 8;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x08_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -149,8 +149,8 @@ fn verify_proof_of_five_leaves_test() {
0x4f35212d12f9ad2036492c95f1fe79baf4ec7bd9bef3dffa7579f2293ff546a4
];

let key: u256 = 1;
let num_leaves: u256 = 5;
let key: u32 = 1;
let num_leaves: u32 = 5;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x01_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -170,8 +170,8 @@ fn verify_invalid_proof_root_test() {
0x4f35212d12f9ad2036492c95f1fe79baf4ec7bd9bef3dffa7579f2293ff546a4
];

let key: u256 = 1;
let num_leaves: u256 = 5;
let key: u32 = 1;
let num_leaves: u32 = 5;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x01_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -189,8 +189,8 @@ fn verify_invalid_proof_key_test() {
];

// correct key: u256 = 1;
let key: u256 = 2;
let num_leaves: u256 = 5;
let key: u32 = 2;
let num_leaves: u32 = 5;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x01_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -207,9 +207,9 @@ fn verify_invalid_proof_number_of_leaves_test() {
0x4f35212d12f9ad2036492c95f1fe79baf4ec7bd9bef3dffa7579f2293ff546a4
];

let key: u256 = 1;
// correct num_leaves: u256 = 5;
let num_leaves: u256 = 200;
let key: u32 = 1;
// correct num_leaves: u32 = 5;
let num_leaves: u32 = 200;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x01_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -230,8 +230,8 @@ fn verify_invalid_proof_side_nodes_test() {
0x5f35212d12f9ad2036492c95f1fe79baf4ec7bd9bef3dffa7579f2293ff546a4
];

let key: u256 = 1;
let num_leaves: u256 = 5;
let key: u32 = 1;
let num_leaves: u32 = 5;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x01_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -250,8 +250,8 @@ fn verify_invalid_proof_data_test() {
0x4f35212d12f9ad2036492c95f1fe79baf4ec7bd9bef3dffa7579f2293ff546a4
];

let key: u256 = 1;
let num_leaves: u256 = 5;
let key: u32 = 1;
let num_leaves: u32 = 5;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty() // correct .encode_packed(0x01_u8);
.encode_packed(0x012345_u32);
Expand All @@ -264,8 +264,8 @@ fn verify_invalid_proof_data_test() {
fn same_key_and_leaves_number_test() {
let root: u256 = 0xb855b42d6c30f5b087e05266783fbd6e394f7b926013ccaa67700a8b0c5a596f;
let side_nodes: Array<u256> = array![];
let key: u256 = 3;
let num_leaves: u256 = 3;
let key: u32 = 3;
let num_leaves: u32 = 3;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x01_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -280,8 +280,8 @@ fn same_key_and_leaves_number_test() {
fn consecutive_key_and_number_of_leaves_test() {
let root: u256 = 0xb855b42d6c30f5b087e05266783fbd6e394f7b926013ccaa67700a8b0c5a596f;
let side_nodes: Array<u256> = array![];
let key: u256 = 6;
let num_leaves: u256 = 7;
let key: u32 = 6;
let num_leaves: u32 = 7;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x01_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand All @@ -300,8 +300,8 @@ fn key_not_in_tree_test() {
0x78850a5ab36238b076dd99fd258c70d523168704247988a94caa8c9ccd056b8d,
0x4301a067262bbb18b4919742326f6f6d706099f9c0e8b0f2db7b88f204b2cf09
];
let key: u256 = 9;
let num_leaves: u256 = 8;
let key: u32 = 9;
let num_leaves: u32 = 8;
let proof: BinaryMerkleProof = BinaryMerkleProof { side_nodes, key, num_leaves };
let data = BytesTrait::new_empty().encode_packed(0x01_u8);
let (is_valid, error_code) = merkle_tree::verify(root, @proof, @data);
Expand Down
7 changes: 0 additions & 7 deletions src/tree/namespace/hasher.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,3 @@ fn node_digest(left: NamespaceNode, right: NamespaceNode) -> NamespaceNode {

return NamespaceNode { min: min, max: max, digest: bytes.sha256() };
}

fn append_bytes28(ref self: Bytes, value: bytes31) {
let mut value_u256: u256 = value.into();
value_u256 = U256BitShift::shl(value_u256, 32);
let mut bytes28Bytes: Bytes = BytesTrait::new(28, array![value_u256.high, value_u256.low]);
self.concat(@bytes28Bytes);
}
Loading

0 comments on commit ea5ba8a

Please sign in to comment.