@voter-protocol/noir-prover 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/circuits/district_membership_14.json +1 -0
  2. package/circuits/district_membership_18.json +1 -0
  3. package/circuits/district_membership_20.json +1 -0
  4. package/circuits/district_membership_22.json +1 -0
  5. package/circuits/district_membership_24.json +1 -0
  6. package/circuits/two_tree_membership_18.json +1 -0
  7. package/circuits/two_tree_membership_20.json +1 -0
  8. package/circuits/two_tree_membership_22.json +1 -0
  9. package/circuits/two_tree_membership_24.json +1 -0
  10. package/dist/district_membership_18-Breq2tlt.js +128 -0
  11. package/dist/district_membership_18-DSj7IJGE.cjs +139 -0
  12. package/dist/district_membership_20-Bu0PWpWT.js +128 -0
  13. package/dist/district_membership_20-DKRyEvX4.cjs +139 -0
  14. package/dist/district_membership_22-DlrHPQtq.js +128 -0
  15. package/dist/district_membership_22-pal861Dz.cjs +139 -0
  16. package/dist/district_membership_24-BAJ-CEhq.cjs +139 -0
  17. package/dist/district_membership_24-CM66_Yd9.js +128 -0
  18. package/dist/index.cjs +1052 -123
  19. package/dist/index.js +1041 -124
  20. package/dist/noir-prover/src/cross-origin-isolation.d.ts +1 -0
  21. package/dist/noir-prover/src/cross-origin-isolation.d.ts.map +1 -0
  22. package/dist/noir-prover/src/fixtures.d.ts +82 -0
  23. package/dist/noir-prover/src/fixtures.d.ts.map +1 -0
  24. package/dist/noir-prover/src/hash.worker.d.ts +2 -0
  25. package/dist/noir-prover/src/hash.worker.d.ts.map +1 -0
  26. package/dist/noir-prover/src/index.d.ts +10 -2
  27. package/dist/noir-prover/src/index.d.ts.map +1 -0
  28. package/dist/noir-prover/src/profiler.d.ts +74 -0
  29. package/dist/noir-prover/src/profiler.d.ts.map +1 -0
  30. package/dist/noir-prover/src/prover-e2e.test.d.ts +1 -0
  31. package/dist/noir-prover/src/prover-e2e.test.d.ts.map +1 -0
  32. package/dist/noir-prover/src/prover-orchestrator.d.ts +104 -0
  33. package/dist/noir-prover/src/prover-orchestrator.d.ts.map +1 -0
  34. package/dist/noir-prover/src/prover.d.ts +43 -1
  35. package/dist/noir-prover/src/prover.d.ts.map +1 -0
  36. package/dist/noir-prover/src/prover.test.d.ts +1 -0
  37. package/dist/noir-prover/src/prover.test.d.ts.map +1 -0
  38. package/dist/noir-prover/src/two-tree-prover.d.ts +106 -0
  39. package/dist/noir-prover/src/two-tree-prover.d.ts.map +1 -0
  40. package/dist/noir-prover/src/two-tree-prover.test.d.ts +18 -0
  41. package/dist/noir-prover/src/two-tree-prover.test.d.ts.map +1 -0
  42. package/dist/noir-prover/src/types.d.ts +289 -20
  43. package/dist/noir-prover/src/types.d.ts.map +1 -0
  44. package/dist/noir-prover/src/worker-protocol.d.ts +75 -0
  45. package/dist/noir-prover/src/worker-protocol.d.ts.map +1 -0
  46. package/dist/two_tree_membership_18-Dfr1mYE-.cjs +195 -0
  47. package/dist/two_tree_membership_18-DufFLCM8.js +184 -0
  48. package/dist/two_tree_membership_20-DhrOeOFx.js +184 -0
  49. package/dist/two_tree_membership_20-jDMJJKIC.cjs +195 -0
  50. package/dist/two_tree_membership_22-CjwYhC_e.cjs +195 -0
  51. package/dist/two_tree_membership_22-iMLJVJEK.js +184 -0
  52. package/dist/two_tree_membership_24-Br8I-xLQ.cjs +195 -0
  53. package/dist/two_tree_membership_24-Df3SNDL0.js +184 -0
  54. package/package.json +12 -8
