@voter-protocol/noir-prover 0.1.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.
@@ -0,0 +1 @@
1
+ {"noir_version":"1.0.0-beta.15+83245db91dcf63420ef4bcbbd85b98f397fee663","hash":"15100744414051153266","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+jp2V9ZrSLHIZEly7YcO9Iqyr8vTFeT5IAV2doLhSFdTBVVEN67p+Hx8vKw3T8fXrtfv9+7x9N2t9u+POwOm/V5e9iPR98/Vp3/fDifhmE81H05P04d16dhf+5+7S+73ap7W+8u7Y9ej+t9w/P6NJ7tV92wfxpxJHze7oZp72P1Od0vjyLXwmlIKjNB/s6AZYYSKglKvmVexZevmm6Zz359rfGG+Qo3oEbcMp/neV3UL8vzUSPn47L+K/OpB+dTDEvzemU+yUyQqs4MqD9eQdSZ4JY7WD8j2IflCOFOD68R/MhExLtdvLqGO23UeQVaZGn+2qNA5iZCVG9hKMGXgFL7RQ1X0ghIdopw5VbU/0qRi98K6esSQcD9cbiyBoGrkIBbbob2Xgpo/B6oP+Ov9WZ7+vY26jBqWnWhbWPbprbNY61WnbRtaVtt2zqKW3XoDWAwjo+iEA1GAkxH85SpEYVYiEqsjTD0BjAIBrERh2SQDaTxh2KgdplQjS72RBADMTbGmAxMVzRhsTTiqAamLfWNP8Eg2GVSNLqUiFSXqC6ZSclcSqYtm7ZsNuVgYNpyavw5G4hdJtOkTJMy1QnVidkkZpOYNjFtYjaJGJg20cYvtUHp7TKFJhWaVKiuUF0xmwrvv2krpq2YTWoRUNOmFgG1CCgjoDRJaZJSnVKdmk3VbKqmrZq2ajZVi0A1bdUiUC0ClRGoNAl97zvwneA7ZhX6RMxEIRYGW4kMOiwNAIjMA0DLgOQ7Hvg58TDjACWaXjDzCN6fQIxEywZCJjIdCN6h4CXy+MPzj2g2IgYilbMBiGYlohCpPCpbXFljZgXJzUxuppcB3gYk2ploJ+sA9gGJdmY+OFgJZD46Mp8deX54uJnZzfRqwLuBTDuFdrIcYDsgtFMSkcrFUgQpROYI4mYWN9OLAm8KCu0stJNVAbuCQjsLg8S6QBkkZZDUg6RuprqZXht4b6C0U2kniwM2B5V2VgaJ5UFlkCqDVD1IU4Om/4ExdSiEaWekDNMb42192q4fdwM/Vp4v+82Xb5fz36Of8a+b4+mwGZ4up2F6s7Rz47vmHw==","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// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\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 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"},"50":{"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}}}
package/dist/index.cjs ADDED
@@ -0,0 +1,253 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
+
5
+ const bb_js = require('@voter-protocol/bb.js');
6
+ const noir_js = require('@noir-lang/noir_js');
7
+ const pako = require('pako');
8
+
9
+ const noir_version = "1.0.0-beta.15+83245db91dcf63420ef4bcbbd85b98f397fee663";
10
+ const hash = "15100744414051153266";
11
+ const abi = {
12
+ parameters: [
13
+ {
14
+ name: "merkle_root",
15
+ type: {
16
+ kind: "field"
17
+ },
18
+ visibility: "private"
19
+ },
20
+ {
21
+ name: "nullifier",
22
+ type: {
23
+ kind: "field"
24
+ },
25
+ visibility: "private"
26
+ },
27
+ {
28
+ name: "authority_hash",
29
+ type: {
30
+ kind: "field"
31
+ },
32
+ visibility: "private"
33
+ },
34
+ {
35
+ name: "epoch_id",
36
+ type: {
37
+ kind: "field"
38
+ },
39
+ visibility: "private"
40
+ },
41
+ {
42
+ name: "campaign_id",
43
+ type: {
44
+ kind: "field"
45
+ },
46
+ visibility: "private"
47
+ },
48
+ {
49
+ name: "leaf",
50
+ type: {
51
+ kind: "field"
52
+ },
53
+ visibility: "private"
54
+ },
55
+ {
56
+ name: "merkle_path",
57
+ type: {
58
+ kind: "array",
59
+ length: 14,
60
+ type: {
61
+ kind: "field"
62
+ }
63
+ },
64
+ visibility: "private"
65
+ },
66
+ {
67
+ name: "leaf_index",
68
+ type: {
69
+ kind: "integer",
70
+ sign: "unsigned",
71
+ width: 32
72
+ },
73
+ visibility: "private"
74
+ },
75
+ {
76
+ name: "user_secret",
77
+ type: {
78
+ kind: "field"
79
+ },
80
+ visibility: "private"
81
+ }
82
+ ],
83
+ return_type: {
84
+ abi_type: {
85
+ kind: "tuple",
86
+ fields: [
87
+ {
88
+ kind: "field"
89
+ },
90
+ {
91
+ kind: "field"
92
+ },
93
+ {
94
+ kind: "field"
95
+ },
96
+ {
97
+ kind: "field"
98
+ },
99
+ {
100
+ kind: "field"
101
+ }
102
+ ]
103
+ },
104
+ visibility: "public"
105
+ },
106
+ error_types: {
107
+ }
108
+ };
109
+ const bytecode = "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";
110
+ const debug_symbols = "tVfLbqNAEPwXzj5Q8+jp2V9ZrSLHIZEly7YcO9Iqyr8vTFeT5IAV2doLhSFdTBVVEN67p+Hx8vKw3T8fXrtfv9+7x9N2t9u+POwOm/V5e9iPR98/Vp3/fDifhmE81H05P04d16dhf+5+7S+73ap7W+8u7Y9ej+t9w/P6NJ7tV92wfxpxJHze7oZp72P1Od0vjyLXwmlIKjNB/s6AZYYSKglKvmVexZevmm6Zz359rfGG+Qo3oEbcMp/neV3UL8vzUSPn47L+K/OpB+dTDEvzemU+yUyQqs4MqD9eQdSZ4JY7WD8j2IflCOFOD68R/MhExLtdvLqGO23UeQVaZGn+2qNA5iZCVG9hKMGXgFL7RQ1X0ghIdopw5VbU/0qRi98K6esSQcD9cbiyBoGrkIBbbob2Xgpo/B6oP+Ov9WZ7+vY26jBqWnWhbWPbprbNY61WnbRtaVtt2zqKW3XoDWAwjo+iEA1GAkxH85SpEYVYiEqsjTD0BjAIBrERh2SQDaTxh2KgdplQjS72RBADMTbGmAxMVzRhsTTiqAamLfWNP8Eg2GVSNLqUiFSXqC6ZSclcSqYtm7ZsNuVgYNpyavw5G4hdJtOkTJMy1QnVidkkZpOYNjFtYjaJGJg20cYvtUHp7TKFJhWaVKiuUF0xmwrvv2krpq2YTWoRUNOmFgG1CCgjoDRJaZJSnVKdmk3VbKqmrZq2ajZVi0A1bdUiUC0ClRGoNAl97zvwneA7ZhX6RMxEIRYGW4kMOiwNAIjMA0DLgOQ7Hvg58TDjACWaXjDzCN6fQIxEywZCJjIdCN6h4CXy+MPzj2g2IgYilbMBiGYlohCpPCpbXFljZgXJzUxuppcB3gYk2ploJ+sA9gGJdmY+OFgJZD46Mp8deX54uJnZzfRqwLuBTDuFdrIcYDsgtFMSkcrFUgQpROYI4mYWN9OLAm8KCu0stJNVAbuCQjsLg8S6QBkkZZDUg6RuprqZXht4b6C0U2kniwM2B5V2VgaJ5UFlkCqDVD1IU4Om/4ExdSiEaWekDNMb42192q4fdwM/Vp4v+82Xb5fz36Of8a+b4+mwGZ4up2F6s7Rz47vmHw==";
111
+ const file_map = {
112
+ "19": {
113
+ 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// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\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 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",
114
+ path: "std/hash/mod.nr"
115
+ },
116
+ "50": {
117
+ 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",
118
+ path: "/Users/noot/Documents/voter-protocol/packages/crypto/noir/district_membership/src/main.nr"
119
+ }
120
+ };
121
+ const expression_width = {
122
+ Bounded: {
123
+ width: 4
124
+ }
125
+ };
126
+ const circuitJson = {
127
+ noir_version: noir_version,
128
+ hash: hash,
129
+ abi: abi,
130
+ bytecode: bytecode,
131
+ debug_symbols: debug_symbols,
132
+ file_map: file_map,
133
+ expression_width: expression_width
134
+ };
135
+
136
+ class NoirProver {
137
+ api = null;
138
+ noir = null;
139
+ bytecode = null;
140
+ provingKey = null;
141
+ config;
142
+ constructor(config = {}) {
143
+ this.config = {
144
+ circuitName: "district_membership",
145
+ ...config
146
+ };
147
+ }
148
+ /**
149
+ * Initialize the prover (must be called before generating proofs)
150
+ */
151
+ async init() {
152
+ if (this.api && this.noir) return;
153
+ console.log("[NoirProver] Initializing...");
154
+ const start = Date.now();
155
+ this.api = await bb_js.Barretenberg.new();
156
+ this.noir = new noir_js.Noir(circuitJson);
157
+ if (this.config.bytecode) {
158
+ this.bytecode = this.config.bytecode;
159
+ } else {
160
+ const bytecodeBuffer = Uint8Array.from(atob(circuitJson.bytecode), (c) => c.charCodeAt(0));
161
+ this.bytecode = pako.inflate(bytecodeBuffer);
162
+ }
163
+ console.log(`[NoirProver] Initialized in ${Date.now() - start}ms`);
164
+ }
165
+ /**
166
+ * Pre-warm the prover by generating the proving key
167
+ * Call this on app load to hide latency from user
168
+ */
169
+ async warmup() {
170
+ await this.init();
171
+ if (this.provingKey) return;
172
+ console.log("[NoirProver] Warming up (generating proving key)...");
173
+ const start = Date.now();
174
+ const result = await this.api.acirGetProvingKey({
175
+ circuit: {
176
+ name: this.config.circuitName,
177
+ bytecode: this.bytecode,
178
+ verificationKey: new Uint8Array(0)
179
+ },
180
+ settings: {
181
+ ipaAccumulation: false,
182
+ oracleHashType: "poseidon",
183
+ disableZk: false,
184
+ optimizedSolidityVerifier: false
185
+ }
186
+ });
187
+ this.provingKey = result.provingKey;
188
+ console.log(`[NoirProver] Warmup complete in ${Date.now() - start}ms`);
189
+ }
190
+ /**
191
+ * Generate a ZK proof for district membership
192
+ */
193
+ async prove(inputs) {
194
+ await this.warmup();
195
+ console.log("[NoirProver] Generating witness...");
196
+ const witnessStart = Date.now();
197
+ const noirInputs = {
198
+ merkle_root: inputs.merkleRoot,
199
+ nullifier: inputs.nullifier,
200
+ authority_hash: inputs.authorityHash,
201
+ epoch_id: inputs.epochId,
202
+ campaign_id: inputs.campaignId,
203
+ leaf: inputs.leaf,
204
+ merkle_path: inputs.merklePath,
205
+ leaf_index: inputs.leafIndex,
206
+ user_secret: inputs.userSecret
207
+ };
208
+ const { witness } = await this.noir.execute(noirInputs);
209
+ console.log(`[NoirProver] Witness generated in ${Date.now() - witnessStart}ms`);
210
+ console.log("[NoirProver] Generating proof...");
211
+ const proofStart = Date.now();
212
+ const result = await this.api.acirProveWithPk({
213
+ circuit: {
214
+ name: this.config.circuitName,
215
+ bytecode: this.bytecode,
216
+ verificationKey: new Uint8Array(0)
217
+ },
218
+ witness,
219
+ provingKey: this.provingKey,
220
+ settings: {
221
+ ipaAccumulation: false,
222
+ oracleHashType: "poseidon",
223
+ disableZk: false,
224
+ optimizedSolidityVerifier: false
225
+ }
226
+ });
227
+ console.log(`[NoirProver] Proof generated in ${Date.now() - proofStart}ms`);
228
+ return {
229
+ proof: result.proof,
230
+ publicInputs: {
231
+ merkleRoot: inputs.merkleRoot,
232
+ nullifier: inputs.nullifier,
233
+ authorityHash: inputs.authorityHash,
234
+ epochId: inputs.epochId,
235
+ campaignId: inputs.campaignId
236
+ }
237
+ };
238
+ }
239
+ /**
240
+ * Clean up resources
241
+ */
242
+ async destroy() {
243
+ if (this.api) {
244
+ await this.api.destroy();
245
+ this.api = null;
246
+ this.noir = null;
247
+ this.bytecode = null;
248
+ this.provingKey = null;
249
+ }
250
+ }
251
+ }
252
+
253
+ exports.NoirProver = NoirProver;
@@ -0,0 +1,2 @@
1
+ export * from './src/index'
2
+ export {}
package/dist/index.js ADDED
@@ -0,0 +1,249 @@
1
+ import { Barretenberg } from '@voter-protocol/bb.js';
2
+ import { Noir } from '@noir-lang/noir_js';
3
+ import { inflate } from 'pako';
4
+
5
+ const noir_version = "1.0.0-beta.15+83245db91dcf63420ef4bcbbd85b98f397fee663";
6
+ const hash = "15100744414051153266";
7
+ const abi = {
8
+ parameters: [
9
+ {
10
+ name: "merkle_root",
11
+ type: {
12
+ kind: "field"
13
+ },
14
+ visibility: "private"
15
+ },
16
+ {
17
+ name: "nullifier",
18
+ type: {
19
+ kind: "field"
20
+ },
21
+ visibility: "private"
22
+ },
23
+ {
24
+ name: "authority_hash",
25
+ type: {
26
+ kind: "field"
27
+ },
28
+ visibility: "private"
29
+ },
30
+ {
31
+ name: "epoch_id",
32
+ type: {
33
+ kind: "field"
34
+ },
35
+ visibility: "private"
36
+ },
37
+ {
38
+ name: "campaign_id",
39
+ type: {
40
+ kind: "field"
41
+ },
42
+ visibility: "private"
43
+ },
44
+ {
45
+ name: "leaf",
46
+ type: {
47
+ kind: "field"
48
+ },
49
+ visibility: "private"
50
+ },
51
+ {
52
+ name: "merkle_path",
53
+ type: {
54
+ kind: "array",
55
+ length: 14,
56
+ type: {
57
+ kind: "field"
58
+ }
59
+ },
60
+ visibility: "private"
61
+ },
62
+ {
63
+ name: "leaf_index",
64
+ type: {
65
+ kind: "integer",
66
+ sign: "unsigned",
67
+ width: 32
68
+ },
69
+ visibility: "private"
70
+ },
71
+ {
72
+ name: "user_secret",
73
+ type: {
74
+ kind: "field"
75
+ },
76
+ visibility: "private"
77
+ }
78
+ ],
79
+ return_type: {
80
+ abi_type: {
81
+ kind: "tuple",
82
+ fields: [
83
+ {
84
+ kind: "field"
85
+ },
86
+ {
87
+ kind: "field"
88
+ },
89
+ {
90
+ kind: "field"
91
+ },
92
+ {
93
+ kind: "field"
94
+ },
95
+ {
96
+ kind: "field"
97
+ }
98
+ ]
99
+ },
100
+ visibility: "public"
101
+ },
102
+ error_types: {
103
+ }
104
+ };
105
+ const bytecode = "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";
106
+ const debug_symbols = "tVfLbqNAEPwXzj5Q8+jp2V9ZrSLHIZEly7YcO9Iqyr8vTFeT5IAV2doLhSFdTBVVEN67p+Hx8vKw3T8fXrtfv9+7x9N2t9u+POwOm/V5e9iPR98/Vp3/fDifhmE81H05P04d16dhf+5+7S+73ap7W+8u7Y9ej+t9w/P6NJ7tV92wfxpxJHze7oZp72P1Od0vjyLXwmlIKjNB/s6AZYYSKglKvmVexZevmm6Zz359rfGG+Qo3oEbcMp/neV3UL8vzUSPn47L+K/OpB+dTDEvzemU+yUyQqs4MqD9eQdSZ4JY7WD8j2IflCOFOD68R/MhExLtdvLqGO23UeQVaZGn+2qNA5iZCVG9hKMGXgFL7RQ1X0ghIdopw5VbU/0qRi98K6esSQcD9cbiyBoGrkIBbbob2Xgpo/B6oP+Ov9WZ7+vY26jBqWnWhbWPbprbNY61WnbRtaVtt2zqKW3XoDWAwjo+iEA1GAkxH85SpEYVYiEqsjTD0BjAIBrERh2SQDaTxh2KgdplQjS72RBADMTbGmAxMVzRhsTTiqAamLfWNP8Eg2GVSNLqUiFSXqC6ZSclcSqYtm7ZsNuVgYNpyavw5G4hdJtOkTJMy1QnVidkkZpOYNjFtYjaJGJg20cYvtUHp7TKFJhWaVKiuUF0xmwrvv2krpq2YTWoRUNOmFgG1CCgjoDRJaZJSnVKdmk3VbKqmrZq2ajZVi0A1bdUiUC0ClRGoNAl97zvwneA7ZhX6RMxEIRYGW4kMOiwNAIjMA0DLgOQ7Hvg58TDjACWaXjDzCN6fQIxEywZCJjIdCN6h4CXy+MPzj2g2IgYilbMBiGYlohCpPCpbXFljZgXJzUxuppcB3gYk2ploJ+sA9gGJdmY+OFgJZD46Mp8deX54uJnZzfRqwLuBTDuFdrIcYDsgtFMSkcrFUgQpROYI4mYWN9OLAm8KCu0stJNVAbuCQjsLg8S6QBkkZZDUg6RuprqZXht4b6C0U2kniwM2B5V2VgaJ5UFlkCqDVD1IU4Om/4ExdSiEaWekDNMb42192q4fdwM/Vp4v+82Xb5fz36Of8a+b4+mwGZ4up2F6s7Rz47vmHw==";
107
+ const file_map = {
108
+ "19": {
109
+ 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// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\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 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",
110
+ path: "std/hash/mod.nr"
111
+ },
112
+ "50": {
113
+ 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",
114
+ path: "/Users/noot/Documents/voter-protocol/packages/crypto/noir/district_membership/src/main.nr"
115
+ }
116
+ };
117
+ const expression_width = {
118
+ Bounded: {
119
+ width: 4
120
+ }
121
+ };
122
+ const circuitJson = {
123
+ noir_version: noir_version,
124
+ hash: hash,
125
+ abi: abi,
126
+ bytecode: bytecode,
127
+ debug_symbols: debug_symbols,
128
+ file_map: file_map,
129
+ expression_width: expression_width
130
+ };
131
+
132
+ class NoirProver {
133
+ api = null;
134
+ noir = null;
135
+ bytecode = null;
136
+ provingKey = null;
137
+ config;
138
+ constructor(config = {}) {
139
+ this.config = {
140
+ circuitName: "district_membership",
141
+ ...config
142
+ };
143
+ }
144
+ /**
145
+ * Initialize the prover (must be called before generating proofs)
146
+ */
147
+ async init() {
148
+ if (this.api && this.noir) return;
149
+ console.log("[NoirProver] Initializing...");
150
+ const start = Date.now();
151
+ this.api = await Barretenberg.new();
152
+ this.noir = new Noir(circuitJson);
153
+ if (this.config.bytecode) {
154
+ this.bytecode = this.config.bytecode;
155
+ } else {
156
+ const bytecodeBuffer = Uint8Array.from(atob(circuitJson.bytecode), (c) => c.charCodeAt(0));
157
+ this.bytecode = inflate(bytecodeBuffer);
158
+ }
159
+ console.log(`[NoirProver] Initialized in ${Date.now() - start}ms`);
160
+ }
161
+ /**
162
+ * Pre-warm the prover by generating the proving key
163
+ * Call this on app load to hide latency from user
164
+ */
165
+ async warmup() {
166
+ await this.init();
167
+ if (this.provingKey) return;
168
+ console.log("[NoirProver] Warming up (generating proving key)...");
169
+ const start = Date.now();
170
+ const result = await this.api.acirGetProvingKey({
171
+ circuit: {
172
+ name: this.config.circuitName,
173
+ bytecode: this.bytecode,
174
+ verificationKey: new Uint8Array(0)
175
+ },
176
+ settings: {
177
+ ipaAccumulation: false,
178
+ oracleHashType: "poseidon",
179
+ disableZk: false,
180
+ optimizedSolidityVerifier: false
181
+ }
182
+ });
183
+ this.provingKey = result.provingKey;
184
+ console.log(`[NoirProver] Warmup complete in ${Date.now() - start}ms`);
185
+ }
186
+ /**
187
+ * Generate a ZK proof for district membership
188
+ */
189
+ async prove(inputs) {
190
+ await this.warmup();
191
+ console.log("[NoirProver] Generating witness...");
192
+ const witnessStart = Date.now();
193
+ const noirInputs = {
194
+ merkle_root: inputs.merkleRoot,
195
+ nullifier: inputs.nullifier,
196
+ authority_hash: inputs.authorityHash,
197
+ epoch_id: inputs.epochId,
198
+ campaign_id: inputs.campaignId,
199
+ leaf: inputs.leaf,
200
+ merkle_path: inputs.merklePath,
201
+ leaf_index: inputs.leafIndex,
202
+ user_secret: inputs.userSecret
203
+ };
204
+ const { witness } = await this.noir.execute(noirInputs);
205
+ console.log(`[NoirProver] Witness generated in ${Date.now() - witnessStart}ms`);
206
+ console.log("[NoirProver] Generating proof...");
207
+ const proofStart = Date.now();
208
+ const result = await this.api.acirProveWithPk({
209
+ circuit: {
210
+ name: this.config.circuitName,
211
+ bytecode: this.bytecode,
212
+ verificationKey: new Uint8Array(0)
213
+ },
214
+ witness,
215
+ provingKey: this.provingKey,
216
+ settings: {
217
+ ipaAccumulation: false,
218
+ oracleHashType: "poseidon",
219
+ disableZk: false,
220
+ optimizedSolidityVerifier: false
221
+ }
222
+ });
223
+ console.log(`[NoirProver] Proof generated in ${Date.now() - proofStart}ms`);
224
+ return {
225
+ proof: result.proof,
226
+ publicInputs: {
227
+ merkleRoot: inputs.merkleRoot,
228
+ nullifier: inputs.nullifier,
229
+ authorityHash: inputs.authorityHash,
230
+ epochId: inputs.epochId,
231
+ campaignId: inputs.campaignId
232
+ }
233
+ };
234
+ }
235
+ /**
236
+ * Clean up resources
237
+ */
238
+ async destroy() {
239
+ if (this.api) {
240
+ await this.api.destroy();
241
+ this.api = null;
242
+ this.noir = null;
243
+ this.bytecode = null;
244
+ this.provingKey = null;
245
+ }
246
+ }
247
+ }
248
+
249
+ export { NoirProver };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @voter-protocol/noir-prover
3
+ *
4
+ * Browser-native ZK prover using Barretenberg/Noir backend.
5
+ */
6
+ export { NoirProver } from './prover';
7
+ export type { ProverConfig, ProofResult, CircuitInputs } from './types';
@@ -0,0 +1,26 @@
1
+ import { ProverConfig, CircuitInputs, ProofResult } from './types';
2
+ export declare class NoirProver {
3
+ private api;
4
+ private noir;
5
+ private bytecode;
6
+ private provingKey;
7
+ private config;
8
+ constructor(config?: ProverConfig);
9
+ /**
10
+ * Initialize the prover (must be called before generating proofs)
11
+ */
12
+ init(): Promise<void>;
13
+ /**
14
+ * Pre-warm the prover by generating the proving key
15
+ * Call this on app load to hide latency from user
16
+ */
17
+ warmup(): Promise<void>;
18
+ /**
19
+ * Generate a ZK proof for district membership
20
+ */
21
+ prove(inputs: CircuitInputs): Promise<ProofResult>;
22
+ /**
23
+ * Clean up resources
24
+ */
25
+ destroy(): Promise<void>;
26
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Type definitions for NoirProver
3
+ */
4
+ export interface ProverConfig {
5
+ /** Circuit name (default: 'district_membership') */
6
+ circuitName?: string;
7
+ /** Custom circuit bytecode (optional) */
8
+ bytecode?: Uint8Array;
9
+ }
10
+ export interface CircuitInputs {
11
+ /** Merkle root of the district tree */
12
+ merkleRoot: string;
13
+ /** Nullifier for double-spend prevention */
14
+ nullifier: string;
15
+ /** Authority hash */
16
+ authorityHash: string;
17
+ /** Epoch ID */
18
+ epochId: string;
19
+ /** Campaign ID */
20
+ campaignId: string;
21
+ /** Leaf value (hashed address) */
22
+ leaf: string;
23
+ /** Merkle path (siblings) */
24
+ merklePath: string[];
25
+ /** Leaf index in tree */
26
+ leafIndex: number;
27
+ /** User secret for nullifier */
28
+ userSecret: string;
29
+ }
30
+ export interface ProofResult {
31
+ /** Serialized proof (format depends on backend) */
32
+ proof: unknown;
33
+ /** Public inputs */
34
+ publicInputs: {
35
+ merkleRoot: string;
36
+ nullifier: string;
37
+ authorityHash: string;
38
+ epochId: string;
39
+ campaignId: string;
40
+ };
41
+ }
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@voter-protocol/noir-prover",
3
+ "version": "0.1.0",
4
+ "description": "Browser-native ZK prover for VOTER Protocol using Barretenberg/Noir",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "wasm",
19
+ "circuits"
20
+ ],
21
+ "scripts": {
22
+ "dev": "vite build --watch",
23
+ "build": "tsc && vite build",
24
+ "test": "vitest",
25
+ "typecheck": "tsc --noEmit",
26
+ "sync-wasm": "../scripts/sync-artifacts"
27
+ },
28
+ "peerDependencies": {
29
+ "@noir-lang/noir_js": "^1.0.0-beta.11",
30
+ "@voter-protocol/bb.js": "^0.87.0-fork.1",
31
+ "pako": "^2.1.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^24.3.2",
35
+ "@types/pako": "^2.0.4",
36
+ "typescript": "^5.7.2",
37
+ "vite": "^5.4.10",
38
+ "vite-plugin-dts": "^4.3.0",
39
+ "vite-plugin-wasm": "^3.3.0",
40
+ "vitest": "^2.1.8"
41
+ },
42
+ "keywords": [
43
+ "voter-protocol",
44
+ "zk",
45
+ "noir",
46
+ "barretenberg",
47
+ "zero-knowledge",
48
+ "browser"
49
+ ],
50
+ "author": "VOTER Protocol",
51
+ "license": "MIT",
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://github.com/communisaas/voter-protocol.git",
55
+ "directory": "packages/noir-prover"
56
+ }
57
+ }
Binary file