Skip to content

Commit

Permalink
fix: fixing a bug that would use 256 siblings instead of 254 (#34)
Browse files Browse the repository at this point in the history
* fix: fixing a bug that would use 256 siblings instead of 254

* bumping noirup in github actions

* bumping noirup in github actions

* constraining bignum to limbs of size u128
  • Loading branch information
signorecello authored Mar 11, 2025
1 parent ce5e584 commit 961eaf6
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 118 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
bun-version: latest
- uses: noir-lang/noirup@v0.1.3
with:
toolchain: 1.0.0-beta.1
toolchain: 1.0.0-beta.3
- run: bun i
- run: bun fmt

Expand All @@ -44,5 +44,5 @@ jobs:
- uses: actions/checkout@v4
- uses: noir-lang/noirup@v0.1.3
with:
toolchain: 1.0.0-beta.1
toolchain: 1.0.0-beta.3
- run: nargo test
2 changes: 1 addition & 1 deletion packages/ecdh/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ type = "lib"
authors = ["YashBit", "signorecello"]

[dependencies]
ec = { tag = "master", git = "https://github.com/noir-lang/ec" }
ec = { tag = "v0.1.2", git = "https://github.com/noir-lang/ec" }
6 changes: 3 additions & 3 deletions packages/merkle-trees/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ fn main(entry: Field, paths: [Field; 0]) {

## Sparse Merkle Tree

The Sparse Merkle Tree introduces some overhead but it's quite convenient, since the index of a leaf is determined by its hash. This makes it very useful to prove that a leaf is _not_ on the tree (since it cannot be found at its index). For this reason, it has a predefined depth of 256 accounting for 32-byte leaves.
The Sparse Merkle Tree introduces some overhead but it's quite convenient, since the index of a leaf is determined by its hash. This makes it very useful to prove that a leaf is _not_ on the tree (since it cannot be found at its index). For this reason, it has a predefined depth of 254 accounting for 32-byte leaves.

Similarly to the Merkle Tree, you need to provide a hasher, but also a leaf hasher. This is because the leaves are hashed with a default value to mark that they're leaves and not nodes.

Expand All @@ -77,11 +77,11 @@ fn leaf_hasher(leaves: [Field; 3]) -> Field {
hash(leaves, 3)
}

fn main(entry: (Field, Field), index: Field, siblings: [Field; 256]) {
fn main(entry: (Field, Field), index: Field, siblings: [Field; 254]) {
let mut tree2 = SparseMerkleTree::new(leaf_hasher, hasher);

// proving non-membership at index
tree2.non_membership(entry, entry, index, [0; 256]);
tree2.non_membership(entry, entry, index, [0; 254]);

// proving that it was added
tree2.add(entry, index, siblings);
Expand Down
2 changes: 1 addition & 1 deletion packages/merkle-trees/src/sparse_merkle.nr
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl<T> NonMembershipProver<T, (T, T)> for SparseMerkleTree<T>
where
T: Eq + Default,
{
fn non_membership(self, matching_entry: (T, T), index: Field, siblings: [T; 256]) {
fn non_membership<let N: u32>(self, matching_entry: (T, T), index: Field, siblings: [T; N]) {
if (self.root != T::default()) {
// non-membership proof: the root is calculated based on the matching_entry, the siblings
// and the path that is determined by the key of entry. This makes sure that matching_entry is in fact
Expand Down
45 changes: 18 additions & 27 deletions packages/merkle-trees/src/types.nr
Original file line number Diff line number Diff line change
@@ -1,50 +1,47 @@
use super::merkle::MerkleTree;
use super::sparse_merkle::SparseMerkleTree;

pub trait Calculator<T, K> {
fn calculate_root<let N: u32>(self, entry: K, indexes: Field, hash_path: [T; N]) -> T;
fn calculate_two_roots<let N: u32>(self, entry: K, indexes: Field, hash_path: [T; N]) -> (T, T);
}

pub trait SMT_Creator<T> {
pub fn default(root: T, leaf_hasher: fn([T; 3]) -> T, hasher: fn([T; 2]) -> T) -> Self {}
fn default(
root: T,
leaf_hasher: fn([T; 3]) -> T,
hasher: fn([T; 2]) -> T,
) -> SparseMerkleTree<T>;

/**
* Imports an existing Sparse Merkle Tree (SparseMerkleTree) instance.
* @param hasher The hash function that is used to hash the nodes of the tree
* @param root The root of the tree
*/
pub fn from(root: T, leaf_hasher: fn([T; 3]) -> T, hasher: fn([T; 2]) -> T) -> Self {
Self::default(root, leaf_hasher, hasher)
}
fn from(root: T, leaf_hasher: fn([T; 3]) -> T, hasher: fn([T; 2]) -> T) -> SparseMerkleTree<T>;

/**
* Creates a new Sparse Merkle Tree (SparseMerkleTree) instance.
* @param hasher The hash function that is used to hash the nodes of the tree
*/
pub fn new(leaf_hasher: fn([T; 3]) -> T, hasher: fn([T; 2]) -> T) -> Self {
Self::from(0, leaf_hasher, hasher)
}
fn new(leaf_hasher: fn([T; 3]) -> T, hasher: fn([T; 2]) -> T) -> SparseMerkleTree<T>;
}

pub trait MT_Creator<T> {
pub fn default(root: T, hasher: fn([T; 2]) -> T) -> Self {
Self { root, hasher }
}
fn default(root: T, hasher: fn([T; 2]) -> T) -> MerkleTree<T>;

/**
* Imports an existing Sparse Merkle Tree (SparseMerkleTree) instance.
* @param hasher The hash function that is used to hash the nodes of the tree
* @param root The root of the tree
*/
pub fn from(root: T, hasher: fn([T; 2]) -> T) -> Self {
Self::default(root, hasher)
}
fn from(root: T, hasher: fn([T; 2]) -> T) -> MerkleTree<T>;

/**
* Creates a new Sparse Merkle Tree (SparseMerkleTree) instance.
* @param hasher The hash function that is used to hash the nodes of the tree
*/
pub fn new(hasher: fn([T; 2]) -> T) -> Self {
Self::from(T::default(), hasher)
}
fn new(hasher: fn([T; 2]) -> T) -> MerkleTree<T>;
}

pub trait MembershipProver<T, K> {
Expand All @@ -53,7 +50,7 @@ pub trait MembershipProver<T, K> {
* @param leaf The leaf to prove
* @param path The hash path and indices
*/
pub fn membership<let N: u32>(self, entry: K, indexes: Field, hash_path: [T; N]);
fn membership<let N: u32>(self, entry: K, indexes: Field, hash_path: [T; N]);
}

pub trait NonMembershipProver<T, K> {
Expand All @@ -65,7 +62,7 @@ pub trait NonMembershipProver<T, K> {
* @param matching_entry Contains (key, value) of a matching entry
* @param siblings Contains array of siblings the matching_entry
*/
pub fn non_membership(self, matching_entry: K, index: Field, siblings: [T; 256]);
fn non_membership<let N: u32>(self, matching_entry: K, index: Field, siblings: [T; N]);
}

pub trait Modifier<T, K> {
Expand All @@ -77,15 +74,15 @@ pub trait Modifier<T, K> {
* @param new_entry The new entry to prove addition
* @param siblings The siblings (and indices for MT proofs)
*/
pub fn add<let N: u32>(&mut self, new_entry: K, indexes: Field, hash_path: [T; N]);
fn add<let N: u32>(&mut self, new_entry: K, indexes: Field, hash_path: [T; N]);

/**
* Proves the deletion of an existing entry from a tree. Based on the siblings first does a membership proof
* of that existing entry and then calculates the new root (without the entry).
* @param entry Contains key and value of the to-be-deleted entry: (key, value)
* @param siblings The siblings (and indices for MT proofs)
*/
pub fn delete<let N: u32>(&mut self, entry: K, indexes: Field, hash_path: [T; N]);
fn delete<let N: u32>(&mut self, entry: K, indexes: Field, hash_path: [T; N]);

/**
* Proves the update of the value of an existing entry in a tree. Based on the siblings first does a membership proof
Expand All @@ -94,11 +91,5 @@ pub trait Modifier<T, K> {
* @param old_entry Contains key and value of the entry to be updated: (key, value)
* @param siblings The siblings (and indices for MT proofs)
*/
pub fn update<let N: u32>(
&mut self,
new_value: K,
old_entry: K,
index: Field,
hash_path: [T; N],
);
fn update<let N: u32>(&mut self, new_value: K, old_entry: K, index: Field, hash_path: [T; N]);
}
1 change: 0 additions & 1 deletion tests/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ authors = ["signorecello"]
bignum = { git = "https://github.com/noir-lang/noir-bignum", tag = "main" }
trees = { path = "../packages/merkle-trees" }
ecdh = { path = "../packages/ecdh" }
ec = { tag = "master", git = "https://github.com/noir-lang/ec" }
3 changes: 1 addition & 2 deletions tests/src/ecdh/mod.nr
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use ec::tecurve::affine::Point;
use ecdh::bjj::BJJ;
use ecdh::{bjj::BJJ, ECDHTrait, Point};

global alice_sk: Field = 0x60c0102756aac2cf5d7277792a469bff83dfe3d3e7e50ad5a55383f3a89283e;
global bob_sk: Field = 0x86cdaad8886954a2eb20142fb98468d476a2d6c7b2c571af42cdc041b1a923c;
Expand Down
52 changes: 13 additions & 39 deletions tests/src/mt/bignum.nr
Original file line number Diff line number Diff line change
@@ -1,67 +1,41 @@
use bignum::BigNum;
use bignum::BigNumTrait;
use bignum::fields::bn254Fq::BN254_Fq_Params;
use std::hash::poseidon2::Poseidon2::hash;
use trees::merkle::MerkleTree;

type BN = BigNum<3, 254, BN254_Fq_Params>;

fn hasher(input: [BN; 2]) -> BN {
let limbs: [Field; 6] =
let limbs: [u128; 6] =
&[].append(input[0].get_limbs_slice()).append(input[1].get_limbs_slice()).as_array();
let hash_field = hash(limbs, 6);
BigNum::from_slice([hash_field, 0x00, 0x00])
let hash_field = hash(limbs.map(|limb| limb as Field), 6);
BigNum::from_slice([hash_field as u128, 0x00, 0x00])
}

#[test]
fn test_merkle_tree_add_bignum() {
let old_root = BigNum::from_slice([
0x21447efbbddb57d6fc5ad24d906388492e82c44e5160425258dd4ea995e3a06e,
0x00,
0x00,
]);
let old_root = BigNum::from_slice([0x21447efbbddb57d6fc5ad24d90638849, 0x00, 0x00]);
let mut mt = MerkleTree::from(old_root, hasher);

let leaf = BigNum::from_slice([
0x2bc00d90b885b09d12764e764410f7f693f514f7f3ca14d916741ff3968b3079,
0x00,
0x00,
]);
let paths = [BigNum::from_slice([
0x21447efbbddb57d6fc5ad24d906388492e82c44e5160425258dd4ea995e3a06e,
0x00,
0x00,
])];
let leaf = BigNum::from_slice([0x2bc00d90b885b09d12764e764410f7f6, 0x00, 0x00]);
let paths = [BigNum::from_slice([0x21447efbbddb57d6fc5ad24d90638849, 0x00, 0x00])];

mt.add(leaf, 0x01, paths);
}

#[test]
fn test_merkle_tree_add_really_bignum() {
let old_root = BigNum::from_slice([
0x2494b80a540ec0a0124a9dba7d5922e3250507677700e9eb680e30a279a72742,
0x00,
0x00,
]);
let old_root = BigNum::from_slice([0x2494b80a540ec0a0124a9dba7d5922e, 0x00, 0x00]);
let mut mt = MerkleTree::from(old_root, hasher);

let leaf = BN::from_slice([
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000,
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000,
0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000,
0x30644e72e131a029b85045b68181585,
0x30644e72e131a029b85045b68181585,
0x30644e72e131a029b85045b68181585,
]);

let paths = [BigNum::from_slice([
0x2494b80a540ec0a0124a9dba7d5922e3250507677700e9eb680e30a279a72742,
0x00,
0x00,
])];
let paths = [BigNum::from_slice([0x2494b80a540ec0a0124a9dba7d5922e, 0x00, 0x00])];
mt.add(leaf, 0x01, paths);
assert(
mt.root
== BN::from_slice([
0x1a9a6cfaea6bfb6f8dec45c5e333cf568d1f74a32acaca391e510a690b3767f9,
0x00,
0x00,
]),
);
assert(mt.root == BN::from_slice([198795359253477292896825724889155436891, 0x00, 0x00]));
}
16 changes: 8 additions & 8 deletions tests/src/smt/bignum.nr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type BN = BigNum<3, 254, BN254_Fq_Params>;
fn hasher<let N: u32>(input: [BN; N]) -> BN {
let mut limbs: [Field] = &[];
for i in 0..N {
limbs = limbs.append(input[i].get_limbs_slice());
limbs = limbs.append(input[i].get_limbs_slice().map(|limb| limb as Field));
}
let limbs_arr: [Field; 3 * N] = limbs.as_array();
let hash_field: [u8; 32] = hash(limbs_arr, 3 * N).to_be_bytes();
Expand All @@ -25,7 +25,7 @@ fn test_sparse_merkle_tree_add_bignum() {
0x412fba0629bcca2a2295b619e5c5c6,
0x03fa,
]);
let siblings: [BN; 256] = [BN::new(); 256];
let siblings: [BN; 254] = [BN::new(); 254];
smt.add((key, value), 0x01, siblings);
assert(
smt.root
Expand Down Expand Up @@ -53,8 +53,8 @@ fn test_sparse_merkle_tree_add_really_bignum() {
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
]);

let mut siblings: [BN; 256] = [BN::default(); 256];
siblings[255] = BN::from_slice([
let mut siblings: [BN; 254] = [BN::default(); 254];
siblings[253] = BN::from_slice([
0x1be857787743ed2a6e1243c3c4234c,
0x282e99f6ba97ce4a5e6c6dcc1987b3,
0x3ed4,
Expand Down Expand Up @@ -88,8 +88,8 @@ fn test_sparse_merkle_tree_non_membership_bignum() {
]);

let entry = (key, value);
let mut siblings: [BN; 256] = [BN::new(); 256];
siblings[255] = BN::from_slice([
let mut siblings: [BN; 254] = [BN::new(); 254];
siblings[253] = BN::from_slice([
0x1be857787743ed2a6e1243c3c4234c,
0x282e99f6ba97ce4a5e6c6dcc1987b3,
0x3ed4,
Expand All @@ -115,8 +115,8 @@ fn test_sparse_merkle_tree_non_membership_bignum() {
// let value = 0x04;
// let entry = (key, value);
// let matching_entry = (0x02, 0x02);
// let mut siblings: [Field; 256] = [0; 256];
// siblings[255] = 0x2caff4d2bbd06504be02b53bf953596476bec9448d5a365c05daf1f39812f42;
// let mut siblings: [Field; 254] = [0; 254];
// siblings[253] = 0x2caff4d2bbd06504be02b53bf953596476bec9448d5a365c05daf1f39812f42;

// smt.non_membership(entry, matching_entry, entry.0, siblings);
// }
34 changes: 17 additions & 17 deletions tests/src/smt/pedersen.nr
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ fn test_verify_membership_proof() {
let key = 0x01;
let value = 0x01;
let entry = (key, value);
let mut siblings: [Field; 256] = [0; 256];
siblings[254] = 0x1a68908828c1c04d18fffa09d2357ac40e717b27a3dbf3f793cdb3fe27d6d17b;
siblings[255] = 0x206456a6a1f0ee74ce95061dfbbc35ddc4ac3644988b324b5fe50e77215f1702;
let mut siblings: [Field; 254] = [0; 254];
siblings[252] = 0x1a68908828c1c04d18fffa09d2357ac40e717b27a3dbf3f793cdb3fe27d6d17b;
siblings[253] = 0x206456a6a1f0ee74ce95061dfbbc35ddc4ac3644988b324b5fe50e77215f1702;

smt.membership(entry, entry.0, siblings);
}
Expand All @@ -25,8 +25,8 @@ fn test_verify_non_membership_proof() {
let value = 0x04;
let entry = (key, value);
let matching_entry = (0x02, 0x02);
let mut siblings: [Field; 256] = [0; 256];
siblings[255] = 0x1891383341c9ba47346ab2cf7dfcf6ba42491d17f3fa692a5c1029732029aa53;
let mut siblings: [Field; 254] = [0; 254];
siblings[253] = 0x1891383341c9ba47346ab2cf7dfcf6ba42491d17f3fa692a5c1029732029aa53;

smt.non_membership(matching_entry, entry.0, siblings);
}
Expand All @@ -38,7 +38,7 @@ fn test_add_first_element() {
let key = 0x01;
let value = 0x01;
let entry = (key, value);
let siblings: [Field; 256] = [0; 256];
let siblings: [Field; 254] = [0; 254];

smt.add(entry, entry.0, siblings);
assert(smt.root == 0xe51bb5b5db9cc2c7dfd9c38ed5db39f784973f7235da39923a78793b28fe13a);
Expand All @@ -52,8 +52,8 @@ fn test_add_element_to_one_element_tree() {
let key = 0x02;
let value = 0x02;
let entry = (key, value);
let mut siblings: [Field; 256] = [0; 256];
siblings[255] = 0xe51bb5b5db9cc2c7dfd9c38ed5db39f784973f7235da39923a78793b28fe13a;
let mut siblings: [Field; 254] = [0; 254];
siblings[253] = 0xe51bb5b5db9cc2c7dfd9c38ed5db39f784973f7235da39923a78793b28fe13a;

smt.add(entry, entry.0, siblings);
assert(smt.root == 0x2d395dd3307368077b47a4841cc7cf2bf37281e2de15be3ed50a4d96fda04072);
Expand All @@ -67,9 +67,9 @@ fn test_add_element_to_existing_tree() {
let key = 0x03;
let value = 0x03;
let entry = (key, value);
let mut siblings: [Field; 256] = [0; 256];
siblings[254] = 0xe51bb5b5db9cc2c7dfd9c38ed5db39f784973f7235da39923a78793b28fe13a;
siblings[255] = 0x206456a6a1f0ee74ce95061dfbbc35ddc4ac3644988b324b5fe50e77215f1702;
let mut siblings: [Field; 254] = [0; 254];
siblings[252] = 0xe51bb5b5db9cc2c7dfd9c38ed5db39f784973f7235da39923a78793b28fe13a;
siblings[253] = 0x206456a6a1f0ee74ce95061dfbbc35ddc4ac3644988b324b5fe50e77215f1702;
let big_tree_root = 0x7ca084dd359e77ce4a7a683ccd717c45ecee547a73e73fd1a1cb62ec2a30961;

smt.add(entry, entry.0, siblings);
Expand All @@ -84,9 +84,9 @@ fn test_delete() {
let key = 0x03;
let value = 0x03;
let entry = (key, value);
let mut siblings: [Field; 256] = [0; 256];
siblings[254] = 0xe51bb5b5db9cc2c7dfd9c38ed5db39f784973f7235da39923a78793b28fe13a;
siblings[255] = 0x206456a6a1f0ee74ce95061dfbbc35ddc4ac3644988b324b5fe50e77215f1702;
let mut siblings: [Field; 254] = [0; 254];
siblings[252] = 0xe51bb5b5db9cc2c7dfd9c38ed5db39f784973f7235da39923a78793b28fe13a;
siblings[253] = 0x206456a6a1f0ee74ce95061dfbbc35ddc4ac3644988b324b5fe50e77215f1702;
let small_tree_root = 0x2d395dd3307368077b47a4841cc7cf2bf37281e2de15be3ed50a4d96fda04072;

smt.delete(entry, entry.0, siblings);
Expand All @@ -103,9 +103,9 @@ fn test_update() {
let new_value = 0x04;
let old_entry = (key, old_value);
let new_entry = (key, new_value);
let mut siblings: [Field; 256] = [0; 256];
siblings[254] = 0xe51bb5b5db9cc2c7dfd9c38ed5db39f784973f7235da39923a78793b28fe13a;
siblings[255] = 0x206456a6a1f0ee74ce95061dfbbc35ddc4ac3644988b324b5fe50e77215f1702;
let mut siblings: [Field; 254] = [0; 254];
siblings[252] = 0xe51bb5b5db9cc2c7dfd9c38ed5db39f784973f7235da39923a78793b28fe13a;
siblings[253] = 0x206456a6a1f0ee74ce95061dfbbc35ddc4ac3644988b324b5fe50e77215f1702;
let big_tree_root = 0x1136738f1460de1ca7bc0c64ed09046070f8e47f5bfa045013262dbce1e0ab3a;

smt.update(new_entry, old_entry, old_entry.0, siblings);
Expand Down
Loading

0 comments on commit 961eaf6

Please sign in to comment.