@@ -0,0 +1 @@
1
+ {"noir_version":"1.0.0-beta.16+2d46fca7203545cbbfb31a0d0328de6c10a8db95","hash":"1459707100751381029","abi":{"parameters":[{"name":"merkle_root","type":{"kind":"field"},"visibility":"private"},{"name":"nullifier","type":{"kind":"field"},"visibility":"private"},{"name":"authority_hash","type":{"kind":"field"},"visibility":"private"},{"name":"epoch_id","type":{"kind":"field"},"visibility":"private"},{"name":"campaign_id","type":{"kind":"field"},"visibility":"private"},{"name":"leaf","type":{"kind":"field"},"visibility":"private"},{"name":"merkle_path","type":{"kind":"array","length":14,"type":{"kind":"field"}},"visibility":"private"},{"name":"leaf_index","type":{"kind":"integer","sign":"unsigned","width":32},"visibility":"private"},{"name":"user_secret","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"field"},{"kind":"field"},{"kind":"field"},{"kind":"field"},{"kind":"field"}]},"visibility":"public"},"error_types":{}},"bytecode":"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","debug_symbols":"tVfLbqNAEPwXzj5Q8+jp2V9ZrSLHIZEly7YcO9Iqyr8vTFc7yQEU2doLNYZ0QRVVEN67p+Hx8vKw3T8fXrtfv9+7x9N2t9u+POwOm/V5e9iPe98/Vp3/fDifhmHc1X05Pk4d16dhf+5+7S+73ap7W+8u7Y9ej+t9w/P6NB7tV92wfxpxJHze7oZp9bH6nO7nR5Fr4TQklStBDt8YMM9QQiVBybfMq/jlq6Zb5rOfX2u8Yb7CDagRt8zn67zO6pf5+aiR83Fe/8J86sH5FMPcvC7MK7ITaP5kQP3xFUR1gnTLHayfEezDfIRwp4dLBD8yEfFuFxev4U4bVVyDFpmbX3oUyLWJENVbGErwS0Cp/ayGhTQC4j4iLNyK+l8pcvFbIX2dIwi4Pw4L1yBXBgm45WZo76WAxu+B+jP+Wm+2p29vow6jplUX2ja2bWrbPNZq1UnblrbVtq2juFWH3gAG4/goCtFgJMC0N0+ZGlGIhajE2ghDbwCDYBAbcUgG2UAafygGaqcJ1ehiTwQxEGNjjMnAdEUTFksjjmpg2lLf+BMMgp0mRaNLiUh1ieqSmZTMpWTasmnLZlMOBqYtp8afs4HYaTJNyjQpU51QnZhNYjaJaRPTJmaTiIFpE238UhuU3k5TaFKhSYXqCtUVs6nw/pu2YtqK2aQWATVtahFQi4AyAkqTlCYp1SnVqdlUzaZq2qppq2ZTtQhU01YtAtUiUBmBSpPQ976AL4IvzCr0iZiJQiwMthIZdFgaABCZB4CWAckXHvhr4mHGAUo0vWDmEbw/gRiJlg2ETGQ6ELxDwUvk8YfnH9FsRAxEKmcDEM1KRCFSeVS2uLLGzAqSm5ncTC8DvA1ItDPRTtYB7AMS7cx8cLASyHx0ZD478vXh4WZmN9OrAe8GMu0U2slygO2A0E5JRCoXSxGkEJkjiJtZ3EwvCrwpKLSz0E5WBewKCu0sDBLrAmWQlEFSD5K6mepmem3gvYHSTqWdLA7YHFTaWRkklgeVQaoMUvUgTQ2a/gfG1KEQpsVIGaY3xtv6tF0/7gZ+rDxf9psv3y7nv0c/4l83x9NhMzxdTsP0ZmnHxnfNPw==","file_map":{"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator<let N: u32>(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash<let N: u32>(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator<let N: u32>(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Decompose the input 'bn254 scalar' into two 128 bits limbs.\n// It is called 'unsafe' because it does not assert the limbs are 128 bits\n// Assuming the limbs are 128 bits:\n// Assert the decomposition does not overflow the field size.\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n // Check that the decomposition does not overflow the field size\n let (a, b) = if xhi == crate::field::bn254::PHI {\n (xlo, crate::field::bn254::PLO)\n } else {\n (xhi, crate::field::bn254::PHI)\n };\n crate::field::bn254::assert_lt(a, b);\n\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash<H>(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl<A, B, C, D, E> Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"52":{"source":"// District membership circuit (Barretenberg / Noir)\n// Mirrors Halo2 semantics with Poseidon hashing and domain-separated nullifier.\n\nuse dep::std::hash::poseidon2_permutation;\n\n// Default depth; build pipeline rewrites this per-class (14 / 20 / 22).\nglobal DEPTH: u32 = 14;\n\nfn poseidon2_hash2(left: Field, right: Field) -> Field {\n let mut state: [Field; 4] = [left, right, 0, 0];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\nfn poseidon2_hash4(a: Field, b: Field, c: Field, d: Field) -> Field {\n let mut state: [Field; 4] = [a, b, c, d];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\nfn compute_merkle_root(leaf: Field, merkle_path: [Field; DEPTH], leaf_index: u32) -> Field {\n assert(leaf_index < (1u32 << DEPTH)); // range-constrain index\n\n let mut node = leaf;\n for i in 0..DEPTH {\n let bit: bool = ((leaf_index >> i) & 1u32) == 1u32;\n let sibling = merkle_path[i];\n node = if bit { poseidon2_hash2(sibling, node) } else { poseidon2_hash2(node, sibling) };\n }\n node\n}\n\nfn compute_nullifier(user_secret: Field, campaign_id: Field, authority_hash: Field, epoch_id: Field) -> Field {\n poseidon2_hash4(user_secret, campaign_id, authority_hash, epoch_id)\n}\n\n// Public inputs are marked `pub`; private witnesses remain secret.\nfn main(\n merkle_root: Field,\n nullifier: Field,\n authority_hash: Field,\n epoch_id: Field,\n campaign_id: Field,\n leaf: Field,\n merkle_path: [Field; DEPTH],\n leaf_index: u32,\n user_secret: Field,\n) -> pub (Field, Field, Field, Field, Field) {\n let computed_root = compute_merkle_root(leaf, merkle_path, leaf_index);\n assert(computed_root == merkle_root);\n\n let computed_nullifier = compute_nullifier(user_secret, campaign_id, authority_hash, epoch_id);\n assert(computed_nullifier == nullifier);\n\n (merkle_root, nullifier, authority_hash, epoch_id, campaign_id)\n}\n","path":"/Users/noot/Documents/voter-protocol/packages/crypto/noir/district_membership/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}}
@@ -0,0 +1 @@
1
+ {"noir_version":"1.0.0-beta.18+99bb8b5cf33d7669adbdef096b12d80f30b4c0c9","hash":"766058119090432835","abi":{"parameters":[{"name":"merkle_root","type":{"kind":"field"},"visibility":"private"},{"name":"nullifier","type":{"kind":"field"},"visibility":"private"},{"name":"authority_hash","type":{"kind":"field"},"visibility":"private"},{"name":"epoch_id","type":{"kind":"field"},"visibility":"private"},{"name":"campaign_id","type":{"kind":"field"},"visibility":"private"},{"name":"leaf","type":{"kind":"field"},"visibility":"private"},{"name":"merkle_path","type":{"kind":"array","length":18,"type":{"kind":"field"}},"visibility":"private"},{"name":"leaf_index","type":{"kind":"integer","sign":"unsigned","width":32},"visibility":"private"},{"name":"user_secret","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"field"},{"kind":"field"},{"kind":"field"},{"kind":"field"},{"kind":"field"}]},"visibility":"public"},"error_types":{}},"bytecode":"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","debug_symbols":"tVfBbts6EPwXnX3gLMnlsr/y8BA4iVMYMJzAtQs8BP33J3FnneYgo3DQC4eWvCvNaIaU3qfn3ePl+8P++PL6Y/r2z/v0eNofDvvvD4fXp+15/3qcj77/2kzx8+F82u3mQ9Nv5+eqt+1pdzxP346Xw2Ez/dweLuNPP962x4Hn7Wk+mzbT7vg849zwZX/YLbNfm4/qtF6K2huroaVdG1T51AHrHZp0Nmj1nnrTuH2zck99jetbz3fUd4QAPeOe+nqtt1X+ul6fLbM+r/O/UV8SWF+yrNXbjXpDjQZWPzqg//EdZIsG5Z4n2D8smGTdQviihrca/JGIyF9W8eY9fFFG0+BgTdfqby0Fek0i1OyeDk3iFtB6WuVww42Aho6QG4+i/9UWtcWj0NTXGgi+bocb96DXDiq452FYilDA8mdD/Tv/2j7tT592owkzp80kY8xjLGOsc6w2k46xjdHG2GdymwnJAQ5z+UwK2WFugOVoXTw1oxIb0Yh9NJTkAAdxyKOxFIfqoKO/NAfzy0j3djkRQRRiHh1zcXBe2YnlNhpnc3BuJY3+BQ7ilynZ25VCJLtCdsVFKq5ScW7VuVWXqYqDc6tl9K/VQf0ylSJVilTJTslOXSZ1mdS5qXNTl0nVwbmpjf7aB7Tkl2kUqVGkRnaN7JrL1Pj8nVtzbs1lMreAOTdzC5hbwGgBo0hGkYzsjOzMZeouU3du3bl1l6m7Bbpz626B7hbotECnSEgpJoiJxMSlQirESlRio7GNSKPD3QCASD8AlAwoMQnDXx0PFw4wovMFPQ+J/AgxE90bkEqkOyCRIYkQhf0R/kd2GZGFSOZMALJLiaxEMs/GFHfGmF5BCTFLiBlhQKQBhXIWysk4gHlAoZyVCwcjgcqlo3LtqNfFI8SsIWZEA5ENVMqplJPhANMBpZxaiGSu7iJoI9JH0BCzhZgRFERS0Chno5yMCpgVNMrZaCTGBUYjGY1kYSQLMS3EjNggcgOjnEY5GRwwOeiUs9NIDA86jdRppB5G6iFmv67G5C4RIklckhPXZEZIGCFJXJaTEhvRjSTJjSSgkQQUUyAxyTEpMancDpTYiEZ0OUUSEUQ3kkgm0kgiFFNEY9JiYjHhVpS5FzFCkmM34naUuR8xQpK5I2VuSTn2pBxilhAzQiQRIimUs1BORkgYISmUsxiRzKsbSSqINJIsGVq+a2QJkSy7+hIiWd4Cfm5P++3jYccP0JfL8em379Hzf29xJr5Y306vT7vny2m3vC2Mc/P7w/8=","file_map":{"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator<let N: u32>(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash<let N: u32>(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator<let N: u32>(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Decompose the input 'bn254 scalar' into two 128 bits limbs.\n// It is called 'unsafe' because it does not assert the limbs are 128 bits\n// Assuming the limbs are 128 bits:\n// Assert the decomposition does not overflow the field size.\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n // Check that the decomposition does not overflow the field size\n let (a, b) = if xhi == crate::field::bn254::PHI {\n (xlo, crate::field::bn254::PLO)\n } else {\n (xhi, crate::field::bn254::PHI)\n };\n crate::field::bn254::assert_lt(a, b);\n\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash<H>(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl<A, B, C, D, E> Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"52":{"source":"// District membership circuit (Barretenberg / Noir)\n// Mirrors Halo2 semantics with Poseidon hashing and domain-separated nullifier.\n\nuse dep::std::hash::poseidon2_permutation;\n\n// Default depth; build pipeline rewrites this per-class (14 / 20 / 22).\nglobal DEPTH: u32 = 18;\n\nfn poseidon2_hash2(left: Field, right: Field) -> Field {\n let mut state: [Field; 4] = [left, right, 0, 0];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\nfn poseidon2_hash4(a: Field, b: Field, c: Field, d: Field) -> Field {\n let mut state: [Field; 4] = [a, b, c, d];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\nfn compute_merkle_root(leaf: Field, merkle_path: [Field; DEPTH], leaf_index: u32) -> Field {\n assert(leaf_index < (1u32 << DEPTH)); // range-constrain index\n\n let mut node = leaf;\n for i in 0..DEPTH {\n let bit: bool = ((leaf_index >> i) & 1u32) == 1u32;\n let sibling = merkle_path[i];\n node = if bit { poseidon2_hash2(sibling, node) } else { poseidon2_hash2(node, sibling) };\n }\n node\n}\n\nfn compute_nullifier(user_secret: Field, campaign_id: Field, authority_hash: Field, epoch_id: Field) -> Field {\n poseidon2_hash4(user_secret, campaign_id, authority_hash, epoch_id)\n}\n\n// Public inputs are marked `pub`; private witnesses remain secret.\nfn main(\n merkle_root: Field,\n nullifier: Field,\n authority_hash: Field,\n epoch_id: Field,\n campaign_id: Field,\n leaf: Field,\n merkle_path: [Field; DEPTH],\n leaf_index: u32,\n user_secret: Field,\n) -> pub (Field, Field, Field, Field, Field) {\n let computed_root = compute_merkle_root(leaf, merkle_path, leaf_index);\n assert(computed_root == merkle_root);\n\n let computed_nullifier = compute_nullifier(user_secret, campaign_id, authority_hash, epoch_id);\n assert(computed_nullifier == nullifier);\n\n (merkle_root, nullifier, authority_hash, epoch_id, campaign_id)\n}\n","path":"/home/noot/voter-protocol/packages/crypto/noir/district_membership/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}}
@@ -0,0 +1 @@
1
+ {"noir_version":"1.0.0-beta.18+99bb8b5cf33d7669adbdef096b12d80f30b4c0c9","hash":"2656653086632005791","abi":{"parameters":[{"name":"merkle_root","type":{"kind":"field"},"visibility":"private"},{"name":"nullifier","type":{"kind":"field"},"visibility":"private"},{"name":"authority_hash","type":{"kind":"field"},"visibility":"private"},{"name":"epoch_id","type":{"kind":"field"},"visibility":"private"},{"name":"campaign_id","type":{"kind":"field"},"visibility":"private"},{"name":"leaf","type":{"kind":"field"},"visibility":"private"},{"name":"merkle_path","type":{"kind":"array","length":20,"type":{"kind":"field"}},"visibility":"private"},{"name":"leaf_index","type":{"kind":"integer","sign":"unsigned","width":32},"visibility":"private"},{"name":"user_secret","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"field"},{"kind":"field"},{"kind":"field"},{"kind":"field"},{"kind":"field"}]},"visibility":"public"},"error_types":{}},"bytecode":"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","debug_symbols":"tZfBbuM4EET/RWcfWE2y2ZxfWSwCJ3EGBgwn8NgDLIL595XY1c7kIGPgYC4qxg7bqqcqyX6fnnePl+8P++PL64/p2z/v0+Npfzjsvz8cXp+25/3rcX71/ddmij8fzqfdbn5p+u39edfb9rQ7nqdvx8vhsJl+bg+X8U8/3rbHoeftaX43babd8XnWeeDL/rBbVr82H7vT+lbU3rgbWtp1QJVPE7A+oUnngFbv2W8ap29W7tlf4/Ot5zv2dwSAnnHP/nrdb6v+dX1/tsz9ed3/jf0lgftLlrX9dmO/ocYAqx8T0P/4DLLFgHLPFewfEUyyHiF8keGtAX8EEfnLFG+ewxcxmoYHa7q2/9atQK9NhJrdM6FJnAJaT6sebqQR0OAIuXEp+l8dUVtcCk19bYDg63G4cQ56naCCey6GpSgFLH8O1L/zX9un/enT02jC7GkzyTjmcSzjWOdabSYdxzaONo59NreZkFzgMm+fTSG7zAOwvFqXTM2q1EY1ah8DJbnARVzyGCzFpbromC/NxfxjpPu4nKigCjWPibm4uK/sxnIbg7O5uLeSxvwCF/GPKdnHlUKlu0J3xSEVp1TcW3Vv1TFVcXFvtYz5tbqof0wlpEpIle6U7tQxqWNS96buTR2Tqot7UxvztQ9pyT+mEVIjpEZ3je6aY2q8/u6tubfmmMwjYO7NPALmETBGwAjJCMnozujOHFN3TN29dffWHVP3CHT31j0C3SPQGYFOSEgpFoiFxMJRIRVqpSq1MdhGZdDhaQBAZR4AIgNKLCLw18TDwQFGdb9g5iHRH6FmqmcDUqlMByQ6JFGiiD8i/8iOEVmodM4GIDtKZKXSeTa2uLPGzApKwCwBM8qAaAMKcRbiZB3APqAQZ+WNg5VA5a2j8t5RrzePgFkDZlQD0Q1U4lTiZDnAdkCJUwuVztVTBG1U5ggaMFvAjKIgmoJGnI04WRWwK2jE2Rgk1gXGIBmDZBEkC5gWMKM2iN7AiNOIk8UBm4NOnJ1BYnnQGaTOIPUIUg+Y/Xo3pneJEkniLTnxnswKCSskibflpNRG9SBJ8iAJGCQBYQokFjkWJRaVjwOlNqpRHadIooLqQRLJVAZJhDBFNBYtFhYLPooyn0WskOR4GvFxlPk8YoUk84mU+UjK8UzKAbMEzCiRRImkEGchTlZIWCEpxFmMSufVgyQVVAZJasCsATNKJFEiqcRZiZMVElZIlDhVqHSuHiTRSmWQRAOmBswokUSJpBFnI05WSFghacTZGCRWSBqD1BgkiyAtHVp+wclSIlm+vywlkuX7zs/tab99POz4U/vlcnz67Zf3+b+3eCd+m7+dXp92z5fTbvleNN6bvyn9Dw==","file_map":{"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator<let N: u32>(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash<let N: u32>(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator<let N: u32>(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Decompose the input 'bn254 scalar' into two 128 bits limbs.\n// It is called 'unsafe' because it does not assert the limbs are 128 bits\n// Assuming the limbs are 128 bits:\n// Assert the decomposition does not overflow the field size.\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n // Check that the decomposition does not overflow the field size\n let (a, b) = if xhi == crate::field::bn254::PHI {\n (xlo, crate::field::bn254::PLO)\n } else {\n (xhi, crate::field::bn254::PHI)\n };\n crate::field::bn254::assert_lt(a, b);\n\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash<H>(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl<A, B, C, D, E> Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"52":{"source":"// District membership circuit (Barretenberg / Noir)\n// Mirrors Halo2 semantics with Poseidon hashing and domain-separated nullifier.\n\nuse dep::std::hash::poseidon2_permutation;\n\n// Default depth; build pipeline rewrites this per-class (14 / 20 / 22).\nglobal DEPTH: u32 = 20;\n\nfn poseidon2_hash2(left: Field, right: Field) -> Field {\n let mut state: [Field; 4] = [left, right, 0, 0];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\nfn poseidon2_hash4(a: Field, b: Field, c: Field, d: Field) -> Field {\n let mut state: [Field; 4] = [a, b, c, d];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\nfn compute_merkle_root(leaf: Field, merkle_path: [Field; DEPTH], leaf_index: u32) -> Field {\n assert(leaf_index < (1u32 << DEPTH)); // range-constrain index\n\n let mut node = leaf;\n for i in 0..DEPTH {\n let bit: bool = ((leaf_index >> i) & 1u32) == 1u32;\n let sibling = merkle_path[i];\n node = if bit { poseidon2_hash2(sibling, node) } else { poseidon2_hash2(node, sibling) };\n }\n node\n}\n\nfn compute_nullifier(user_secret: Field, campaign_id: Field, authority_hash: Field, epoch_id: Field) -> Field {\n poseidon2_hash4(user_secret, campaign_id, authority_hash, epoch_id)\n}\n\n// Public inputs are marked `pub`; private witnesses remain secret.\nfn main(\n merkle_root: Field,\n nullifier: Field,\n authority_hash: Field,\n epoch_id: Field,\n campaign_id: Field,\n leaf: Field,\n merkle_path: [Field; DEPTH],\n leaf_index: u32,\n user_secret: Field,\n) -> pub (Field, Field, Field, Field, Field) {\n let computed_root = compute_merkle_root(leaf, merkle_path, leaf_index);\n assert(computed_root == merkle_root);\n\n let computed_nullifier = compute_nullifier(user_secret, campaign_id, authority_hash, epoch_id);\n assert(computed_nullifier == nullifier);\n\n (merkle_root, nullifier, authority_hash, epoch_id, campaign_id)\n}\n","path":"/home/noot/voter-protocol/packages/crypto/noir/district_membership/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}}
@@ -0,0 +1 @@
1
+ {"noir_version":"1.0.0-beta.18+99bb8b5cf33d7669adbdef096b12d80f30b4c0c9","hash":"13799438578992426126","abi":{"parameters":[{"name":"merkle_root","type":{"kind":"field"},"visibility":"private"},{"name":"nullifier","type":{"kind":"field"},"visibility":"private"},{"name":"authority_hash","type":{"kind":"field"},"visibility":"private"},{"name":"epoch_id","type":{"kind":"field"},"visibility":"private"},{"name":"campaign_id","type":{"kind":"field"},"visibility":"private"},{"name":"leaf","type":{"kind":"field"},"visibility":"private"},{"name":"merkle_path","type":{"kind":"array","length":22,"type":{"kind":"field"}},"visibility":"private"},{"name":"leaf_index","type":{"kind":"integer","sign":"unsigned","width":32},"visibility":"private"},{"name":"user_secret","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"field"},{"kind":"field"},{"kind":"field"},{"kind":"field"},{"kind":"field"}]},"visibility":"public"},"error_types":{}},"bytecode":"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","debug_symbols":"tZjNbhpLEIXfZdYsuqr/qvMqV1cWtnGEhLBFINKVlXe/w9RXOF6AIqxs5rQhXcz55pwZwvv0vHk8fX/Y7l9ef0zf/nmfHg/b3W77/WH3+rQ+bl/386vvv1ZT/PlwPGw280vTb+/Pu97Wh83+OH3bn3a71fRzvTst/+jH23q/6HF9mN9Nq2mzf551Hviy3W3Oq1+rj93p+lapo7NbWumXAVU/TZDrE7oOBvR6z35rcfpm5Z79NT7fRr5j/5AAMLLcs79e9ttV/+36/myZ/fm6/xv7SxL2l6zX9tuN/SY1Blj9mCDjj88gWwwo91zB8RHBpNcjJF9keGvAH0GU/GWKN8/hixithQfr7dr+W7eCdmmiNLN7JnSNU5A+0lUPN9Io0oKj6I1LMf7qiNrjUrQ0rg1Q+XocbpxDu0xoKvdcDEtRCrH8OVD/zn+tn7aHT0+jSWZPq0mXY16OZTnWuVarqS3HvhxtOY7Z3GqS5CIu8/bZlGSXeYCcX63nTM3a0I4aOpaBmlzERV3yMliLS3Vpy3ztLuYfo8PH5YQKqmheJubi4r6yG8t9GZzNxb2VtMwv4qL+MSX7uFJQ3BXcFYdUnFJxb9W9VcdU1cW91bLMr9Wl+cdUIFUgVdw13DXH1BxTc2/NvTXH1JqLe2u2zG9jkZ78YzqQOpA67jruumPqXH/31t1bd0zmETD3Zh4B8wgYETAgGZAMd4Y7c0zDMQ33NtzbcEzDIzDc2/AIDI/AIAIDSJJSLCQWGgtHJamgFW1oJ9iGEnTxNIgISh5EQCZSYhGBvyReHJyIoe5XyLxo9EfRjHo2RCtKOkSjQxolivhL5F+yY5SsKM5pgGRHKbmhOM9Giwc1JitSAmYJmFEGiTZIAWcBJ3UQ+iAFnJUbB5WQyq2jcu+ol5tHwKwBM6oh0Q2p4GzgpBxCO6SBsxUU581TJK2j5EhawOwBM4oi0RTp4OzgpCpCV6SDsxMk6iJGkIwgWQTJAqYFzKiNRG/EwGngpDhCc2SAcxAkyiODIA2CNCJII2COy90Y7xol0sQtOXFPpkJKhTRxW04N7agHSZMHSYUgqQBTRWORY1FiUXkcNLSjhjpO1YQK6kFSzShBUgWmaotFj4XFgkdR5llEhTTH04jHUeZ5RIU080TKPJJyPJNywCwBM0qkUSIt4CzgpEJKhbSAsxiK8+pB0iooQdIaMGvAjBJplEgrOCs4qZBSIW3gbIrivHmQtFWUIGkLmC1gRok0SqQdnB2cVEipkHZwdoJEhbQTpE6QLIJkAdMCZpRIo0Rq4DRwUiGlQmrgHASJCukgSIMgjQjSCJgjYEaJNEqkw3HmlFBBFXWcORW0oh6knDpKkPK5Q+f/q+ZzifT8He1cIj1/s/u5PmzXj7sNPyq8nPZPv/3GcPzvLd6JXyHeDq9Pm+fTYXP+Bri8N38n/B8=","file_map":{"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator<let N: u32>(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash<let N: u32>(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator<let N: u32>(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Decompose the input 'bn254 scalar' into two 128 bits limbs.\n// It is called 'unsafe' because it does not assert the limbs are 128 bits\n// Assuming the limbs are 128 bits:\n// Assert the decomposition does not overflow the field size.\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n // Check that the decomposition does not overflow the field size\n let (a, b) = if xhi == crate::field::bn254::PHI {\n (xlo, crate::field::bn254::PLO)\n } else {\n (xhi, crate::field::bn254::PHI)\n };\n crate::field::bn254::assert_lt(a, b);\n\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash<H>(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl<A, B, C, D, E> Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"52":{"source":"// District membership circuit (Barretenberg / Noir)\n// Mirrors Halo2 semantics with Poseidon hashing and domain-separated nullifier.\n\nuse dep::std::hash::poseidon2_permutation;\n\n// Default depth; build pipeline rewrites this per-class (14 / 20 / 22).\nglobal DEPTH: u32 = 22;\n\nfn poseidon2_hash2(left: Field, right: Field) -> Field {\n let mut state: [Field; 4] = [left, right, 0, 0];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\nfn poseidon2_hash4(a: Field, b: Field, c: Field, d: Field) -> Field {\n let mut state: [Field; 4] = [a, b, c, d];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\nfn compute_merkle_root(leaf: Field, merkle_path: [Field; DEPTH], leaf_index: u32) -> Field {\n assert(leaf_index < (1u32 << DEPTH)); // range-constrain index\n\n let mut node = leaf;\n for i in 0..DEPTH {\n let bit: bool = ((leaf_index >> i) & 1u32) == 1u32;\n let sibling = merkle_path[i];\n node = if bit { poseidon2_hash2(sibling, node) } else { poseidon2_hash2(node, sibling) };\n }\n node\n}\n\nfn compute_nullifier(user_secret: Field, campaign_id: Field, authority_hash: Field, epoch_id: Field) -> Field {\n poseidon2_hash4(user_secret, campaign_id, authority_hash, epoch_id)\n}\n\n// Public inputs are marked `pub`; private witnesses remain secret.\nfn main(\n merkle_root: Field,\n nullifier: Field,\n authority_hash: Field,\n epoch_id: Field,\n campaign_id: Field,\n leaf: Field,\n merkle_path: [Field; DEPTH],\n leaf_index: u32,\n user_secret: Field,\n) -> pub (Field, Field, Field, Field, Field) {\n let computed_root = compute_merkle_root(leaf, merkle_path, leaf_index);\n assert(computed_root == merkle_root);\n\n let computed_nullifier = compute_nullifier(user_secret, campaign_id, authority_hash, epoch_id);\n assert(computed_nullifier == nullifier);\n\n (merkle_root, nullifier, authority_hash, epoch_id, campaign_id)\n}\n","path":"/home/noot/voter-protocol/packages/crypto/noir/district_membership/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}}
@@ -0,0 +1 @@
1
+ {"noir_version":"1.0.0-beta.18+99bb8b5cf33d7669adbdef096b12d80f30b4c0c9","hash":"9266678664366874381","abi":{"parameters":[{"name":"merkle_root","type":{"kind":"field"},"visibility":"private"},{"name":"nullifier","type":{"kind":"field"},"visibility":"private"},{"name":"authority_hash","type":{"kind":"field"},"visibility":"private"},{"name":"epoch_id","type":{"kind":"field"},"visibility":"private"},{"name":"campaign_id","type":{"kind":"field"},"visibility":"private"},{"name":"leaf","type":{"kind":"field"},"visibility":"private"},{"name":"merkle_path","type":{"kind":"array","length":24,"type":{"kind":"field"}},"visibility":"private"},{"name":"leaf_index","type":{"kind":"integer","sign":"unsigned","width":32},"visibility":"private"},{"name":"user_secret","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"tuple","fields":[{"kind":"field"},{"kind":"field"},{"kind":"field"},{"kind":"field"},{"kind":"field"}]},"visibility":"public"},"error_types":{}},"bytecode":"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","debug_symbols":"tZjdjho5EIXfhWsuXFX+Ke+rrFYRmZAICTEjMhNpFeXdt+n6iiQXoIjR3vTxQFzd9fU5tsP3zaf9x7cvHw6nz89fN3/9/X3z8Xw4Hg9fPhyfn3avh+fT8un3H9tN/vnh9bzfLx9tfvl+mfWyO+9Pr5u/Tm/H43bzbXd8W//R15fdadXX3Xn5tmw3+9OnRZeCnw/H/WX0Y/tzdrk9VdoczJZex7VA098qyO0KQycFRntkvvd8fPf6yPyW9/dpD8yfkgCmySPz23W+3+y/355vbsy32/3fmV+LML+a3prvd+a7tCzg7WcFmX/8BOZZoD7yBudPCxa9bSF5J8N7Bf4Ioti7Kd59hndi9J49+Oi35t9bCvo1idLdH6kwNB9Bxiw3e7jjRpGeHEXvvIr5v5ZoI19FL/NWAZX32+HOM/Rrha7yyMvwkqEQt98N9c/y1+7pcP5tN9rI0tN2o+vV1mtdr22J1XbT1+tYr75e59LcdiMlREKW6UtTYiFLAbl82i6eWrSjA3V0rgW1hEiIhthaWGtIC+lrfR0hHrfRGeWsoIIqamtFqyHRl0VjNtbC5iHRWy1r/SohGrepFuVqRemu0l0NSDUo1eitRW8tMDUNid5aXeu3FtLjNg1IDUiN7jrd9cDUA1OP3nr01gNT7yHRW/e1fp+rjBK3GUAaQBp0N+huBKbB+4/eRvQ2ApOHBTx687CAhwUcCziQHEhOd053HphmYJrR24zeZmCaYYEZvc2wwAwLTCwwgSSl5EByoDkIVFIq2tCODoztKEaXcIOIoPhBBGQiNQdp+KvjJcCJOBr9Cp4Xzfwoamh4Q7ShuEM0M6QZorS/pP/FAqOYonROAsQCpVhH6dycFE9ijFekJsyaMDMMkmmQCs4KTuIg5EEqOBsLB5GQxtLRWDvadfFImC1hZjQksyENnB2chENIh3Rw9orSeQ8XSR8oPpKeMEfCzKBIJkUGOAc4iYqQFRngHBiJuIhjJMdInkbyhOkJM2MjmRtxcDo4CY6QHJngnBiJ8MjESBMjzTTSTJjzuhrTu2aItLAkF9ZkIqRESAvLcunoQMNIWsJIKhhJBZgqmgPLQc1BYzvo6EAdDZyqBRU0jKRqKEZSBaZqz8HIgeeArcjYi4iQWu5GbEfGfkSE1NiRjC3Jck+yhFkTZoZIM0RawVnBSYSUCGkFZ3WUzlsYSZugGElbwmwJM0OkGSJt4GzgJEJKhLSDsytK5z2MpL2hGEl7wuwJM0OkGSId4BzgJEJKhHSAc2AkIqQDIw2M5GkkT5ieMDNEmiFSB6eDkwgpEVIH58RIREgnRpoYaaaRZsKcCTNDpBkinYHTSkEFVTRwWqloQ8NIVgaKkazk6Uaux5s832SITDjhCEccImREyIRTjnDMIUKmYSRTQTGSqeURquag5aDnIHCaOkrnRMgscJopSucWRjJrKEayS4Yu/yu3S4j0chq9hEgvZ9hvu/Nh9/G45+eTz2+np19+TXn99yW/yd9bXs7PT/tPb+f95ay7frecfv8D","file_map":{"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator<let N: u32>(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash<let N: u32>(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator<let N: u32>(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Decompose the input 'bn254 scalar' into two 128 bits limbs.\n// It is called 'unsafe' because it does not assert the limbs are 128 bits\n// Assuming the limbs are 128 bits:\n// Assert the decomposition does not overflow the field size.\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n // Check that the decomposition does not overflow the field size\n let (a, b) = if xhi == crate::field::bn254::PHI {\n (xlo, crate::field::bn254::PLO)\n } else {\n (xhi, crate::field::bn254::PHI)\n };\n crate::field::bn254::assert_lt(a, b);\n\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash<H>(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl<A, B, C, D, E> Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"52":{"source":"// District membership circuit (Barretenberg / Noir)\n// Mirrors Halo2 semantics with Poseidon hashing and domain-separated nullifier.\n\nuse dep::std::hash::poseidon2_permutation;\n\n// Default depth; build pipeline rewrites this per-class (14 / 20 / 22).\nglobal DEPTH: u32 = 24;\n\nfn poseidon2_hash2(left: Field, right: Field) -> Field {\n let mut state: [Field; 4] = [left, right, 0, 0];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\nfn poseidon2_hash4(a: Field, b: Field, c: Field, d: Field) -> Field {\n let mut state: [Field; 4] = [a, b, c, d];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\nfn compute_merkle_root(leaf: Field, merkle_path: [Field; DEPTH], leaf_index: u32) -> Field {\n assert(leaf_index < (1u32 << DEPTH)); // range-constrain index\n\n let mut node = leaf;\n for i in 0..DEPTH {\n let bit: bool = ((leaf_index >> i) & 1u32) == 1u32;\n let sibling = merkle_path[i];\n node = if bit { poseidon2_hash2(sibling, node) } else { poseidon2_hash2(node, sibling) };\n }\n node\n}\n\nfn compute_nullifier(user_secret: Field, campaign_id: Field, authority_hash: Field, epoch_id: Field) -> Field {\n poseidon2_hash4(user_secret, campaign_id, authority_hash, epoch_id)\n}\n\n// Public inputs are marked `pub`; private witnesses remain secret.\nfn main(\n merkle_root: Field,\n nullifier: Field,\n authority_hash: Field,\n epoch_id: Field,\n campaign_id: Field,\n leaf: Field,\n merkle_path: [Field; DEPTH],\n leaf_index: u32,\n user_secret: Field,\n) -> pub (Field, Field, Field, Field, Field) {\n let computed_root = compute_merkle_root(leaf, merkle_path, leaf_index);\n assert(computed_root == merkle_root);\n\n let computed_nullifier = compute_nullifier(user_secret, campaign_id, authority_hash, epoch_id);\n assert(computed_nullifier == nullifier);\n\n (merkle_root, nullifier, authority_hash, epoch_id, campaign_id)\n}\n","path":"/home/noot/voter-protocol/packages/crypto/noir/district_membership/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}}
@@ -0,0 +1 @@
1
+ {"noir_version":"1.0.0-beta.16+2d46fca7203545cbbfb31a0d0328de6c10a8db95","hash":"12911964840868525972","abi":{"parameters":[{"name":"user_root","type":{"kind":"field"},"visibility":"public"},{"name":"cell_map_root","type":{"kind":"field"},"visibility":"public"},{"name":"districts","type":{"kind":"array","length":24,"type":{"kind":"field"}},"visibility":"public"},{"name":"nullifier","type":{"kind":"field"},"visibility":"public"},{"name":"action_domain","type":{"kind":"field"},"visibility":"public"},{"name":"authority_level","type":{"kind":"field"},"visibility":"public"},{"name":"user_secret","type":{"kind":"field"},"visibility":"private"},{"name":"cell_id","type":{"kind":"field"},"visibility":"private"},{"name":"registration_salt","type":{"kind":"field"},"visibility":"private"},{"name":"user_path","type":{"kind":"array","length":18,"type":{"kind":"field"}},"visibility":"private"},{"name":"user_index","type":{"kind":"integer","sign":"unsigned","width":32},"visibility":"private"},{"name":"cell_map_path","type":{"kind":"array","length":18,"type":{"kind":"field"}},"visibility":"private"},{"name":"cell_map_path_bits","type":{"kind":"array","length":18,"type":{"kind":"integer","sign":"unsigned","width":1}},"visibility":"private"}],"return_type":null,"error_types":{"1581818912316326543":{"error_kind":"string","string":"Nullifier verification failed"},"2343933809292327097":{"error_kind":"string","string":"Leaf index out of range"},"5254098518846542452":{"error_kind":"string","string":"Authority level below minimum (1)"},"6155364669794686959":{"error_kind":"string","string":"Authority level exceeds u8 range"},"6595073843744152109":{"error_kind":"string","string":"Authority level above maximum (5)"},"13294772739336026880":{"error_kind":"string","string":"user_secret cannot be zero"},"16755691356112141991":{"error_kind":"string","string":"Tree 2: SMT proof verification failed"},"17148460859403048861":{"error_kind":"string","string":"Tree 1: Merkle proof verification failed"}}},"bytecode":"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","debug_symbols":"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","file_map":{"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3<let N: u32>(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3<let N: u32>(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment<let N: u32>(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator<let N: u32>(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash<let N: u32>(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator<let N: u32>(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators<let N: u32, let M: u32>(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Decompose the input 'bn254 scalar' into two 128 bits limbs.\n// It is called 'unsafe' because it does not assert the limbs are 128 bits\n// Assuming the limbs are 128 bits:\n// Assert the decomposition does not overflow the field size.\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n // Check that the decomposition does not overflow the field size\n let (a, b) = if xhi == crate::field::bn254::PHI {\n (xlo, crate::field::bn254::PLO)\n } else {\n (xhi, crate::field::bn254::PHI)\n };\n crate::field::bn254::assert_lt(a, b);\n\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation<let N: u32>(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal<let N: u32>(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash<H>(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault<H>;\n\nimpl<H> BuildHasher for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl<H> Default for BuildHasherDefault<H>\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash<H>(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl<T, let N: u32> Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<T> Hash for [T]\nwhere\n T: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl<A, B> Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl<A, B, C> Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl<A, B, C, D> Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl<A, B, C, D, E> Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash<H>(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"51":{"source":"// Two-Tree Membership Circuit (Barretenberg / Noir)\n//\n// Proves that a user belongs to a geographic cell (Tree 1) that maps to a specific\n// set of 24 districts (Tree 2). This is the core circuit for the two-tree architecture\n// described in TWO-TREE-ARCHITECTURE-SPEC.md Section 4.\n//\n// ARCHITECTURE:\n// - Tree 1 (User Tree): Standard Merkle tree mapping user identity to a cell.\n// Leaf = H3(user_secret, cell_id, registration_salt)\n// - Tree 2 (Cell Map): Sparse Merkle tree mapping cells to district commitments.\n// Leaf = H2(cell_id, district_commitment)\n// where district_commitment = poseidon2_sponge_24(districts)\n//\n// SECURITY:\n// - SA-011: user_secret cannot be zero (prevents predictable nullifiers)\n// - ISSUE-006: authority_level range-checked to [1, 5]\n// - CVE-001/CVE-003: Leaves computed inside circuit from user_secret\n// - CVE-002: nullifier uses only user_secret + public action_domain\n// - BA-003: Domain separation tags prevent cross-arity hash collisions\n// - BA-007: Authority level cast through u64 to prevent truncation attacks\n\nuse dep::std::hash::poseidon2_permutation;\n\n// Import sponge module for district commitment\nmod sponge;\nuse sponge::poseidon2_sponge_24;\n\n// ===============================================================================\n// CONSTANTS\n// ===============================================================================\n\n// Default tree depth. Build pipeline rewrites this per variant (18 / 20 / 22 / 24).\n// Depth 20 is the default: ~1M leaves, suitable for UK constituencies, medium countries.\n// Valid depths: 18 (260K), 20 (1M), 22 (4M), 24 (16M)\nglobal TREE_DEPTH: u32 = 18;\n\n// Valid authority level bounds (inclusive)\nglobal MIN_AUTHORITY_LEVEL: Field = 1;\nglobal MAX_AUTHORITY_LEVEL: Field = 5;\n\n// BA-003: Domain separation tag for 2-input hash.\n// Prevents cross-arity collisions: poseidon2_hash2(a, b) cannot equal\n// poseidon2_hash4(a, b, 0, 0) because the third state element is 0x48324d\n// (\"H2M\" = Hash-2 Marker) instead of 0.\n// MUST match district_membership circuit for nullifier compatibility.\nglobal DOMAIN_HASH2: Field = 0x48324d;\n\n// Domain separation tag for 3-input hash.\n// Used for user leaf computation: H3(user_secret, cell_id, registration_salt).\n// All 4 state slots are filled so the tag goes in the 4th position.\n// Value: 0x48334d = \"H3M\" (Hash-3 Marker), following the pattern:\n// DOMAIN_HASH1 = 0x48314d (\"H1M\")\n// DOMAIN_HASH2 = 0x48324d (\"H2M\")\n// DOMAIN_HASH3 = 0x48334d (\"H3M\")\n// MUST match poseidon2.ts DOMAIN_HASH3 for cross-language parity.\nglobal DOMAIN_HASH3: Field = 0x48334d;\n\n// ===============================================================================\n// HASH FUNCTIONS\n// ===============================================================================\n\n/// Domain-separated 2-input Poseidon2 hash.\n/// State layout: [a, b, DOMAIN_HASH2, 0]\n/// Used for: cell map leaf, nullifier, Merkle node hashing\nfn poseidon2_hash2(left: Field, right: Field) -> Field {\n let state: [Field; 4] = [left, right, DOMAIN_HASH2, 0];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\n/// Domain-separated 3-input Poseidon2 hash.\n/// State layout: [a, b, c, DOMAIN_HASH3]\n/// Used for: user leaf commitment (user_secret, cell_id, registration_salt)\nfn poseidon2_hash3(a: Field, b: Field, c: Field) -> Field {\n let state: [Field; 4] = [a, b, c, DOMAIN_HASH3];\n let out = poseidon2_permutation(state, 4);\n out[0]\n}\n\n// ===============================================================================\n// MERKLE VERIFICATION\n// ===============================================================================\n\n/// Standard Merkle path verification for Tree 1 (user identity tree).\n/// Direction bits are derived from the leaf index.\n///\n/// @param leaf - The computed leaf value\n/// @param path - Array of sibling hashes along the path\n/// @param index - The leaf's position in the tree (determines left/right at each level)\n/// @returns The computed Merkle root\nfn compute_merkle_root(leaf: Field, path: [Field; TREE_DEPTH], index: u32) -> Field {\n // Range-constrain index to valid leaf positions\n assert(index < (1u32 << TREE_DEPTH), \"Leaf index out of range\");\n\n let mut node = leaf;\n for i in 0..TREE_DEPTH {\n let bit: bool = ((index >> i) & 1u32) == 1u32;\n let sibling = path[i];\n node = if bit {\n poseidon2_hash2(sibling, node)\n } else {\n poseidon2_hash2(node, sibling)\n };\n }\n node\n}\n\n/// Sparse Merkle Tree path verification for Tree 2 (cell mapping tree).\n/// Direction bits are provided as witness (pre-computed from SMT position).\n///\n/// Unlike standard Merkle trees where direction is derived from a numeric index,\n/// SMTs use key-derived path bits. The path_bits are provided as private input\n/// and represent the traversal directions at each level.\n///\n/// @param leaf - The computed cell map leaf\n/// @param path - Array of sibling hashes along the SMT path\n/// @param path_bits - Direction bits at each level (0 = left, 1 = right)\n/// @returns The computed SMT root\nfn compute_smt_root(\n leaf: Field,\n path: [Field; TREE_DEPTH],\n path_bits: [u1; TREE_DEPTH],\n) -> Field {\n let mut node = leaf;\n for i in 0..TREE_DEPTH {\n let sibling = path[i];\n node = if path_bits[i] == 0 {\n poseidon2_hash2(node, sibling)\n } else {\n poseidon2_hash2(sibling, node)\n };\n }\n node\n}\n\n// ===============================================================================\n// LEAF COMPUTATION\n// ===============================================================================\n\n/// Computes the user leaf for Tree 1.\n///\n/// SECURITY (CVE-001/CVE-003): The leaf MUST be derived from user_secret to prove\n/// ownership. Without this binding, an attacker could use any valid leaf from the\n/// tree without proving they control the corresponding secret.\n///\n/// @param user_secret - The user's private key material (proves identity ownership)\n/// @param cell_id - The geographic cell the user is registered in\n/// @param registration_salt - Unique salt assigned during registration (prevents rainbow attacks)\n/// @returns The user leaf commitment\nfn compute_user_leaf(\n user_secret: Field,\n cell_id: Field,\n registration_salt: Field,\n) -> Field {\n poseidon2_hash3(user_secret, cell_id, registration_salt)\n}\n\n/// Computes the cell map leaf for Tree 2.\n///\n/// Binds a geographic cell to its full set of overlapping districts.\n///\n/// @param cell_id - The geographic cell identifier\n/// @param district_commitment - Hash of all 24 district IDs (from sponge)\n/// @returns The cell map leaf\nfn compute_cell_map_leaf(cell_id: Field, district_commitment: Field) -> Field {\n poseidon2_hash2(cell_id, district_commitment)\n}\n\n// ===============================================================================\n// NULLIFIER\n// ===============================================================================\n\n/// Computes a domain-separated nullifier to prevent double-voting.\n///\n/// SECURITY (CVE-002): The nullifier is derived from user_secret and a PUBLIC\n/// action_domain that is controlled by the verifying contract. This prevents\n/// users from manipulating private inputs to generate multiple valid proofs\n/// for the same action.\n///\n/// @param user_secret - The user's private key material\n/// @param action_domain - Contract-controlled scope (encodes epoch, campaign, authority hash)\n/// @returns Unique nullifier for this user+action combination\nfn compute_nullifier(user_secret: Field, action_domain: Field) -> Field {\n poseidon2_hash2(user_secret, action_domain)\n}\n\n// ===============================================================================\n// AUTHORITY VALIDATION\n// ===============================================================================\n\n/// Validates that authority_level is within the valid range [1, 5].\n///\n/// SECURITY (ISSUE-006): Authority levels must be bounded to prevent\n/// privilege escalation or invalid tier claims.\n///\n/// SECURITY (BA-007): Cast through u64 first to detect values >= 256 that\n/// would silently truncate when cast to u8 (e.g., 261 would become 5).\nfn validate_authority_level(authority_level: Field) {\n // BA-007 FIX: Ensure value fits in u8 before casting to prevent truncation attacks.\n // A Field value like 261 (256 + 5) would silently truncate to 5 as u8.\n assert(authority_level as u64 < 256, \"Authority level exceeds u8 range\");\n let level_u8 = authority_level as u8;\n assert(level_u8 >= MIN_AUTHORITY_LEVEL as u8, \"Authority level below minimum (1)\");\n assert(level_u8 <= MAX_AUTHORITY_LEVEL as u8, \"Authority level above maximum (5)\");\n}\n\n// ===============================================================================\n// MAIN CIRCUIT\n// ===============================================================================\n\n/// Two-tree membership circuit - proves user belongs to a geographic cell that\n/// maps to a specific set of districts.\n///\n/// PUBLIC INPUTS (verified on-chain, contract-controlled):\n/// - user_root: Tree 1 Merkle root (user identity tree)\n/// - cell_map_root: Tree 2 SMT root (cell-to-districts mapping)\n/// - districts: All 24 district IDs for this cell\n/// - nullifier: Anti-double-vote token\n/// - action_domain: Contract-controlled scope for nullifier\n/// - authority_level: User's voting tier (1-5)\n///\n/// PRIVATE INPUTS (user-provided witnesses):\n/// - user_secret: User's private key material\n/// - cell_id: The geographic cell identifier\n/// - registration_salt: Salt from registration\n/// - user_path: Merkle siblings for Tree 1\n/// - user_index: Leaf position in Tree 1\n/// - cell_map_path: SMT siblings for Tree 2\n/// - cell_map_path_bits: SMT direction bits for Tree 2\nfn main(\n // =======================================================================\n // PUBLIC INPUTS\n // =======================================================================\n user_root: pub Field,\n cell_map_root: pub Field,\n districts: pub [Field; 24],\n nullifier: pub Field,\n action_domain: pub Field,\n authority_level: pub Field,\n\n // =======================================================================\n // PRIVATE INPUTS (witnesses)\n // =======================================================================\n user_secret: Field,\n cell_id: Field,\n registration_salt: Field,\n\n // Tree 1: Standard Merkle proof\n user_path: [Field; TREE_DEPTH],\n user_index: u32,\n\n // Tree 2: SMT proof\n cell_map_path: [Field; TREE_DEPTH],\n cell_map_path_bits: [u1; TREE_DEPTH],\n) {\n // =======================================================================\n // PRE-CHECKS\n // =======================================================================\n\n // SA-011 FIX: Reject zero user_secret to prevent predictable nullifiers.\n // A zero secret makes nullifier = hash(0, action_domain), which is guessable.\n // The security model requires high-entropy secrets.\n assert(user_secret != 0, \"user_secret cannot be zero\");\n\n // ISSUE-006 FIX: Validate authority_level is in valid range [1, 5]\n validate_authority_level(authority_level);\n\n // =======================================================================\n // STEP 1: Verify user identity (Tree 1)\n // =======================================================================\n // Compute leaf inside circuit from user_secret (CVE-001/CVE-003 fix).\n // The user must know the secret used during registration.\n let user_leaf = compute_user_leaf(user_secret, cell_id, registration_salt);\n let computed_user_root = compute_merkle_root(user_leaf, user_path, user_index);\n assert(computed_user_root == user_root, \"Tree 1: Merkle proof verification failed\");\n\n // =======================================================================\n // STEP 2: Compute district commitment\n // =======================================================================\n // Hash all 24 district IDs into a single commitment using the sponge.\n let district_commitment = poseidon2_sponge_24(districts);\n\n // =======================================================================\n // STEP 3: Verify cell mapping (Tree 2)\n // =======================================================================\n // Prove that cell_id maps to this specific set of districts in the SMT.\n let cell_map_leaf = compute_cell_map_leaf(cell_id, district_commitment);\n let computed_map_root = compute_smt_root(\n cell_map_leaf,\n cell_map_path,\n cell_map_path_bits,\n );\n assert(computed_map_root == cell_map_root, \"Tree 2: SMT proof verification failed\");\n\n // =======================================================================\n // STEP 4: Verify nullifier\n // =======================================================================\n // Nullifier binds user identity to action scope, preventing double-voting.\n let computed_nullifier = compute_nullifier(user_secret, action_domain);\n assert(computed_nullifier == nullifier, \"Nullifier verification failed\");\n}\n\n// ===============================================================================\n// TESTS\n// ===============================================================================\n\n#[test]\nfn test_hash2_deterministic() {\n // Verify that poseidon2_hash2 produces consistent output for same inputs\n let a: Field = 42;\n let b: Field = 99;\n\n let result1 = poseidon2_hash2(a, b);\n let result2 = poseidon2_hash2(a, b);\n assert(result1 == result2, \"hash2 must be deterministic\");\n\n // Verify different inputs produce different outputs\n let result3 = poseidon2_hash2(b, a);\n assert(result1 != result3, \"hash2 must not be commutative\");\n\n // Verify non-zero output\n assert(result1 != 0, \"hash2 should produce non-zero output for non-zero inputs\");\n}\n\n#[test]\nfn test_hash3_deterministic() {\n // Verify that poseidon2_hash3 produces consistent output for same inputs\n let a: Field = 1;\n let b: Field = 2;\n let c: Field = 3;\n\n let result1 = poseidon2_hash3(a, b, c);\n let result2 = poseidon2_hash3(a, b, c);\n assert(result1 == result2, \"hash3 must be deterministic\");\n\n // Verify different inputs produce different outputs\n let result3 = poseidon2_hash3(c, b, a);\n assert(result1 != result3, \"hash3 input order must matter\");\n\n // Verify non-zero output\n assert(result1 != 0, \"hash3 should produce non-zero output for non-zero inputs\");\n}\n\n#[test]\nfn test_hash2_hash3_no_collision() {\n // Domain separation must prevent hash2(a, b) from equaling hash3(a, b, 0)\n let a: Field = 7;\n let b: Field = 13;\n\n let h2 = poseidon2_hash2(a, b);\n let h3 = poseidon2_hash3(a, b, 0);\n assert(h2 != h3, \"hash2 and hash3 must not collide due to domain separation\");\n}\n\n#[test]\nfn test_sponge_integration() {\n // Verify that the sponge module can be called from main and produces expected output.\n // Uses the same golden vector as sponge.nr's own test.\n let inputs: [Field; 24] = [\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,\n 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n ];\n\n let result = poseidon2_sponge_24(inputs);\n\n // Must match the golden vector from sponge.nr / TypeScript implementation\n let expected: Field = 13897144223796711226515669182413786178697447221339740051025074265447026549851;\n assert(result == expected, \"sponge golden vector mismatch - cross-language incompatibility\");\n}\n\n#[test]\nfn test_authority_validation() {\n // Valid authority levels: 1 through 5\n validate_authority_level(1);\n validate_authority_level(2);\n validate_authority_level(3);\n validate_authority_level(4);\n validate_authority_level(5);\n}\n\n#[test(should_fail_with = \"Authority level below minimum (1)\")]\nfn test_authority_validation_rejects_zero() {\n validate_authority_level(0);\n}\n\n#[test(should_fail_with = \"Authority level above maximum (5)\")]\nfn test_authority_validation_rejects_six() {\n validate_authority_level(6);\n}\n\n#[test(should_fail_with = \"Authority level exceeds u8 range\")]\nfn test_authority_validation_rejects_overflow() {\n // 261 = 256 + 5, would truncate to 5 as u8 (BA-007)\n validate_authority_level(261);\n}\n\n#[test]\nfn test_compute_user_leaf() {\n // Verify user leaf computation is deterministic and non-trivial\n let secret: Field = 12345;\n let cell: Field = 67890;\n let salt: Field = 11111;\n\n let leaf1 = compute_user_leaf(secret, cell, salt);\n let leaf2 = compute_user_leaf(secret, cell, salt);\n assert(leaf1 == leaf2, \"user leaf must be deterministic\");\n assert(leaf1 != 0, \"user leaf should be non-zero for non-zero inputs\");\n\n // Different salt must produce different leaf\n let leaf3 = compute_user_leaf(secret, cell, 22222);\n assert(leaf1 != leaf3, \"different salt must produce different leaf\");\n}\n\n#[test]\nfn test_compute_cell_map_leaf() {\n // Verify cell map leaf computation\n let cell_id: Field = 67890;\n let commitment: Field = 99999;\n\n let leaf1 = compute_cell_map_leaf(cell_id, commitment);\n let leaf2 = compute_cell_map_leaf(cell_id, commitment);\n assert(leaf1 == leaf2, \"cell map leaf must be deterministic\");\n\n // Different commitment must produce different leaf\n let leaf3 = compute_cell_map_leaf(cell_id, 88888);\n assert(leaf1 != leaf3, \"different commitment must produce different cell map leaf\");\n}\n\n#[test]\nfn test_nullifier_deterministic() {\n // Verify nullifier computation matches the pattern from district_membership\n let secret: Field = 42;\n let domain: Field = 100;\n\n let null1 = compute_nullifier(secret, domain);\n let null2 = compute_nullifier(secret, domain);\n assert(null1 == null2, \"nullifier must be deterministic\");\n\n // Different domain must produce different nullifier\n let null3 = compute_nullifier(secret, 200);\n assert(null1 != null3, \"different action_domain must produce different nullifier\");\n}\n","path":"/Users/noot/Documents/voter-protocol/packages/crypto/noir/two_tree_membership/src/main.nr"},"52":{"source":"// Poseidon2 Sponge Construction for 24-District Commitment\n//\n// This module implements the sponge construction for hashing 24 district IDs\n// into a single commitment. It is used by the two-tree architecture to bind\n// a user's geographic cell to their full district set.\n//\n// SECURITY:\n// - Domain separation: DOMAIN_SPONGE_24 prevents collision with other hash functions\n// - ADD to state (not overwrite): Proper sponge construction that maintains\n// cryptographic chaining between rounds\n// - Rate = 3, Capacity = 1: Standard sponge parameters for 4-element state\n//\n// SPECIFICATION REFERENCE:\n// - TWO-TREE-ARCHITECTURE-SPEC.md Section 4.3 (Sponge Construction)\n// - TWO-TREE-AGENT-REVIEW-SUMMARY.md BLOCKER-3 (Sponge Bug Fix)\n\nuse dep::std::hash::poseidon2_permutation;\n\n/// Domain separation tag for 24-district sponge.\n/// Value: 0x534f4e47455f24\n/// Breakdown:\n/// 0x53 = 'S', 0x4f = 'O', 0x4e = 'N', 0x47 = 'G', 0x45 = 'E'\n/// 0x5f = '_', 0x24 = hex for decimal 36 (represents \"24\")\n/// This prevents collision with other hash functions in the protocol.\nglobal DOMAIN_SPONGE_24: Field = 0x534f4e47455f24;\n\n/// Poseidon2 sponge for hashing 24 district IDs into a single commitment.\n///\n/// ALGORITHM:\n/// 1. Initialize state: [DOMAIN_SPONGE_24, 0, 0, 0]\n/// 2. For each chunk of 3 inputs (8 rounds total):\n/// - ADD inputs to state[1], state[2], state[3] (NOT overwrite)\n/// - Apply Poseidon2 permutation to full state\n/// 3. Return state[0] as output\n///\n/// CRITICAL SECURITY NOTE:\n/// The spec v0.1 had a bug where inputs were assigned (overwriting state).\n/// This implementation uses ADDITION, which is the correct sponge construction.\n/// Overwriting would break the cryptographic chaining and create collision vulnerabilities.\n///\n/// CORRECT (this implementation):\n/// state[1] = state[1] + inputs[i * 3]\n///\n/// BUGGY (from spec v0.1):\n/// state[1] = inputs[i * 3] // WRONG - discards previous state\n///\n/// @param inputs - Exactly 24 field elements (district IDs)\n/// @returns Single field element (district commitment)\npub fn poseidon2_sponge_24(inputs: [Field; 24]) -> Field {\n // Initialize state with domain tag in capacity position (state[0])\n let mut state: [Field; 4] = [DOMAIN_SPONGE_24, 0, 0, 0];\n\n // Absorb phase: 24 inputs / 3 rate = 8 rounds\n for i in 0..8 {\n // ADD inputs to rate elements (state[1], state[2], state[3])\n // CRITICAL: Use addition, not assignment, to maintain sponge security\n state[1] = state[1] + inputs[i * 3];\n state[2] = state[2] + inputs[i * 3 + 1];\n state[3] = state[3] + inputs[i * 3 + 2];\n\n // Apply full Poseidon2 permutation\n state = poseidon2_permutation(state, 4);\n }\n\n // Squeeze phase: return capacity element (state[0])\n state[0]\n}\n\n// ============================================================================\n// TEST CASES\n// ============================================================================\n\n#[test]\nfn test_sponge_deterministic() {\n // Test that same inputs produce same output\n let inputs: [Field; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];\n\n let result1 = poseidon2_sponge_24(inputs);\n let result2 = poseidon2_sponge_24(inputs);\n\n assert(result1 == result2);\n}\n\n#[test]\nfn test_sponge_different_inputs() {\n // Test that different inputs produce different outputs\n let inputs1: [Field; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];\n let inputs2: [Field; 24] = [24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1];\n\n let result1 = poseidon2_sponge_24(inputs1);\n let result2 = poseidon2_sponge_24(inputs2);\n\n assert(result1 != result2);\n}\n\n#[test]\nfn test_sponge_all_zeros() {\n // Test edge case: all zero inputs\n let inputs: [Field; 24] = [0; 24];\n\n let result = poseidon2_sponge_24(inputs);\n\n // Should produce a non-zero output due to domain tag\n assert(result != 0);\n}\n\n#[test]\nfn test_sponge_order_matters() {\n // Test that input order affects output (no commutativity)\n let inputs1: [Field; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];\n let inputs2: [Field; 24] = [2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];\n\n let result1 = poseidon2_sponge_24(inputs1);\n let result2 = poseidon2_sponge_24(inputs2);\n\n // Swapping first two elements should change output\n assert(result1 != result2);\n}\n\n#[test]\nfn test_sponge_golden_vector_sequential() {\n // GOLDEN VECTOR: Cross-language verification with TypeScript\n // This test ensures Noir and TypeScript implementations produce identical output\n //\n // Input: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]\n // Expected output (from TypeScript): 13897144223796711226515669182413786178697447221339740051025074265447026549851\n //\n // If this test fails, it means the TypeScript and Noir implementations have diverged.\n // This would cause all two-tree proofs to fail verification.\n\n let inputs: [Field; 24] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];\n let result = poseidon2_sponge_24(inputs);\n\n // TypeScript-computed golden vector\n let expected: Field = 13897144223796711226515669182413786178697447221339740051025074265447026549851;\n\n assert(result == expected);\n}\n\n#[test]\nfn test_sponge_golden_vector_all_zeros() {\n // GOLDEN VECTOR: All zeros should produce non-zero output due to domain tag\n let inputs: [Field; 24] = [0; 24];\n let result = poseidon2_sponge_24(inputs);\n\n // Should not be zero (domain tag ensures this)\n assert(result != 0);\n\n // This test doesn't enforce a specific value since it depends on the\n // Poseidon2 permutation internals, but we verify it's deterministic\n let result2 = poseidon2_sponge_24(inputs);\n assert(result == result2);\n}\n","path":"/Users/noot/Documents/voter-protocol/packages/crypto/noir/two_tree_membership/src/sponge.nr"}},"expression_width":{"Bounded":{"width":4}}}