From c0012ba24e8f8fcdf432ed6342fa1142f5f73625 Mon Sep 17 00:00:00 2001 From: Cedoor Date: Fri, 16 Jan 2026 16:26:33 +0100 Subject: [PATCH 01/30] refactor: move pvss circuits to enclave --- circuits/Nargo.toml | 6 - circuits/bin/aggregation/Nargo.toml | 7 + circuits/bin/aggregation/fold/Nargo.toml | 9 + circuits/bin/aggregation/fold/src/main.nr | 19 + .../verify_shares_trbfv_wrapper/Nargo.toml | 9 + .../verify_shares_trbfv_wrapper/src/main.nr | 28 + .../aggregation/pk_trbfv_wrapper/Nargo.toml | 9 + .../aggregation/pk_trbfv_wrapper/src/main.nr | 28 + .../verify_shares_trbfv_wrapper/Nargo.toml | 9 + .../verify_shares_trbfv_wrapper/src/main.nr | 28 + circuits/bin/insecure/Nargo.toml | 15 + circuits/bin/insecure/dec_bfv_e_sm/Nargo.toml | 9 + circuits/bin/insecure/dec_bfv_e_sm/README.md | 1 + .../bin/insecure/dec_bfv_e_sm/src/main.nr | 16 + circuits/bin/insecure/dec_bfv_sk/Nargo.toml | 9 + circuits/bin/insecure/dec_bfv_sk/README.md | 1 + circuits/bin/insecure/dec_bfv_sk/src/main.nr | 16 + .../insecure/dec_share_agg_trbfv/Nargo.toml | 9 + .../insecure/dec_share_agg_trbfv/README.md | 1 + .../insecure/dec_share_agg_trbfv/src/main.nr | 27 + .../bin/insecure/dec_share_trbfv/Nargo.toml | 9 + .../bin/insecure/dec_share_trbfv/README.md | 1 + .../bin/insecure/dec_share_trbfv/src/main.nr | 38 ++ circuits/bin/insecure/enc_bfv_e_sm/Nargo.toml | 9 + circuits/bin/insecure/enc_bfv_e_sm/README.md | 1 + .../bin/insecure/enc_bfv_e_sm/src/main.nr | 46 ++ circuits/bin/insecure/enc_bfv_sk/Nargo.toml | 9 + circuits/bin/insecure/enc_bfv_sk/README.md | 1 + circuits/bin/insecure/enc_bfv_sk/src/main.nr | 46 ++ circuits/bin/insecure/greco/Nargo.toml | 9 + circuits/bin/insecure/greco/README.md | 1 + circuits/bin/insecure/greco/src/main.nr | 45 ++ circuits/bin/insecure/pk_agg_trbfv/Nargo.toml | 9 + circuits/bin/insecure/pk_agg_trbfv/README.md | 1 + .../bin/insecure/pk_agg_trbfv/src/main.nr | 25 + circuits/bin/insecure/pk_bfv/Nargo.toml | 9 + circuits/bin/insecure/pk_bfv/README.md | 1 + circuits/bin/insecure/pk_bfv/src/main.nr | 8 + circuits/bin/insecure/pk_trbfv/Nargo.toml | 9 + circuits/bin/insecure/pk_trbfv/README.md | 1 + circuits/bin/insecure/pk_trbfv/src/main.nr | 21 + .../verify_shares_trbfv_e_sm/Nargo.toml | 9 + .../verify_shares_trbfv_e_sm/README.md | 1 + .../verify_shares_trbfv_e_sm/src/main.nr | 27 + .../verify_shares_trbfv_sk/Nargo.toml | 9 + .../insecure/verify_shares_trbfv_sk/README.md | 1 + .../verify_shares_trbfv_sk/src/main.nr | 27 + circuits/bin/production/Nargo.toml | 15 + .../bin/production/dec_bfv_e_sm/Nargo.toml | 9 + .../bin/production/dec_bfv_e_sm/README.md | 1 + .../bin/production/dec_bfv_e_sm/src/main.nr | 16 + circuits/bin/production/dec_bfv_sk/Nargo.toml | 9 + circuits/bin/production/dec_bfv_sk/README.md | 1 + .../bin/production/dec_bfv_sk/src/main.nr | 16 + .../production/dec_share_agg_trbfv/Nargo.toml | 9 + .../production/dec_share_agg_trbfv/README.md | 1 + .../dec_share_agg_trbfv/src/main.nr | 27 + .../bin/production/dec_share_trbfv/Nargo.toml | 9 + .../bin/production/dec_share_trbfv/README.md | 1 + .../production/dec_share_trbfv/src/main.nr | 38 ++ .../bin/production/enc_bfv_e_sm/Nargo.toml | 9 + .../bin/production/enc_bfv_e_sm/README.md | 1 + .../bin/production/enc_bfv_e_sm/src/main.nr | 46 ++ circuits/bin/production/enc_bfv_sk/Nargo.toml | 9 + circuits/bin/production/enc_bfv_sk/README.md | 1 + .../bin/production/enc_bfv_sk/src/main.nr | 46 ++ circuits/bin/production/greco/Nargo.toml | 9 + circuits/bin/production/greco/README.md | 1 + circuits/bin/production/greco/src/main.nr | 45 ++ .../bin/production/pk_agg_trbfv/Nargo.toml | 8 + .../bin/production/pk_agg_trbfv/README.md | 1 + .../bin/production/pk_agg_trbfv/src/main.nr | 25 + circuits/bin/production/pk_bfv/Nargo.toml | 8 + circuits/bin/production/pk_bfv/README.md | 1 + circuits/bin/production/pk_bfv/src/main.nr | 8 + circuits/bin/production/pk_trbfv/Nargo.toml | 8 + circuits/bin/production/pk_trbfv/README.md | 1 + circuits/bin/production/pk_trbfv/src/main.nr | 21 + .../verify_shares_trbfv_e_sm/Nargo.toml | 9 + .../verify_shares_trbfv_e_sm/README.md | 1 + .../verify_shares_trbfv_e_sm/src/main.nr | 27 + .../verify_shares_trbfv_sk/Nargo.toml | 9 + .../verify_shares_trbfv_sk/README.md | 1 + .../verify_shares_trbfv_sk/src/main.nr | 27 + circuits/crates/libs/greco/Nargo.toml | 11 - circuits/crates/libs/greco/README.md | 104 --- circuits/crates/libs/polynomial/Nargo.toml | 8 - circuits/crates/libs/polynomial/README.md | 35 -- circuits/crates/libs/safe/README.md | 83 --- circuits/{crates/libs/safe => lib}/Nargo.toml | 10 +- circuits/lib/src/configs/insecure/bfv.nr | 114 ++++ circuits/lib/src/configs/insecure/mod.nr | 2 + circuits/lib/src/configs/insecure/trbfv.nr | 175 ++++++ circuits/lib/src/configs/mod.nr | 2 + circuits/lib/src/configs/production/bfv.nr | 117 ++++ circuits/lib/src/configs/production/mod.nr | 2 + circuits/lib/src/configs/production/trbfv.nr | 185 ++++++ circuits/lib/src/core/bfv_dec.nr | 78 +++ circuits/lib/src/core/bfv_enc.nr | 369 +++++++++++ circuits/lib/src/core/bfv_pk.nr | 28 + .../src/lib.nr => lib/src/core/greco.nr} | 365 +++-------- circuits/lib/src/core/mod.nr | 9 + circuits/lib/src/core/trbfv_dec_share.nr | 286 +++++++++ circuits/lib/src/core/trbfv_dec_shares_agg.nr | 321 ++++++++++ circuits/lib/src/core/trbfv_pk.nr | 216 +++++++ circuits/lib/src/core/trbfv_pk_agg.nr | 118 ++++ circuits/lib/src/core/trbfv_verify_shares.nr | 282 +++++++++ circuits/lib/src/lib.nr | 11 + circuits/lib/src/math/commitments.nr | 303 +++++++++ .../src/lib.nr => lib/src/math/helpers.nr} | 299 ++++----- circuits/lib/src/math/mod.nr | 5 + circuits/lib/src/math/modulo/U128.nr | 592 +++++++++++++++++ circuits/lib/src/math/modulo/mod.nr | 2 + .../lib/src/math/modulo/unconstrained_U128.nr | 593 ++++++++++++++++++ circuits/lib/src/math/polynomial.nr | 457 ++++++++++++++ .../safe/src/lib.nr => lib/src/math/safe.nr} | 0 scripts/lint-circuits.sh | 50 +- scripts/test-circuits.sh | 2 +- 118 files changed, 5620 insertions(+), 717 deletions(-) delete mode 100644 circuits/Nargo.toml create mode 100644 circuits/bin/aggregation/Nargo.toml create mode 100644 circuits/bin/aggregation/fold/Nargo.toml create mode 100644 circuits/bin/aggregation/fold/src/main.nr create mode 100644 circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr create mode 100644 circuits/bin/insecure/Nargo.toml create mode 100644 circuits/bin/insecure/dec_bfv_e_sm/Nargo.toml create mode 100644 circuits/bin/insecure/dec_bfv_e_sm/README.md create mode 100644 circuits/bin/insecure/dec_bfv_e_sm/src/main.nr create mode 100644 circuits/bin/insecure/dec_bfv_sk/Nargo.toml create mode 100644 circuits/bin/insecure/dec_bfv_sk/README.md create mode 100644 circuits/bin/insecure/dec_bfv_sk/src/main.nr create mode 100644 circuits/bin/insecure/dec_share_agg_trbfv/Nargo.toml create mode 100644 circuits/bin/insecure/dec_share_agg_trbfv/README.md create mode 100644 circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr create mode 100644 circuits/bin/insecure/dec_share_trbfv/Nargo.toml create mode 100644 circuits/bin/insecure/dec_share_trbfv/README.md create mode 100644 circuits/bin/insecure/dec_share_trbfv/src/main.nr create mode 100644 circuits/bin/insecure/enc_bfv_e_sm/Nargo.toml create mode 100644 circuits/bin/insecure/enc_bfv_e_sm/README.md create mode 100644 circuits/bin/insecure/enc_bfv_e_sm/src/main.nr create mode 100644 circuits/bin/insecure/enc_bfv_sk/Nargo.toml create mode 100644 circuits/bin/insecure/enc_bfv_sk/README.md create mode 100644 circuits/bin/insecure/enc_bfv_sk/src/main.nr create mode 100644 circuits/bin/insecure/greco/Nargo.toml create mode 100644 circuits/bin/insecure/greco/README.md create mode 100644 circuits/bin/insecure/greco/src/main.nr create mode 100644 circuits/bin/insecure/pk_agg_trbfv/Nargo.toml create mode 100644 circuits/bin/insecure/pk_agg_trbfv/README.md create mode 100644 circuits/bin/insecure/pk_agg_trbfv/src/main.nr create mode 100644 circuits/bin/insecure/pk_bfv/Nargo.toml create mode 100644 circuits/bin/insecure/pk_bfv/README.md create mode 100644 circuits/bin/insecure/pk_bfv/src/main.nr create mode 100644 circuits/bin/insecure/pk_trbfv/Nargo.toml create mode 100644 circuits/bin/insecure/pk_trbfv/README.md create mode 100644 circuits/bin/insecure/pk_trbfv/src/main.nr create mode 100644 circuits/bin/insecure/verify_shares_trbfv_e_sm/Nargo.toml create mode 100644 circuits/bin/insecure/verify_shares_trbfv_e_sm/README.md create mode 100644 circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr create mode 100644 circuits/bin/insecure/verify_shares_trbfv_sk/Nargo.toml create mode 100644 circuits/bin/insecure/verify_shares_trbfv_sk/README.md create mode 100644 circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr create mode 100644 circuits/bin/production/Nargo.toml create mode 100644 circuits/bin/production/dec_bfv_e_sm/Nargo.toml create mode 100644 circuits/bin/production/dec_bfv_e_sm/README.md create mode 100644 circuits/bin/production/dec_bfv_e_sm/src/main.nr create mode 100644 circuits/bin/production/dec_bfv_sk/Nargo.toml create mode 100644 circuits/bin/production/dec_bfv_sk/README.md create mode 100644 circuits/bin/production/dec_bfv_sk/src/main.nr create mode 100644 circuits/bin/production/dec_share_agg_trbfv/Nargo.toml create mode 100644 circuits/bin/production/dec_share_agg_trbfv/README.md create mode 100644 circuits/bin/production/dec_share_agg_trbfv/src/main.nr create mode 100644 circuits/bin/production/dec_share_trbfv/Nargo.toml create mode 100644 circuits/bin/production/dec_share_trbfv/README.md create mode 100644 circuits/bin/production/dec_share_trbfv/src/main.nr create mode 100644 circuits/bin/production/enc_bfv_e_sm/Nargo.toml create mode 100644 circuits/bin/production/enc_bfv_e_sm/README.md create mode 100644 circuits/bin/production/enc_bfv_e_sm/src/main.nr create mode 100644 circuits/bin/production/enc_bfv_sk/Nargo.toml create mode 100644 circuits/bin/production/enc_bfv_sk/README.md create mode 100644 circuits/bin/production/enc_bfv_sk/src/main.nr create mode 100644 circuits/bin/production/greco/Nargo.toml create mode 100644 circuits/bin/production/greco/README.md create mode 100644 circuits/bin/production/greco/src/main.nr create mode 100644 circuits/bin/production/pk_agg_trbfv/Nargo.toml create mode 100644 circuits/bin/production/pk_agg_trbfv/README.md create mode 100644 circuits/bin/production/pk_agg_trbfv/src/main.nr create mode 100644 circuits/bin/production/pk_bfv/Nargo.toml create mode 100644 circuits/bin/production/pk_bfv/README.md create mode 100644 circuits/bin/production/pk_bfv/src/main.nr create mode 100644 circuits/bin/production/pk_trbfv/Nargo.toml create mode 100644 circuits/bin/production/pk_trbfv/README.md create mode 100644 circuits/bin/production/pk_trbfv/src/main.nr create mode 100644 circuits/bin/production/verify_shares_trbfv_e_sm/Nargo.toml create mode 100644 circuits/bin/production/verify_shares_trbfv_e_sm/README.md create mode 100644 circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr create mode 100644 circuits/bin/production/verify_shares_trbfv_sk/Nargo.toml create mode 100644 circuits/bin/production/verify_shares_trbfv_sk/README.md create mode 100644 circuits/bin/production/verify_shares_trbfv_sk/src/main.nr delete mode 100644 circuits/crates/libs/greco/Nargo.toml delete mode 100644 circuits/crates/libs/greco/README.md delete mode 100644 circuits/crates/libs/polynomial/Nargo.toml delete mode 100644 circuits/crates/libs/polynomial/README.md delete mode 100644 circuits/crates/libs/safe/README.md rename circuits/{crates/libs/safe => lib}/Nargo.toml (51%) create mode 100644 circuits/lib/src/configs/insecure/bfv.nr create mode 100644 circuits/lib/src/configs/insecure/mod.nr create mode 100644 circuits/lib/src/configs/insecure/trbfv.nr create mode 100644 circuits/lib/src/configs/mod.nr create mode 100644 circuits/lib/src/configs/production/bfv.nr create mode 100644 circuits/lib/src/configs/production/mod.nr create mode 100644 circuits/lib/src/configs/production/trbfv.nr create mode 100644 circuits/lib/src/core/bfv_dec.nr create mode 100644 circuits/lib/src/core/bfv_enc.nr create mode 100644 circuits/lib/src/core/bfv_pk.nr rename circuits/{crates/libs/greco/src/lib.nr => lib/src/core/greco.nr} (50%) create mode 100644 circuits/lib/src/core/mod.nr create mode 100644 circuits/lib/src/core/trbfv_dec_share.nr create mode 100644 circuits/lib/src/core/trbfv_dec_shares_agg.nr create mode 100644 circuits/lib/src/core/trbfv_pk.nr create mode 100644 circuits/lib/src/core/trbfv_pk_agg.nr create mode 100644 circuits/lib/src/core/trbfv_verify_shares.nr create mode 100644 circuits/lib/src/lib.nr create mode 100644 circuits/lib/src/math/commitments.nr rename circuits/{crates/libs/polynomial/src/lib.nr => lib/src/math/helpers.nr} (53%) create mode 100644 circuits/lib/src/math/mod.nr create mode 100644 circuits/lib/src/math/modulo/U128.nr create mode 100644 circuits/lib/src/math/modulo/mod.nr create mode 100644 circuits/lib/src/math/modulo/unconstrained_U128.nr create mode 100644 circuits/lib/src/math/polynomial.nr rename circuits/{crates/libs/safe/src/lib.nr => lib/src/math/safe.nr} (100%) diff --git a/circuits/Nargo.toml b/circuits/Nargo.toml deleted file mode 100644 index 6bb1b01d19..0000000000 --- a/circuits/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[workspace] -members = [ - "crates/libs/greco", - "crates/libs/safe/", - "crates/libs/polynomial" -] \ No newline at end of file diff --git a/circuits/bin/aggregation/Nargo.toml b/circuits/bin/aggregation/Nargo.toml new file mode 100644 index 0000000000..d07c2b2748 --- /dev/null +++ b/circuits/bin/aggregation/Nargo.toml @@ -0,0 +1,7 @@ +[workspace] +members = [ + "fold", + "pk_trbfv_wrapper", + "insecure/verify_shares_trbfv_wrapper", + "production/verify_shares_trbfv_wrapper" +] \ No newline at end of file diff --git a/circuits/bin/aggregation/fold/Nargo.toml b/circuits/bin/aggregation/fold/Nargo.toml new file mode 100644 index 0000000000..a0ca121abc --- /dev/null +++ b/circuits/bin/aggregation/fold/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "fold" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20260102", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/fold/src/main.nr b/circuits/bin/aggregation/fold/src/main.nr new file mode 100644 index 0000000000..78d01486bb --- /dev/null +++ b/circuits/bin/aggregation/fold/src/main.nr @@ -0,0 +1,19 @@ +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; +use lib::math::commitments::compute_aggregation_commitment; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; 2], + commitments: pub [Field; 2], + key_hash: Field, +) -> pub Field { + verify_honk_proof_non_zk(verification_key, proofs[0], [commitments[0]], key_hash); + verify_honk_proof_non_zk(verification_key, proofs[1], [commitments[1]], key_hash); + + let mut commitments_vec = Vec::new(); + + commitments_vec.push(commitments[0]); + commitments_vec.push(commitments[1]); + + compute_aggregation_commitment(commitments_vec) +} diff --git a/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..5dd27583c5 --- /dev/null +++ b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "verify_shares_trbfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20260102", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr new file mode 100644 index 0000000000..4055e81f9a --- /dev/null +++ b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr @@ -0,0 +1,28 @@ +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 2; +/// Number of commitments per proof. +pub global N_COMMITMENTS: u32 = 10; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + commitments: pub [[Field; N_COMMITMENTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_honk_proof_non_zk(verification_key, proofs[i], commitments[i], key_hash); + } + + let mut aggregated_commitments = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_COMMITMENTS { + aggregated_commitments.push(commitments[i][j]); + } + } + + compute_aggregation_commitment(aggregated_commitments) +} diff --git a/circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..05ad684ea8 --- /dev/null +++ b/circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "pk_trbfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20260102", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr new file mode 100644 index 0000000000..96574b1104 --- /dev/null +++ b/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr @@ -0,0 +1,28 @@ +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 1; +/// Number of commitments per proof. +pub global N_COMMITMENTS: u32 = 3; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + commitments: pub [[Field; N_COMMITMENTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_honk_proof_non_zk(verification_key, proofs[i], commitments[i], key_hash); + } + + let mut aggregated_commitments = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_COMMITMENTS { + aggregated_commitments.push(commitments[i][j]); + } + } + + compute_aggregation_commitment(aggregated_commitments) +} diff --git a/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..5dd27583c5 --- /dev/null +++ b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "verify_shares_trbfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20260102", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr new file mode 100644 index 0000000000..4d963513d4 --- /dev/null +++ b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr @@ -0,0 +1,28 @@ +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 2; +/// Number of commitments per proof. +pub global N_COMMITMENTS: u32 = 20; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + commitments: pub [[Field; N_COMMITMENTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_honk_proof_non_zk(verification_key, proofs[i], commitments[i], key_hash); + } + + let mut aggregated_commitments = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_COMMITMENTS { + aggregated_commitments.push(commitments[i][j]); + } + } + + compute_aggregation_commitment(aggregated_commitments) +} diff --git a/circuits/bin/insecure/Nargo.toml b/circuits/bin/insecure/Nargo.toml new file mode 100644 index 0000000000..c5a20cc008 --- /dev/null +++ b/circuits/bin/insecure/Nargo.toml @@ -0,0 +1,15 @@ +[workspace] +members = [ + "pk_bfv", + "pk_trbfv", + "verify_shares_trbfv_sk", + "verify_shares_trbfv_e_sm", + "enc_bfv_sk", + "enc_bfv_e_sm", + "dec_bfv_sk", + "dec_bfv_e_sm", + "pk_agg_trbfv", + "greco", + "dec_share_trbfv", + "dec_share_agg_trbfv" +] \ No newline at end of file diff --git a/circuits/bin/insecure/dec_bfv_e_sm/Nargo.toml b/circuits/bin/insecure/dec_bfv_e_sm/Nargo.toml new file mode 100644 index 0000000000..f72554aadf --- /dev/null +++ b/circuits/bin/insecure/dec_bfv_e_sm/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_bfv_e_sm" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/dec_bfv_e_sm/README.md b/circuits/bin/insecure/dec_bfv_e_sm/README.md new file mode 100644 index 0000000000..d588064a46 --- /dev/null +++ b/circuits/bin/insecure/dec_bfv_e_sm/README.md @@ -0,0 +1 @@ +insecure instantiation of dec_bfv smudging noise circuit (PVSS #4b) diff --git a/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr b/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr new file mode 100644 index 0000000000..6f1cb56626 --- /dev/null +++ b/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr @@ -0,0 +1,16 @@ +use lib::configs::insecure::bfv::{DEC_BFV_BIT_MSG_E_SM, L_TRBFV, N}; +use lib::core::bfv_dec::BfvDecCommitVerify; +use lib::math::polynomial::Polynomial; + +/// Number of honest parties. +pub global H: u32 = 5; + +fn main( + expected_commitments: [[Field; L_TRBFV]; H], + decrypted_shares: [[Polynomial; L_TRBFV]; H], +) -> pub Field { + let circuit: BfvDecCommitVerify = + BfvDecCommitVerify::new(expected_commitments, decrypted_shares); + + circuit.verify() +} diff --git a/circuits/bin/insecure/dec_bfv_sk/Nargo.toml b/circuits/bin/insecure/dec_bfv_sk/Nargo.toml new file mode 100644 index 0000000000..ad3b7f7f8c --- /dev/null +++ b/circuits/bin/insecure/dec_bfv_sk/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_bfv_sk" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/dec_bfv_sk/README.md b/circuits/bin/insecure/dec_bfv_sk/README.md new file mode 100644 index 0000000000..ea1b15e3fd --- /dev/null +++ b/circuits/bin/insecure/dec_bfv_sk/README.md @@ -0,0 +1 @@ +insecure instantiation of dec_bfv secret key circuit (PVSS #4a) diff --git a/circuits/bin/insecure/dec_bfv_sk/src/main.nr b/circuits/bin/insecure/dec_bfv_sk/src/main.nr new file mode 100644 index 0000000000..3c83cf74db --- /dev/null +++ b/circuits/bin/insecure/dec_bfv_sk/src/main.nr @@ -0,0 +1,16 @@ +use lib::configs::insecure::bfv::{DEC_BFV_BIT_MSG_SK, L_TRBFV, N}; +use lib::core::bfv_dec::BfvDecCommitVerify; +use lib::math::polynomial::Polynomial; + +/// Number of honest parties. +pub global H: u32 = 5; + +fn main( + expected_commitments: [[Field; L_TRBFV]; H], + decrypted_shares: [[Polynomial; L_TRBFV]; H], +) -> pub Field { + let circuit: BfvDecCommitVerify = + BfvDecCommitVerify::new(expected_commitments, decrypted_shares); + + circuit.verify() +} diff --git a/circuits/bin/insecure/dec_share_agg_trbfv/Nargo.toml b/circuits/bin/insecure/dec_share_agg_trbfv/Nargo.toml new file mode 100644 index 0000000000..e04a837cbc --- /dev/null +++ b/circuits/bin/insecure/dec_share_agg_trbfv/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_shares_agg_trbfv" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/dec_share_agg_trbfv/README.md b/circuits/bin/insecure/dec_share_agg_trbfv/README.md new file mode 100644 index 0000000000..597bde76e3 --- /dev/null +++ b/circuits/bin/insecure/dec_share_agg_trbfv/README.md @@ -0,0 +1 @@ +insecure instantiation of dec_shares_agg_trbfv circuit (PVSS #7) diff --git a/circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr b/circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr new file mode 100644 index 0000000000..b21cc5c599 --- /dev/null +++ b/circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr @@ -0,0 +1,27 @@ +use lib::configs::insecure::trbfv::{DEC_SHARES_AGG_BIT_NOISE, DEC_SHARES_AGG_CONFIGS, L}; +use lib::core::trbfv_dec_shares_agg::DecryptionSharesAggregation; +use lib::math::polynomial::Polynomial; + +/// Max number of non-zero coefficients in the message polynomial. +pub global MAX_MSG_NON_ZERO_COEFFS: u32 = 80; +/// Threshold. +pub global T: u32 = 2; + +fn main( + decryption_shares: [[Polynomial; L]; T + 1], + party_ids: [Field; T + 1], + message: Polynomial, + u_global: Polynomial, + crt_quotients: [Polynomial; L], +) { + let dec_share_agg: DecryptionSharesAggregation = DecryptionSharesAggregation::new( + DEC_SHARES_AGG_CONFIGS, + decryption_shares, + party_ids, + message, + u_global, + crt_quotients, + ); + + dec_share_agg.verify_no_bn(); +} diff --git a/circuits/bin/insecure/dec_share_trbfv/Nargo.toml b/circuits/bin/insecure/dec_share_trbfv/Nargo.toml new file mode 100644 index 0000000000..cc6b5f1e6b --- /dev/null +++ b/circuits/bin/insecure/dec_share_trbfv/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_share_trbfv" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/dec_share_trbfv/README.md b/circuits/bin/insecure/dec_share_trbfv/README.md new file mode 100644 index 0000000000..26c85ac8a8 --- /dev/null +++ b/circuits/bin/insecure/dec_share_trbfv/README.md @@ -0,0 +1 @@ +insecure instantiation of dec_share_trbfv circuit (PVSS #6) diff --git a/circuits/bin/insecure/dec_share_trbfv/src/main.nr b/circuits/bin/insecure/dec_share_trbfv/src/main.nr new file mode 100644 index 0000000000..8ee5883b40 --- /dev/null +++ b/circuits/bin/insecure/dec_share_trbfv/src/main.nr @@ -0,0 +1,38 @@ +use lib::configs::insecure::trbfv::{ + DEC_SHARES_BIT_CT, DEC_SHARES_BIT_D, DEC_SHARES_BIT_E, DEC_SHARES_BIT_R1, DEC_SHARES_BIT_R2, + DEC_SHARES_BIT_S, DEC_SHARES_CONFIGS, L, N, +}; +use lib::core::trbfv_dec_share::DecryptionShare; +use lib::math::polynomial::Polynomial; + +/// Number of parties. +pub global N_PARTIES: u32 = 5; +/// Threshold. +pub global T: u32 = 2; + +fn main( + expected_s_commitment: pub Field, + expected_e_commitment: pub Field, + c_0: [Polynomial; L], + c_1: [Polynomial; L], + s: [Polynomial; L], + e: [Polynomial; L], + r_1: [Polynomial<(2 * N) - 1>; L], + r_2: [Polynomial; L], + d: [Polynomial; L], +) { + let dec_share: DecryptionShare = DecryptionShare::new( + DEC_SHARES_CONFIGS, + expected_s_commitment, + expected_e_commitment, + c_0, + c_1, + s, + e, + r_1, + r_2, + d, + ); + + dec_share.verify() +} diff --git a/circuits/bin/insecure/enc_bfv_e_sm/Nargo.toml b/circuits/bin/insecure/enc_bfv_e_sm/Nargo.toml new file mode 100644 index 0000000000..f34e6c7c44 --- /dev/null +++ b/circuits/bin/insecure/enc_bfv_e_sm/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "enc_bfv_e_sm" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/enc_bfv_e_sm/README.md b/circuits/bin/insecure/enc_bfv_e_sm/README.md new file mode 100644 index 0000000000..4b06d51499 --- /dev/null +++ b/circuits/bin/insecure/enc_bfv_e_sm/README.md @@ -0,0 +1 @@ +insecure instantiation of enc_bfv smudging noise circuit (PVSS #3b) diff --git a/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr b/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr new file mode 100644 index 0000000000..2ec4f122bc --- /dev/null +++ b/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr @@ -0,0 +1,46 @@ +use lib::configs::insecure::bfv::{ + ENC_BFV_BIT_CT, ENC_BFV_BIT_E0, ENC_BFV_BIT_E1, ENC_BFV_BIT_MSG, ENC_BFV_BIT_P1, ENC_BFV_BIT_P2, + ENC_BFV_BIT_PK, ENC_BFV_BIT_R1, ENC_BFV_BIT_R2, ENC_BFV_BIT_U, ENC_BFV_CONFIGS_E_SM, L, N, +}; +use lib::core::bfv_enc::EncryptionBfv; +use lib::math::polynomial::Polynomial; + +fn main( + expected_pk_commitment: Field, + expected_message_commitment: Field, + pk0is: [Polynomial; L], + pk1is: [Polynomial; L], + ct0is: [Polynomial; L], + ct1is: [Polynomial; L], + u: Polynomial, + e0: Polynomial, + e0is: [Polynomial; L], + e0_quotients: [Polynomial; L], + e1: Polynomial, + message: Polynomial, + r1is: [Polynomial<(2 * N) - 1>; L], + r2is: [Polynomial; L], + p1is: [Polynomial<(2 * N) - 1>; L], + p2is: [Polynomial; L], +) -> pub bool { + let enc_bfv: EncryptionBfv = EncryptionBfv::new( + ENC_BFV_CONFIGS_E_SM, + expected_pk_commitment, + expected_message_commitment, + pk0is, + pk1is, + ct0is, + ct1is, + u, + e0, + e0is, + e0_quotients, + e1, + message, + r1is, + r2is, + p1is, + p2is, + ); + enc_bfv.verify() +} diff --git a/circuits/bin/insecure/enc_bfv_sk/Nargo.toml b/circuits/bin/insecure/enc_bfv_sk/Nargo.toml new file mode 100644 index 0000000000..1f980ff8c9 --- /dev/null +++ b/circuits/bin/insecure/enc_bfv_sk/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "enc_bfv_sk" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/enc_bfv_sk/README.md b/circuits/bin/insecure/enc_bfv_sk/README.md new file mode 100644 index 0000000000..f4968b795f --- /dev/null +++ b/circuits/bin/insecure/enc_bfv_sk/README.md @@ -0,0 +1 @@ +insecure instantiation of enc_bfv secret key circuit (PVSS #3a) diff --git a/circuits/bin/insecure/enc_bfv_sk/src/main.nr b/circuits/bin/insecure/enc_bfv_sk/src/main.nr new file mode 100644 index 0000000000..875eaada2c --- /dev/null +++ b/circuits/bin/insecure/enc_bfv_sk/src/main.nr @@ -0,0 +1,46 @@ +use lib::configs::insecure::bfv::{ + ENC_BFV_BIT_CT, ENC_BFV_BIT_E0, ENC_BFV_BIT_E1, ENC_BFV_BIT_MSG, ENC_BFV_BIT_P1, ENC_BFV_BIT_P2, + ENC_BFV_BIT_PK, ENC_BFV_BIT_R1, ENC_BFV_BIT_R2, ENC_BFV_BIT_U, ENC_BFV_CONFIGS_SK, L, N, +}; +use lib::core::bfv_enc::EncryptionBfv; +use lib::math::polynomial::Polynomial; + +fn main( + expected_pk_commitment: Field, + expected_message_commitment: Field, + pk0is: [Polynomial; L], + pk1is: [Polynomial; L], + ct0is: [Polynomial; L], + ct1is: [Polynomial; L], + u: Polynomial, + e0: Polynomial, + e0is: [Polynomial; L], + e0_quotients: [Polynomial; L], + e1: Polynomial, + message: Polynomial, + r1is: [Polynomial<(2 * N) - 1>; L], + r2is: [Polynomial; L], + p1is: [Polynomial<(2 * N) - 1>; L], + p2is: [Polynomial; L], +) -> pub bool { + let enc_bfv: EncryptionBfv = EncryptionBfv::new( + ENC_BFV_CONFIGS_SK, + expected_pk_commitment, + expected_message_commitment, + pk0is, + pk1is, + ct0is, + ct1is, + u, + e0, + e0is, + e0_quotients, + e1, + message, + r1is, + r2is, + p1is, + p2is, + ); + enc_bfv.verify() +} diff --git a/circuits/bin/insecure/greco/Nargo.toml b/circuits/bin/insecure/greco/Nargo.toml new file mode 100644 index 0000000000..7071850269 --- /dev/null +++ b/circuits/bin/insecure/greco/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "greco" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/greco/README.md b/circuits/bin/insecure/greco/README.md new file mode 100644 index 0000000000..abf6a0aa1c --- /dev/null +++ b/circuits/bin/insecure/greco/README.md @@ -0,0 +1 @@ +insecure instantiation of Greco circuit diff --git a/circuits/bin/insecure/greco/src/main.nr b/circuits/bin/insecure/greco/src/main.nr new file mode 100644 index 0000000000..8c46634a2e --- /dev/null +++ b/circuits/bin/insecure/greco/src/main.nr @@ -0,0 +1,45 @@ +use lib::configs::insecure::trbfv::{ + GRECO_BIT_CT, GRECO_BIT_E0, GRECO_BIT_E1, GRECO_BIT_K, GRECO_BIT_P1, GRECO_BIT_P2, GRECO_BIT_PK, + GRECO_BIT_R1, GRECO_BIT_R2, GRECO_BIT_U, GRECO_CONFIGS, L, N, +}; +use lib::core::greco::Greco; +use lib::math::polynomial::Polynomial; + +fn main( + pk_commitment: pub Field, + pk0is: [Polynomial; L], + pk1is: [Polynomial; L], + ct0is: [Polynomial; L], + ct1is: [Polynomial; L], + u: Polynomial, + e0: Polynomial, + e1: Polynomial, + e0is: [Polynomial; L], + e0_quotients: [Polynomial; L], + k1: Polynomial, + r1is: [Polynomial<(2 * N) - 1>; L], + r2is: [Polynomial; L], + p1is: [Polynomial<(2 * N) - 1>; L], + p2is: [Polynomial; L], +) { + let greco: Greco = Greco::new( + GRECO_CONFIGS, + pk_commitment, + pk0is, + pk1is, + ct0is, + ct1is, + u, + e0, + e0is, + e0_quotients, + e1, + k1, + r1is, + r2is, + p1is, + p2is, + ); + let is_greco_valid = greco.verify(); + assert(is_greco_valid); +} diff --git a/circuits/bin/insecure/pk_agg_trbfv/Nargo.toml b/circuits/bin/insecure/pk_agg_trbfv/Nargo.toml new file mode 100644 index 0000000000..5795159baa --- /dev/null +++ b/circuits/bin/insecure/pk_agg_trbfv/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "pk_agg_trbfv" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/pk_agg_trbfv/README.md b/circuits/bin/insecure/pk_agg_trbfv/README.md new file mode 100644 index 0000000000..bad797050f --- /dev/null +++ b/circuits/bin/insecure/pk_agg_trbfv/README.md @@ -0,0 +1 @@ +insecure instantiation of Threshold BFV Public Key Aggregation circuit (PVSS #5) diff --git a/circuits/bin/insecure/pk_agg_trbfv/src/main.nr b/circuits/bin/insecure/pk_agg_trbfv/src/main.nr new file mode 100644 index 0000000000..1fc67723e2 --- /dev/null +++ b/circuits/bin/insecure/pk_agg_trbfv/src/main.nr @@ -0,0 +1,25 @@ +use lib::configs::insecure::trbfv::{L, N, PK_AGG_TRBFV_BIT_PK, PK_AGG_TRBFV_CONFIGS}; +use lib::core::trbfv_pk_agg::TrbfvPublicKeyAggregation; +use lib::math::polynomial::Polynomial; + +/// Number of honest parties. +pub global H: u32 = 5; + +fn main( + expected_pk_trbfv_commitments: [Field; H], + pk0: [[Polynomial; L]; H], + pk1: [[Polynomial; L]; H], + pk0_agg: [Polynomial; L], + pk1_agg: [Polynomial; L], +) -> pub Field { + let pk_agg_trbfv: TrbfvPublicKeyAggregation = TrbfvPublicKeyAggregation::new( + PK_AGG_TRBFV_CONFIGS, + expected_pk_trbfv_commitments, + pk0, + pk1, + pk0_agg, + pk1_agg, + ); + + pk_agg_trbfv.verify() +} diff --git a/circuits/bin/insecure/pk_bfv/Nargo.toml b/circuits/bin/insecure/pk_bfv/Nargo.toml new file mode 100644 index 0000000000..acc96bf081 --- /dev/null +++ b/circuits/bin/insecure/pk_bfv/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "pk_bfv" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/pk_bfv/README.md b/circuits/bin/insecure/pk_bfv/README.md new file mode 100644 index 0000000000..63b2150c71 --- /dev/null +++ b/circuits/bin/insecure/pk_bfv/README.md @@ -0,0 +1 @@ +insecure instantiation of BFV Public Key circuit (PVSS #0) diff --git a/circuits/bin/insecure/pk_bfv/src/main.nr b/circuits/bin/insecure/pk_bfv/src/main.nr new file mode 100644 index 0000000000..6235e35eaf --- /dev/null +++ b/circuits/bin/insecure/pk_bfv/src/main.nr @@ -0,0 +1,8 @@ +use lib::configs::insecure::bfv::{L, N, PK_BFV_BIT_PK}; +use lib::core::bfv_pk::BfvPkCommit; +use lib::math::polynomial::Polynomial; + +fn main(pk0is: [Polynomial; L], pk1is: [Polynomial; L]) -> pub Field { + let pk_bfv: BfvPkCommit = BfvPkCommit::new(pk0is, pk1is); + pk_bfv.verify() +} diff --git a/circuits/bin/insecure/pk_trbfv/Nargo.toml b/circuits/bin/insecure/pk_trbfv/Nargo.toml new file mode 100644 index 0000000000..7b1bb89db4 --- /dev/null +++ b/circuits/bin/insecure/pk_trbfv/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "pk_trbfv" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/pk_trbfv/README.md b/circuits/bin/insecure/pk_trbfv/README.md new file mode 100644 index 0000000000..ea0cbce733 --- /dev/null +++ b/circuits/bin/insecure/pk_trbfv/README.md @@ -0,0 +1 @@ +insecure instantiation of Threshold BFV Public Key circuit (PVSS #1) diff --git a/circuits/bin/insecure/pk_trbfv/src/main.nr b/circuits/bin/insecure/pk_trbfv/src/main.nr new file mode 100644 index 0000000000..5bbfd3fa7a --- /dev/null +++ b/circuits/bin/insecure/pk_trbfv/src/main.nr @@ -0,0 +1,21 @@ +use lib::configs::insecure::trbfv::{ + L, N, PK_TRBFV_BIT_E_SM, PK_TRBFV_BIT_EEK, PK_TRBFV_BIT_PK, PK_TRBFV_BIT_R1, PK_TRBFV_BIT_R2, + PK_TRBFV_BIT_SK, PK_TRBFV_CONFIGS, +}; +use lib::core::trbfv_pk::TrbfvPublicKey; +use lib::math::polynomial::Polynomial; + +fn main( + a: [Polynomial; L], + eek: Polynomial, + sk: Polynomial, + e_sm: Polynomial, + r1is: [Polynomial<(2 * N) - 1>; L], + r2is: [Polynomial; L], + pk0is: [Polynomial; L], + pk1is: [Polynomial; L], +) -> pub (Field, Field, Field) { + let pk_trbfv: TrbfvPublicKey = + TrbfvPublicKey::new(PK_TRBFV_CONFIGS, a, eek, sk, e_sm, r1is, r2is, pk0is, pk1is); + pk_trbfv.verify() +} diff --git a/circuits/bin/insecure/verify_shares_trbfv_e_sm/Nargo.toml b/circuits/bin/insecure/verify_shares_trbfv_e_sm/Nargo.toml new file mode 100644 index 0000000000..bc36263a21 --- /dev/null +++ b/circuits/bin/insecure/verify_shares_trbfv_e_sm/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "verify_shares_trbfv_e_sm" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/verify_shares_trbfv_e_sm/README.md b/circuits/bin/insecure/verify_shares_trbfv_e_sm/README.md new file mode 100644 index 0000000000..05f5057209 --- /dev/null +++ b/circuits/bin/insecure/verify_shares_trbfv_e_sm/README.md @@ -0,0 +1 @@ +insecure instantiation of verify_shares_trbfv smudging noise circuit (PVSS #2b) diff --git a/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr b/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr new file mode 100644 index 0000000000..0970b9472c --- /dev/null +++ b/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr @@ -0,0 +1,27 @@ +use lib::configs::insecure::trbfv::{ + L, N, VERIFY_SHARES_BIT_SECRET_E_SM, VERIFY_SHARES_BIT_SHARE, VERIFY_SHARES_CONFIGS_E_SM, +}; +use lib::core::trbfv_verify_shares::VerifySharesEsm; +use lib::math::polynomial::Polynomial; + +/// Number of parties. +pub global N_PARTIES: u32 = 5; +/// Threshold. +pub global T: u32 = 2; + +fn main( + expected_secret_commitment: Field, + secret_e_sm: [Polynomial; L], + y: [[[Field; N_PARTIES + 1]; L]; N], + h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], +) -> pub [[Field; L]; N_PARTIES] { + let verify_shares: VerifySharesEsm = VerifySharesEsm::new( + VERIFY_SHARES_CONFIGS_E_SM, + expected_secret_commitment, + secret_e_sm, + y, + h, + ); + + verify_shares.verify() +} diff --git a/circuits/bin/insecure/verify_shares_trbfv_sk/Nargo.toml b/circuits/bin/insecure/verify_shares_trbfv_sk/Nargo.toml new file mode 100644 index 0000000000..2e37875c00 --- /dev/null +++ b/circuits/bin/insecure/verify_shares_trbfv_sk/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "verify_shares_trbfv_sk" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/insecure/verify_shares_trbfv_sk/README.md b/circuits/bin/insecure/verify_shares_trbfv_sk/README.md new file mode 100644 index 0000000000..9c701969a0 --- /dev/null +++ b/circuits/bin/insecure/verify_shares_trbfv_sk/README.md @@ -0,0 +1 @@ +insecure instantiation of verify_shares_trbfv secret key circuit (PVSS #2a) diff --git a/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr b/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr new file mode 100644 index 0000000000..ca6087adc4 --- /dev/null +++ b/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr @@ -0,0 +1,27 @@ +use lib::configs::insecure::trbfv::{ + L, N, VERIFY_SHARES_BIT_SECRET_SK, VERIFY_SHARES_BIT_SHARE, VERIFY_SHARES_CONFIGS_SK, +}; +use lib::core::trbfv_verify_shares::VerifySharesSk; +use lib::math::polynomial::Polynomial; + +/// Number of parties. +pub global N_PARTIES: u32 = 5; +/// Threshold. +pub global T: u32 = 2; + +fn main( + expected_secret_commitment: Field, + secret_sk: Polynomial, + y: [[[Field; N_PARTIES + 1]; L]; N], + h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], +) -> pub [[Field; L]; N_PARTIES] { + let verify_shares: VerifySharesSk = VerifySharesSk::new( + VERIFY_SHARES_CONFIGS_SK, + expected_secret_commitment, + secret_sk, + y, + h, + ); + + verify_shares.verify() +} diff --git a/circuits/bin/production/Nargo.toml b/circuits/bin/production/Nargo.toml new file mode 100644 index 0000000000..19670a5ae2 --- /dev/null +++ b/circuits/bin/production/Nargo.toml @@ -0,0 +1,15 @@ +[workspace] +members = [ + "pk_bfv", + "pk_trbfv", + "verify_shares_trbfv_sk", + "verify_shares_trbfv_e_sm", + "enc_bfv_sk", + "enc_bfv_e_sm", + "dec_bfv_sk", + "dec_bfv_e_sm", + "pk_agg_trbfv", + "greco", + "dec_share_trbfv", + "dec_share_agg_trbfv" +] \ No newline at end of file diff --git a/circuits/bin/production/dec_bfv_e_sm/Nargo.toml b/circuits/bin/production/dec_bfv_e_sm/Nargo.toml new file mode 100644 index 0000000000..f72554aadf --- /dev/null +++ b/circuits/bin/production/dec_bfv_e_sm/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_bfv_e_sm" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/dec_bfv_e_sm/README.md b/circuits/bin/production/dec_bfv_e_sm/README.md new file mode 100644 index 0000000000..3a9ab911a2 --- /dev/null +++ b/circuits/bin/production/dec_bfv_e_sm/README.md @@ -0,0 +1 @@ +production instantiation of dec_bfv smudging noise circuit (PVSS #4b) diff --git a/circuits/bin/production/dec_bfv_e_sm/src/main.nr b/circuits/bin/production/dec_bfv_e_sm/src/main.nr new file mode 100644 index 0000000000..72c6e7489d --- /dev/null +++ b/circuits/bin/production/dec_bfv_e_sm/src/main.nr @@ -0,0 +1,16 @@ +use lib::configs::production::bfv::{DEC_BFV_BIT_MSG_E_SM, L_TRBFV, N}; +use lib::core::bfv_dec::BfvDecCommitVerify; +use lib::math::polynomial::Polynomial; + +/// Number of honest parties. +pub global H: u32 = 5; + +fn main( + expected_commitments: [[Field; L_TRBFV]; H], + decrypted_shares: [[Polynomial; L_TRBFV]; H], +) -> pub Field { + let circuit: BfvDecCommitVerify = + BfvDecCommitVerify::new(expected_commitments, decrypted_shares); + + circuit.verify() +} diff --git a/circuits/bin/production/dec_bfv_sk/Nargo.toml b/circuits/bin/production/dec_bfv_sk/Nargo.toml new file mode 100644 index 0000000000..ad3b7f7f8c --- /dev/null +++ b/circuits/bin/production/dec_bfv_sk/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_bfv_sk" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/dec_bfv_sk/README.md b/circuits/bin/production/dec_bfv_sk/README.md new file mode 100644 index 0000000000..421887b0e8 --- /dev/null +++ b/circuits/bin/production/dec_bfv_sk/README.md @@ -0,0 +1 @@ +production instantiation of dec_bfv secret key circuit (PVSS #4a) diff --git a/circuits/bin/production/dec_bfv_sk/src/main.nr b/circuits/bin/production/dec_bfv_sk/src/main.nr new file mode 100644 index 0000000000..51d7d17b7e --- /dev/null +++ b/circuits/bin/production/dec_bfv_sk/src/main.nr @@ -0,0 +1,16 @@ +use lib::configs::production::bfv::{DEC_BFV_BIT_MSG_SK, L_TRBFV, N}; +use lib::core::bfv_dec::BfvDecCommitVerify; +use lib::math::polynomial::Polynomial; + +/// Number of honest parties. +pub global H: u32 = 5; + +fn main( + expected_commitments: [[Field; L_TRBFV]; H], + decrypted_shares: [[Polynomial; L_TRBFV]; H], +) -> pub Field { + let circuit: BfvDecCommitVerify = + BfvDecCommitVerify::new(expected_commitments, decrypted_shares); + + circuit.verify() +} diff --git a/circuits/bin/production/dec_share_agg_trbfv/Nargo.toml b/circuits/bin/production/dec_share_agg_trbfv/Nargo.toml new file mode 100644 index 0000000000..e04a837cbc --- /dev/null +++ b/circuits/bin/production/dec_share_agg_trbfv/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_shares_agg_trbfv" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/dec_share_agg_trbfv/README.md b/circuits/bin/production/dec_share_agg_trbfv/README.md new file mode 100644 index 0000000000..0e4ce4eee5 --- /dev/null +++ b/circuits/bin/production/dec_share_agg_trbfv/README.md @@ -0,0 +1 @@ +production instantiation of dec_shares_agg_trbfv circuit (PVSS #7) diff --git a/circuits/bin/production/dec_share_agg_trbfv/src/main.nr b/circuits/bin/production/dec_share_agg_trbfv/src/main.nr new file mode 100644 index 0000000000..c58005a813 --- /dev/null +++ b/circuits/bin/production/dec_share_agg_trbfv/src/main.nr @@ -0,0 +1,27 @@ +use lib::configs::production::trbfv::{DEC_SHARES_AGG_BIT_NOISE, DEC_SHARES_AGG_CONFIGS, L}; +use lib::core::trbfv_dec_shares_agg::DecryptionSharesAggregation; +use lib::math::polynomial::Polynomial; + +/// Max number of non-zero coefficients in the message polynomial. +pub global MAX_MSG_NON_ZERO_COEFFS: u32 = 80; +/// Threshold. +pub global T: u32 = 2; + +fn main( + decryption_shares: [[Polynomial; L]; T + 1], + party_ids: [Field; T + 1], + message: Polynomial, + u_global: Polynomial, + crt_quotients: [Polynomial; L], +) { + let dec_share_agg: DecryptionSharesAggregation = DecryptionSharesAggregation::new( + DEC_SHARES_AGG_CONFIGS, + decryption_shares, + party_ids, + message, + u_global, + crt_quotients, + ); + + dec_share_agg.verify(); +} diff --git a/circuits/bin/production/dec_share_trbfv/Nargo.toml b/circuits/bin/production/dec_share_trbfv/Nargo.toml new file mode 100644 index 0000000000..cc6b5f1e6b --- /dev/null +++ b/circuits/bin/production/dec_share_trbfv/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_share_trbfv" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/dec_share_trbfv/README.md b/circuits/bin/production/dec_share_trbfv/README.md new file mode 100644 index 0000000000..4c01485a79 --- /dev/null +++ b/circuits/bin/production/dec_share_trbfv/README.md @@ -0,0 +1 @@ +production instantiation of dec_share_trbfv circuit (PVSS #6) diff --git a/circuits/bin/production/dec_share_trbfv/src/main.nr b/circuits/bin/production/dec_share_trbfv/src/main.nr new file mode 100644 index 0000000000..f4d0f4efb0 --- /dev/null +++ b/circuits/bin/production/dec_share_trbfv/src/main.nr @@ -0,0 +1,38 @@ +use lib::configs::production::trbfv::{ + DEC_SHARES_BIT_CT, DEC_SHARES_BIT_D, DEC_SHARES_BIT_E, DEC_SHARES_BIT_R1, DEC_SHARES_BIT_R2, + DEC_SHARES_BIT_S, DEC_SHARES_CONFIGS, L, N, +}; +use lib::core::trbfv_dec_share::DecryptionShare; +use lib::math::polynomial::Polynomial; + +/// Number of parties. +pub global N_PARTIES: u32 = 5; +/// Threshold. +pub global T: u32 = 2; + +fn main( + expected_s_commitment: pub Field, + expected_e_commitment: pub Field, + c_0: [Polynomial; L], + c_1: [Polynomial; L], + s: [Polynomial; L], + e: [Polynomial; L], + r_1: [Polynomial<(2 * N) - 1>; L], + r_2: [Polynomial; L], + d: [Polynomial; L], +) { + let dec_share: DecryptionShare = DecryptionShare::new( + DEC_SHARES_CONFIGS, + expected_s_commitment, + expected_e_commitment, + c_0, + c_1, + s, + e, + r_1, + r_2, + d, + ); + + dec_share.verify() +} diff --git a/circuits/bin/production/enc_bfv_e_sm/Nargo.toml b/circuits/bin/production/enc_bfv_e_sm/Nargo.toml new file mode 100644 index 0000000000..f34e6c7c44 --- /dev/null +++ b/circuits/bin/production/enc_bfv_e_sm/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "enc_bfv_e_sm" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/enc_bfv_e_sm/README.md b/circuits/bin/production/enc_bfv_e_sm/README.md new file mode 100644 index 0000000000..d8035d6d1d --- /dev/null +++ b/circuits/bin/production/enc_bfv_e_sm/README.md @@ -0,0 +1 @@ +production instantiation of enc_bfv smudging noise circuit (PVSS #3b) diff --git a/circuits/bin/production/enc_bfv_e_sm/src/main.nr b/circuits/bin/production/enc_bfv_e_sm/src/main.nr new file mode 100644 index 0000000000..949e17f579 --- /dev/null +++ b/circuits/bin/production/enc_bfv_e_sm/src/main.nr @@ -0,0 +1,46 @@ +use lib::configs::production::bfv::{ + ENC_BFV_BIT_CT, ENC_BFV_BIT_E0, ENC_BFV_BIT_E1, ENC_BFV_BIT_MSG, ENC_BFV_BIT_P1, ENC_BFV_BIT_P2, + ENC_BFV_BIT_PK, ENC_BFV_BIT_R1, ENC_BFV_BIT_R2, ENC_BFV_BIT_U, ENC_BFV_CONFIGS_E_SM, L, N, +}; +use lib::core::bfv_enc::EncryptionBfv; +use lib::math::polynomial::Polynomial; + +fn main( + expected_pk_commitment: Field, + expected_message_commitment: Field, + pk0is: [Polynomial; L], + pk1is: [Polynomial; L], + ct0is: [Polynomial; L], + ct1is: [Polynomial; L], + u: Polynomial, + e0: Polynomial, + e0is: [Polynomial; L], + e0_quotients: [Polynomial; L], + e1: Polynomial, + message: Polynomial, + r1is: [Polynomial<(2 * N) - 1>; L], + r2is: [Polynomial; L], + p1is: [Polynomial<(2 * N) - 1>; L], + p2is: [Polynomial; L], +) -> pub bool { + let enc_bfv: EncryptionBfv = EncryptionBfv::new( + ENC_BFV_CONFIGS_E_SM, + expected_pk_commitment, + expected_message_commitment, + pk0is, + pk1is, + ct0is, + ct1is, + u, + e0, + e0is, + e0_quotients, + e1, + message, + r1is, + r2is, + p1is, + p2is, + ); + enc_bfv.verify() +} diff --git a/circuits/bin/production/enc_bfv_sk/Nargo.toml b/circuits/bin/production/enc_bfv_sk/Nargo.toml new file mode 100644 index 0000000000..1f980ff8c9 --- /dev/null +++ b/circuits/bin/production/enc_bfv_sk/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "enc_bfv_sk" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/enc_bfv_sk/README.md b/circuits/bin/production/enc_bfv_sk/README.md new file mode 100644 index 0000000000..39411db5ea --- /dev/null +++ b/circuits/bin/production/enc_bfv_sk/README.md @@ -0,0 +1 @@ +production instantiation of enc_bfv secret key circuit (PVSS #3a) diff --git a/circuits/bin/production/enc_bfv_sk/src/main.nr b/circuits/bin/production/enc_bfv_sk/src/main.nr new file mode 100644 index 0000000000..d43181331a --- /dev/null +++ b/circuits/bin/production/enc_bfv_sk/src/main.nr @@ -0,0 +1,46 @@ +use lib::configs::production::bfv::{ + ENC_BFV_BIT_CT, ENC_BFV_BIT_E0, ENC_BFV_BIT_E1, ENC_BFV_BIT_MSG, ENC_BFV_BIT_P1, ENC_BFV_BIT_P2, + ENC_BFV_BIT_PK, ENC_BFV_BIT_R1, ENC_BFV_BIT_R2, ENC_BFV_BIT_U, ENC_BFV_CONFIGS_SK, L, N, +}; +use lib::core::bfv_enc::EncryptionBfv; +use lib::math::polynomial::Polynomial; + +fn main( + expected_pk_commitment: Field, + expected_message_commitment: Field, + pk0is: [Polynomial; L], + pk1is: [Polynomial; L], + ct0is: [Polynomial; L], + ct1is: [Polynomial; L], + u: Polynomial, + e0: Polynomial, + e0is: [Polynomial; L], + e0_quotients: [Polynomial; L], + e1: Polynomial, + message: Polynomial, + r1is: [Polynomial<(2 * N) - 1>; L], + r2is: [Polynomial; L], + p1is: [Polynomial<(2 * N) - 1>; L], + p2is: [Polynomial; L], +) -> pub bool { + let enc_bfv: EncryptionBfv = EncryptionBfv::new( + ENC_BFV_CONFIGS_SK, + expected_pk_commitment, + expected_message_commitment, + pk0is, + pk1is, + ct0is, + ct1is, + u, + e0, + e0is, + e0_quotients, + e1, + message, + r1is, + r2is, + p1is, + p2is, + ); + enc_bfv.verify() +} diff --git a/circuits/bin/production/greco/Nargo.toml b/circuits/bin/production/greco/Nargo.toml new file mode 100644 index 0000000000..7071850269 --- /dev/null +++ b/circuits/bin/production/greco/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "greco" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/greco/README.md b/circuits/bin/production/greco/README.md new file mode 100644 index 0000000000..143d50f56a --- /dev/null +++ b/circuits/bin/production/greco/README.md @@ -0,0 +1 @@ +production instantiation of Greco circuit diff --git a/circuits/bin/production/greco/src/main.nr b/circuits/bin/production/greco/src/main.nr new file mode 100644 index 0000000000..1972c14c5d --- /dev/null +++ b/circuits/bin/production/greco/src/main.nr @@ -0,0 +1,45 @@ +use lib::configs::production::trbfv::{ + GRECO_BIT_CT, GRECO_BIT_E0, GRECO_BIT_E1, GRECO_BIT_K, GRECO_BIT_P1, GRECO_BIT_P2, GRECO_BIT_PK, + GRECO_BIT_R1, GRECO_BIT_R2, GRECO_BIT_U, GRECO_CONFIGS, L, N, +}; +use lib::core::greco::Greco; +use lib::math::polynomial::Polynomial; + +fn main( + pk_commitment: pub Field, + pk0is: [Polynomial; L], + pk1is: [Polynomial; L], + ct0is: [Polynomial; L], + ct1is: [Polynomial; L], + u: Polynomial, + e0: Polynomial, + e1: Polynomial, + e0is: [Polynomial; L], + e0_quotients: [Polynomial; L], + k1: Polynomial, + r1is: [Polynomial<(2 * N) - 1>; L], + r2is: [Polynomial; L], + p1is: [Polynomial<(2 * N) - 1>; L], + p2is: [Polynomial; L], +) { + let greco: Greco = Greco::new( + GRECO_CONFIGS, + pk_commitment, + pk0is, + pk1is, + ct0is, + ct1is, + u, + e0, + e0is, + e0_quotients, + e1, + k1, + r1is, + r2is, + p1is, + p2is, + ); + let is_greco_valid = greco.verify(); + assert(is_greco_valid); +} diff --git a/circuits/bin/production/pk_agg_trbfv/Nargo.toml b/circuits/bin/production/pk_agg_trbfv/Nargo.toml new file mode 100644 index 0000000000..4a32c89e12 --- /dev/null +++ b/circuits/bin/production/pk_agg_trbfv/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "pk_agg_trbfv" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/pk_agg_trbfv/README.md b/circuits/bin/production/pk_agg_trbfv/README.md new file mode 100644 index 0000000000..60228803e7 --- /dev/null +++ b/circuits/bin/production/pk_agg_trbfv/README.md @@ -0,0 +1 @@ +production instantiation of Threshold BFV Public Key Aggregation circuit (PVSS #5) diff --git a/circuits/bin/production/pk_agg_trbfv/src/main.nr b/circuits/bin/production/pk_agg_trbfv/src/main.nr new file mode 100644 index 0000000000..943dd3398a --- /dev/null +++ b/circuits/bin/production/pk_agg_trbfv/src/main.nr @@ -0,0 +1,25 @@ +use lib::configs::production::trbfv::{L, N, PK_AGG_TRBFV_BIT_PK, PK_AGG_TRBFV_CONFIGS}; +use lib::core::trbfv_pk_agg::TrbfvPublicKeyAggregation; +use lib::math::polynomial::Polynomial; + +/// Number of honest parties. +pub global H: u32 = 5; + +fn main( + expected_pk_trbfv_commitments: [Field; H], + pk0: [[Polynomial; L]; H], + pk1: [[Polynomial; L]; H], + pk0_agg: [Polynomial; L], + pk1_agg: [Polynomial; L], +) -> pub Field { + let pk_agg_trbfv: TrbfvPublicKeyAggregation = TrbfvPublicKeyAggregation::new( + PK_AGG_TRBFV_CONFIGS, + expected_pk_trbfv_commitments, + pk0, + pk1, + pk0_agg, + pk1_agg, + ); + + pk_agg_trbfv.verify() +} diff --git a/circuits/bin/production/pk_bfv/Nargo.toml b/circuits/bin/production/pk_bfv/Nargo.toml new file mode 100644 index 0000000000..585e8bc524 --- /dev/null +++ b/circuits/bin/production/pk_bfv/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "pk_bfv" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/pk_bfv/README.md b/circuits/bin/production/pk_bfv/README.md new file mode 100644 index 0000000000..ec8f150c68 --- /dev/null +++ b/circuits/bin/production/pk_bfv/README.md @@ -0,0 +1 @@ +production instantiation of BFV Public Key circuit (PVSS #0) diff --git a/circuits/bin/production/pk_bfv/src/main.nr b/circuits/bin/production/pk_bfv/src/main.nr new file mode 100644 index 0000000000..f43ae128df --- /dev/null +++ b/circuits/bin/production/pk_bfv/src/main.nr @@ -0,0 +1,8 @@ +use lib::configs::production::bfv::{L, N, PK_BFV_BIT_PK}; +use lib::core::bfv_pk::BfvPkCommit; +use lib::math::polynomial::Polynomial; + +fn main(pk0is: [Polynomial; L], pk1is: [Polynomial; L]) -> pub Field { + let pk_bfv: BfvPkCommit = BfvPkCommit::new(pk0is, pk1is); + pk_bfv.verify() +} diff --git a/circuits/bin/production/pk_trbfv/Nargo.toml b/circuits/bin/production/pk_trbfv/Nargo.toml new file mode 100644 index 0000000000..5c535fd218 --- /dev/null +++ b/circuits/bin/production/pk_trbfv/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "pk_trbfv" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/pk_trbfv/README.md b/circuits/bin/production/pk_trbfv/README.md new file mode 100644 index 0000000000..5c9b5aa307 --- /dev/null +++ b/circuits/bin/production/pk_trbfv/README.md @@ -0,0 +1 @@ +production instantiation of Threshold BFV Public Key circuit (PVSS #1) diff --git a/circuits/bin/production/pk_trbfv/src/main.nr b/circuits/bin/production/pk_trbfv/src/main.nr new file mode 100644 index 0000000000..94b609cfaf --- /dev/null +++ b/circuits/bin/production/pk_trbfv/src/main.nr @@ -0,0 +1,21 @@ +use lib::configs::production::trbfv::{ + L, N, PK_TRBFV_BIT_E_SM, PK_TRBFV_BIT_EEK, PK_TRBFV_BIT_PK, PK_TRBFV_BIT_R1, PK_TRBFV_BIT_R2, + PK_TRBFV_BIT_SK, PK_TRBFV_CONFIGS, +}; +use lib::core::trbfv_pk::TrbfvPublicKey; +use lib::math::polynomial::Polynomial; + +fn main( + a: [Polynomial; L], + eek: Polynomial, + sk: Polynomial, + e_sm: Polynomial, + r1is: [Polynomial<(2 * N) - 1>; L], + r2is: [Polynomial; L], + pk0is: [Polynomial; L], + pk1is: [Polynomial; L], +) -> pub (Field, Field, Field) { + let pk_trbfv: TrbfvPublicKey = + TrbfvPublicKey::new(PK_TRBFV_CONFIGS, a, eek, sk, e_sm, r1is, r2is, pk0is, pk1is); + pk_trbfv.verify() +} diff --git a/circuits/bin/production/verify_shares_trbfv_e_sm/Nargo.toml b/circuits/bin/production/verify_shares_trbfv_e_sm/Nargo.toml new file mode 100644 index 0000000000..bc36263a21 --- /dev/null +++ b/circuits/bin/production/verify_shares_trbfv_e_sm/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "verify_shares_trbfv_e_sm" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/verify_shares_trbfv_e_sm/README.md b/circuits/bin/production/verify_shares_trbfv_e_sm/README.md new file mode 100644 index 0000000000..623089cec7 --- /dev/null +++ b/circuits/bin/production/verify_shares_trbfv_e_sm/README.md @@ -0,0 +1 @@ +production instantiation of verify_shares_trbfv smudging noise circuit (PVSS #2b) diff --git a/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr b/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr new file mode 100644 index 0000000000..3856fd82a9 --- /dev/null +++ b/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr @@ -0,0 +1,27 @@ +use lib::configs::production::trbfv::{ + L, N, VERIFY_SHARES_BIT_SECRET_E_SM, VERIFY_SHARES_BIT_SHARE, VERIFY_SHARES_CONFIGS_E_SM, +}; +use lib::core::trbfv_verify_shares::VerifySharesEsm; +use lib::math::polynomial::Polynomial; + +/// Number of parties. +pub global N_PARTIES: u32 = 5; +/// Threshold. +pub global T: u32 = 2; + +fn main( + expected_secret_commitment: Field, + secret_e_sm: [Polynomial; L], + y: [[[Field; N_PARTIES + 1]; L]; N], + h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], +) -> pub [[Field; L]; N_PARTIES] { + let verify_shares: VerifySharesEsm = VerifySharesEsm::new( + VERIFY_SHARES_CONFIGS_E_SM, + expected_secret_commitment, + secret_e_sm, + y, + h, + ); + + verify_shares.verify() +} diff --git a/circuits/bin/production/verify_shares_trbfv_sk/Nargo.toml b/circuits/bin/production/verify_shares_trbfv_sk/Nargo.toml new file mode 100644 index 0000000000..2e37875c00 --- /dev/null +++ b/circuits/bin/production/verify_shares_trbfv_sk/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "verify_shares_trbfv_sk" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + + +[dependencies] +lib = { path = "../../../lib" } diff --git a/circuits/bin/production/verify_shares_trbfv_sk/README.md b/circuits/bin/production/verify_shares_trbfv_sk/README.md new file mode 100644 index 0000000000..bae81c6647 --- /dev/null +++ b/circuits/bin/production/verify_shares_trbfv_sk/README.md @@ -0,0 +1 @@ +production instantiation of verify_shares_trbfv secret key circuit (PVSS #2a) diff --git a/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr b/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr new file mode 100644 index 0000000000..fe48b206df --- /dev/null +++ b/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr @@ -0,0 +1,27 @@ +use lib::configs::production::trbfv::{ + L, N, VERIFY_SHARES_BIT_SECRET_SK, VERIFY_SHARES_BIT_SHARE, VERIFY_SHARES_CONFIGS_SK, +}; +use lib::core::trbfv_verify_shares::VerifySharesSk; +use lib::math::polynomial::Polynomial; + +/// Number of parties. +pub global N_PARTIES: u32 = 5; +/// Threshold. +pub global T: u32 = 2; + +fn main( + expected_secret_commitment: Field, + secret_sk: Polynomial, + y: [[[Field; N_PARTIES + 1]; L]; N], + h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], +) -> pub [[Field; L]; N_PARTIES] { + let verify_shares: VerifySharesSk = VerifySharesSk::new( + VERIFY_SHARES_CONFIGS_SK, + expected_secret_commitment, + secret_sk, + y, + h, + ); + + verify_shares.verify() +} diff --git a/circuits/crates/libs/greco/Nargo.toml b/circuits/crates/libs/greco/Nargo.toml deleted file mode 100644 index 49514b693a..0000000000 --- a/circuits/crates/libs/greco/Nargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "greco" -version = "0.1.0" -type = "lib" -authors = ["Gnosis Guild"] -license = "MIT" - -[dependencies] -poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } -polynomial = { path = "../polynomial" } -safe = { path = "../safe" } \ No newline at end of file diff --git a/circuits/crates/libs/greco/README.md b/circuits/crates/libs/greco/README.md deleted file mode 100644 index 935d887e85..0000000000 --- a/circuits/crates/libs/greco/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# Greco - -This package contains a zero-knowledge proof circuit in Noir for verifying the correct formation of -ciphertexts resulting from BFV (Brakerski-Fan-Vercauteren) public key encryption. - -- Proves correct ciphertext formation without revealing secrets -- Implements the Brakerski-Fan-Vercauteren homomorphic encryption scheme -- Supports multiple Chinese Remainder Theorem (CRT) bases for efficient computation -- Comprehensive bounds validation for all polynomial coefficients -- Uses the Fiat-Shamir heuristic for non-interactive proof generation -- Leverages polynomial identity testing for efficient verification - -## Overview - -The Greco circuit verifies that ciphertext components `(ct0, ct1)` are correctly computed from -public key components `(pk0, pk1)` and encryption randomness. The circuit enforces: - -1. **Range Constraints**: All polynomial coefficients must be within expected bounds -2. **Encryption Equations**: - - `ct0i(γ) = pk0i(γ) * u(γ) + e0(γ) + k1(γ) * k0i + r1i(γ) * qi + r2i(γ) * cyclo(γ)` - - `ct1i(γ) = pk1i(γ) * u(γ) + e1(γ) + p1i(γ) * qi + p2i(γ) * cyclo(γ)` - -Where `cyclo(γ) = γ^N + 1` is the cyclotomic polynomial. - -## Installation - -In your _Nargo.toml_ file, add this library as a dependency: - -```toml -[dependencies] -greco = { tag = "v0.1.5", git = "https://github.com/gnosisguild/enclave", directory = "packages/circuits/crates/libs/greco"} -``` - -nb. the `tag` corresponds to the latest tag release of Enclave (`v0.1.5`). From `v0.1.6` you should -remove `packages/` from `directory` field (ie., `circuits/crates/...`). - -## API Reference - -### Core Structures - -#### `Params` - -Complete parameters combining cryptographic and bound parameters. - -#### `CryptographicParams` - -Contains core mathematical constants: - -- `q_mod_t`: Plaintext modulus -- `qis`: CRT moduli for each basis -- `k0is`: Scaling factors for each basis - -#### `BoundParams` - -Contains all bounds for range checking: - -- `pk_bounds`: Public key polynomial bounds -- `e_bound`: Error polynomial bound -- `u_bound`: Secret polynomial bound -- `r1_low_bounds`, `r1_up_bounds`: Modulus switching bounds -- `r2_bounds`: Cyclotomic reduction bounds -- `p1_bounds`, `p2_bounds`: Additional randomness bounds -- `k1_low_bound`, `k1_up_bound`: Scaled message bounds - -#### `Greco` - -Main circuit structure implementing the zero-knowledge proof. - -### Key Methods - -- `new()`: Creates a new Greco circuit instance -- `verify_correct_ciphertext_encryption()`: Performs the complete verification -- `check_range_bounds()`: Validates all coefficient bounds -- `generate_challenge()`: Generates Fiat-Shamir challenges -- `check_encryption_constraints()`: Verifies encryption equations - -## Generic Parameters - -- `N`: Polynomial degree (ring dimension) -- `L`: Number of CRT bases - -## Disclaimer - -This circuit is a port of the Halo2 implementation from the Greco paper authors at PSE. The original -Halo2 implementation is available at -[https://github.com/privacy-scaling-explorations/greco](https://github.com/privacy-scaling-explorations/greco). -We extend our gratitude for their groundbreaking work on zero-knowledge proofs for BFV encryption -correctness, detailed in their [research paper](https://eprint.iacr.org/2024/594). - -## Compatibility - -This has been developed and tested with - -```bash -nargo --version -nargo version = 1.0.0-beta.15 -noirc version = 1.0.0-beta.15+83245db91dcf63420ef4bcbbd85b98f397fee663 -(git version hash: 83245db91dcf63420ef4bcbbd85b98f397fee663, is dirty: false) -``` - -```bash -bb --version -3.0.0-nightly.20251104 -``` diff --git a/circuits/crates/libs/polynomial/Nargo.toml b/circuits/crates/libs/polynomial/Nargo.toml deleted file mode 100644 index e5d25f96f3..0000000000 --- a/circuits/crates/libs/polynomial/Nargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "polynomial" -version = "0.1.0" -type = "lib" -authors = ["Gnosis Guild"] -license = "MIT" - -[dependencies] diff --git a/circuits/crates/libs/polynomial/README.md b/circuits/crates/libs/polynomial/README.md deleted file mode 100644 index e472488514..0000000000 --- a/circuits/crates/libs/polynomial/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Polynomial Noir Library - -This package contains a custom polynomial structure object and evaluation functions for use in -zero-knowledge circuits. - -- Efficient polynomial evaluation using Horner's method -- Cryptographic range checking for polynomial coefficients with symmetric and asymmetric bounds - -## Installation - -In your _Nargo.toml_ file, add this library as a dependency: - -```toml -[dependencies] -polynomial = { tag = "v0.1.5", git = "https://github.com/gnosisguild/enclave", directory = "packages/circuits/crates/libs/polynomial"} -``` - -nb. the `tag` corresponds to the latest tag release of Enclave (`v0.1.5`). From `v0.1.6` you should -remove `packages/` from `directory` field (ie., `circuits/crates/...`). - -### Compatibility - -This has been developed and tested with - -```bash -nargo --version -nargo version = 1.0.0-beta.15 -noirc version = 1.0.0-beta.15+83245db91dcf63420ef4bcbbd85b98f397fee663 -(git version hash: 83245db91dcf63420ef4bcbbd85b98f397fee663, is dirty: false) -``` - -```bash -bb --version -3.0.0-nightly.20251104 -``` diff --git a/circuits/crates/libs/safe/README.md b/circuits/crates/libs/safe/README.md deleted file mode 100644 index bdd2d695ca..0000000000 --- a/circuits/crates/libs/safe/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# SAFE (Sponge API for Field Elements) Noir Library - -This package contains a complete implementation of the SAFE API in Noir as defined in the -specification -[SAFE (Sponge API for Field Elements) - A Toolbox for ZK Hash Applications](https://hackmd.io/bHgsH6mMStCVibM_wYvb2w#22-Sponge-state). -SAFE provides a unified interface for cryptographic sponge functions that can be instantiated with -various permutations to create hash functions, MACs, authenticated encryption schemes, and other -cryptographic primitives for ZK proof systems. - -- START, ABSORB, SQUEEZE, FINISH operations following spec 2.4 -- Domain separation, tag computation, IO pattern validation -- Field-friendly permutation for ZK systems -- All operations follow SAFE spec 2.4 exactly -- Variable-length inputs, automatic length detection from IO patterns -- Automatic validation of operation sequences against expected patterns -- Cross-protocol security through configurable domain separators - -## Installation - -In your _Nargo.toml_ file, add this library as a dependency: - -```toml -[dependencies] -safe = { tag = "v0.1.5", git = "https://github.com/gnosisguild/enclave", directory = "packages/circuits/crates/libs/safe"} -``` - -nb. the `tag` corresponds to the latest tag release of Enclave (`v0.1.5`). From `v0.1.6` you should -remove `packages/` from `directory` field (ie., `circuits/crates/...`). - -## API Reference - -### SafeSponge - -The main sponge structure that implements the SAFE API. - -#### Methods - -- `start(io_pattern: [u32; L], domain_separator: [u8; 64]) -> SafeSponge`: Initializes a new SAFE - sponge instance with the given IO pattern and domain separator - -- `absorb(&mut self, input: [Field])`: Absorbs field elements into the sponge state, automatically - validating against the IO pattern - -- `squeeze(&mut self) -> Vec`: Extracts field elements from the sponge state according to the - IO pattern - -- `finish(&mut self)`: Finalizes the sponge instance, verifying all operations and clearing internal - state - -### IO Pattern Encoding - -IO patterns are encoded as 32-bit words where: - -- MSB = 1 for ABSORB operations -- MSB = 0 for SQUEEZE operations -- Lower 31 bits specify the number of field elements - -Examples: - -- `0x80000003` = ABSORB(3) -- `0x00000001` = SQUEEZE(1) -- `0x80000000` = ABSORB(0) - -### Domain Separation - -Each sponge instance requires a 64-byte domain separator for cross-protocol security. Different -domain separators ensure that distinct applications behave like distinct functions. - -## Compatibility - -This has been developed and tested with - -```bash -nargo --version -nargo version = 1.0.0-beta.15 -noirc version = 1.0.0-beta.15+83245db91dcf63420ef4bcbbd85b98f397fee663 -(git version hash: 83245db91dcf63420ef4bcbbd85b98f397fee663, is dirty: false) -``` - -```bash -bb --version -3.0.0-nightly.20251104 -``` diff --git a/circuits/crates/libs/safe/Nargo.toml b/circuits/lib/Nargo.toml similarity index 51% rename from circuits/crates/libs/safe/Nargo.toml rename to circuits/lib/Nargo.toml index cdb3f5a856..9bc2479aea 100644 --- a/circuits/crates/libs/safe/Nargo.toml +++ b/circuits/lib/Nargo.toml @@ -1,10 +1,10 @@ [package] -name = "safe" -version = "0.1.0" +name = "lib" type = "lib" -authors = ["Gnosis Guild"] -license = "MIT" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" [dependencies] poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } -keccak256 = { tag = "v0.1.1", git = "https://github.com/noir-lang/keccak256" } \ No newline at end of file +keccak256 = { tag = "v0.1.1", git = "https://github.com/noir-lang/keccak256" } +bignum = { tag = "v0.0.2", git = "https://github.com/gnosisguild/noir-bignum" } \ No newline at end of file diff --git a/circuits/lib/src/configs/insecure/bfv.nr b/circuits/lib/src/configs/insecure/bfv.nr new file mode 100644 index 0000000000..2cf123d718 --- /dev/null +++ b/circuits/lib/src/configs/insecure/bfv.nr @@ -0,0 +1,114 @@ +use crate::core::bfv_enc::Configs as BfvEncConfigs; + +// Global configs for BFV Decryption circuit +pub global N: u32 = 512; +pub global L_TRBFV: u32 = 2; +pub global L_PRIME: u32 = 1; +pub global QIS: [Field; L_PRIME] = [2251799813554177]; +pub global TRBFV_QIS: [Field; L_TRBFV] = [68719403009, 68719230977]; +pub global L: u32 = 1; +pub global Q_MOD_T: Field = 1082658244788225; +pub global BFV_Q_INVERSE_MOD_T: Field = 39210117854; +pub global BFV_PLAINTEXT_MODULUS: Field = 68719403009; + +/************************************ +------------------------------------- +pk_bfv (CIRCUIT 0 - PUBLIC KEY BFV) +------------------------------------- +************************************/ + +// pk_bfv - bit parameters +pub global PK_BFV_BIT_PK: u32 = 51; + +/************************************ +------------------------------------- +enc_bfv (CIRCUIT 3a - BFV ENCRYPTION SK) +------------------------------------- +************************************/ + +// enc_bfv - bit parameters +pub global ENC_BFV_BIT_PK: u32 = 51; +pub global ENC_BFV_BIT_CT: u32 = 51; +pub global ENC_BFV_BIT_U: u32 = 2; +pub global ENC_BFV_BIT_E0: u32 = 4; +pub global ENC_BFV_BIT_E1: u32 = 4; +pub global ENC_BFV_BIT_MSG: u32 = 37; +pub global ENC_BFV_BIT_R1: u32 = 36; +pub global ENC_BFV_BIT_R2: u32 = 51; +pub global ENC_BFV_BIT_P1: u32 = 10; +pub global ENC_BFV_BIT_P2: u32 = 51; + +// enc_bfv - bounds +pub global ENC_BFV_T: Field = 68719403009; +pub global ENC_BFV_Q_MOD_T: Field = 2415755265; +pub global ENC_BFV_K0IS: [Field; L] = [1284838520228573]; +pub global ENC_BFV_PK_BOUNDS: [Field; L] = [1125899906777088]; +pub global ENC_BFV_E0_BOUND: Field = 6; +pub global ENC_BFV_E1_BOUND: Field = 6; +pub global ENC_BFV_U_BOUND: Field = 1; +pub global ENC_BFV_R1_LOW_BOUNDS: [Field; L] = [19605059183]; +pub global ENC_BFV_R1_UP_BOUNDS: [Field; L] = [19605059183]; +pub global ENC_BFV_R2_BOUNDS: [Field; L] = [1125899906777088]; +pub global ENC_BFV_P1_BOUNDS: [Field; L] = [256]; +pub global ENC_BFV_P2_BOUNDS: [Field; L] = [1125899906777088]; +pub global ENC_BFV_MSG_BOUND: Field = 68719403008; + +// enc_bfv - configs +pub global ENC_BFV_CONFIGS_SK: BfvEncConfigs = BfvEncConfigs::new( + ENC_BFV_T, + ENC_BFV_Q_MOD_T, + QIS, + ENC_BFV_K0IS, + ENC_BFV_PK_BOUNDS, + ENC_BFV_E0_BOUND, + ENC_BFV_E1_BOUND, + ENC_BFV_U_BOUND, + ENC_BFV_R1_LOW_BOUNDS, + ENC_BFV_R1_UP_BOUNDS, + ENC_BFV_R2_BOUNDS, + ENC_BFV_P1_BOUNDS, + ENC_BFV_P2_BOUNDS, + ENC_BFV_MSG_BOUND, +); + +/************************************ +------------------------------------- +enc_bfv (CIRCUIT 3b - BFV ENCRYPTION E_SM) +------------------------------------- +************************************/ + +// enc_bfv E_SM uses the same bit parameters and bounds as SK +pub global ENC_BFV_CONFIGS_E_SM: BfvEncConfigs = BfvEncConfigs::new( + ENC_BFV_T, + ENC_BFV_Q_MOD_T, + QIS, + ENC_BFV_K0IS, + ENC_BFV_PK_BOUNDS, + ENC_BFV_E0_BOUND, + ENC_BFV_E1_BOUND, + ENC_BFV_U_BOUND, + ENC_BFV_R1_LOW_BOUNDS, + ENC_BFV_R1_UP_BOUNDS, + ENC_BFV_R2_BOUNDS, + ENC_BFV_P1_BOUNDS, + ENC_BFV_P2_BOUNDS, + ENC_BFV_MSG_BOUND, +); + +/************************************ +------------------------------------- +dec_bfv (CIRCUIT 4a - BFV DECRYPTION SK) +------------------------------------- +************************************/ + +// dec_bfv - bit parameters +pub global DEC_BFV_BIT_MSG_SK: u32 = 37; + +/************************************ +------------------------------------- +dec_bfv (CIRCUIT 4b - BFV DECRYPTION E_SM) +------------------------------------- +************************************/ + +// dec_bfv - bit parameters +pub global DEC_BFV_BIT_MSG_E_SM: u32 = 37; diff --git a/circuits/lib/src/configs/insecure/mod.nr b/circuits/lib/src/configs/insecure/mod.nr new file mode 100644 index 0000000000..0b3b884634 --- /dev/null +++ b/circuits/lib/src/configs/insecure/mod.nr @@ -0,0 +1,2 @@ +pub mod bfv; +pub mod trbfv; diff --git a/circuits/lib/src/configs/insecure/trbfv.nr b/circuits/lib/src/configs/insecure/trbfv.nr new file mode 100644 index 0000000000..77fc02e3b9 --- /dev/null +++ b/circuits/lib/src/configs/insecure/trbfv.nr @@ -0,0 +1,175 @@ +use crate::core::greco::Configs as GrecoConfigs; +use crate::core::trbfv_dec_share::Configs as DecShareTrBfvConfigs; +use crate::core::trbfv_dec_shares_agg::Configs as DecShareAggTrBfvConfigs; +use crate::core::trbfv_pk::Configs as TrbfvPkConfigs; +use crate::core::trbfv_pk_agg::Configs as PkAggTrBfvConfigs; +use crate::core::trbfv_verify_shares::Configs as VerifySharesConfigs; + +// Global configs for BFV parameter set +pub global N: u32 = 512; +pub global L: u32 = 2; +pub global PLAINTEXT_MODULUS: Field = 10; +pub global QIS: [Field; L] = [68719403009, 68719230977]; +pub global Q_MOD_T_MOD_P: Field = 3; +pub global Q_MOD_T: Field = 3; +pub global Q_INVERSE_MOD_T: Field = 7; +pub global T_INV_MOD_Q: Field = 1416703358393105942938; + +/************************************ +------------------------------------- +pk_trbfv (CIRCUIT 1 - PUBLIC KEY THRESHOLD BFV) +------------------------------------- +************************************/ + +// pk_trbfv - bit parameters +pub global PK_TRBFV_BIT_EEK: u32 = 6; +pub global PK_TRBFV_BIT_SK: u32 = 2; +pub global PK_TRBFV_BIT_E_SM: u32 = 18; +pub global PK_TRBFV_BIT_R1: u32 = 14; +pub global PK_TRBFV_BIT_R2: u32 = 36; +pub global PK_TRBFV_BIT_PK: u32 = 36; + +// pk_trbfv - bounds +pub global PK_TRBFV_EEK_BOUND: Field = 20; +pub global PK_TRBFV_SK_BOUND: Field = 1; +pub global PK_TRBFV_E_SM_BOUND: Field = 122892; +pub global PK_TRBFV_R1_BOUNDS: [Field; L] = [5120, 5120]; +pub global PK_TRBFV_R2_BOUNDS: [Field; L] = [34359701504, 34359615488]; + +// pk_trbfv - configs +pub global PK_TRBFV_CONFIGS: TrbfvPkConfigs = TrbfvPkConfigs::new( + QIS, + PK_TRBFV_EEK_BOUND, + PK_TRBFV_SK_BOUND, + PK_TRBFV_E_SM_BOUND, + PK_TRBFV_R1_BOUNDS, + PK_TRBFV_R2_BOUNDS, +); + +/************************************ +------------------------------------- +verify_shares (CIRCUIT 2a - VERIFY SHARES SK) +------------------------------------- +************************************/ + +// verify_shares - bit parameters +pub global VERIFY_SHARES_BIT_SHARE: u32 = 37; +pub global VERIFY_SHARES_BIT_SECRET_SK: u32 = 2; + +// verify_shares - configs +pub global VERIFY_SHARES_CONFIGS_SK: VerifySharesConfigs = VerifySharesConfigs::new(QIS); + +/************************************ +------------------------------------- +verify_shares (CIRCUIT 2b - VERIFY SHARES E_SM) +------------------------------------- +************************************/ + +// verify_shares - bit parameters +pub global VERIFY_SHARES_BIT_SECRET_E_SM: u32 = 18; + +// verify_shares - configs +pub global VERIFY_SHARES_CONFIGS_E_SM: VerifySharesConfigs = VerifySharesConfigs::new(QIS); + +/************************************ +------------------------------------- +pk_agg_trbfv (CIRCUIT 5 - PUBLIC KEY AGGREGATION TRBFV) +------------------------------------- +************************************/ + +// pk_agg_trbfv - bit parameters +pub global PK_AGG_TRBFV_BIT_PK: u32 = 36; + +// pk_agg_trbfv - configs +pub global PK_AGG_TRBFV_CONFIGS: PkAggTrBfvConfigs = PkAggTrBfvConfigs::new(QIS); + +/************************************ +------------------------------------- +greco (USED FOR ENCRYPTION TRBFV x PVSS) +------------------------------------- +************************************/ + +// greco - bit parameters +pub global GRECO_BIT_PK: u32 = 36; +pub global GRECO_BIT_CT: u32 = 36; +pub global GRECO_BIT_U: u32 = 2; +pub global GRECO_BIT_E0: u32 = 6; +pub global GRECO_BIT_E1: u32 = 6; +pub global GRECO_BIT_K: u32 = 4; +pub global GRECO_BIT_R1: u32 = 10; +pub global GRECO_BIT_R2: u32 = 36; +pub global GRECO_BIT_P1: u32 = 10; +pub global GRECO_BIT_P2: u32 = 36; + +// greco - bounds +pub global GRECO_Q_MOD_T: Field = 3; +pub global GRECO_K0IS: [Field; L] = [61847462708, 20615769293]; +pub global GRECO_PK_BOUNDS: [Field; L] = [34359701504, 34359615488]; +pub global GRECO_E0_BOUND: Field = 20; +pub global GRECO_E1_BOUND: Field = 20; +pub global GRECO_U_BOUND: Field = 1; +pub global GRECO_K1_LOW_BOUND: Field = 5; +pub global GRECO_K1_UP_BOUND: Field = 4; +pub global GRECO_R1_LOW_BOUNDS: [Field; L] = [261, 258]; +pub global GRECO_R1_UP_BOUNDS: [Field; L] = [260, 258]; +pub global GRECO_R2_BOUNDS: [Field; L] = [34359701504, 34359615488]; +pub global GRECO_P1_BOUNDS: [Field; L] = [256, 256]; +pub global GRECO_P2_BOUNDS: [Field; L] = [34359701504, 34359615488]; + +// greco - configs +pub global GRECO_CONFIGS: GrecoConfigs = GrecoConfigs::new( + GRECO_Q_MOD_T, + QIS, + GRECO_K0IS, + GRECO_PK_BOUNDS, + GRECO_E0_BOUND, + GRECO_E1_BOUND, + GRECO_U_BOUND, + GRECO_R1_LOW_BOUNDS, + GRECO_R1_UP_BOUNDS, + GRECO_R2_BOUNDS, + GRECO_P1_BOUNDS, + GRECO_P2_BOUNDS, + GRECO_K1_LOW_BOUND, + GRECO_K1_UP_BOUND, +); + +/************************************ +------------------------------------- +dec_share_trbfv (CIRCUIT 6 - DECRYPTION SHARE TRBFV) +------------------------------------- +************************************/ + +// dec_share_trbfv - bit parameters +pub global DEC_SHARES_BIT_CT: u32 = 36; +pub global DEC_SHARES_BIT_S: u32 = 36; +pub global DEC_SHARES_BIT_E: u32 = 36; +pub global DEC_SHARES_BIT_R1: u32 = 44; +pub global DEC_SHARES_BIT_R2: u32 = 36; +pub global DEC_SHARES_BIT_D: u32 = 36; + +// dec_share_trbfv - bounds +pub global DEC_SHARES_DECRYPTION_SHARE_BOUND: Field = 34359701504; +pub global DEC_SHARES_R1_BOUNDS: [Field; L] = [8796083584897, 8796061564801]; +pub global DEC_SHARES_R2_BOUNDS: [Field; L] = [34359701504, 34359615488]; + +// dec_share_trbfv - configs +pub global DEC_SHARES_CONFIGS: DecShareTrBfvConfigs = DecShareTrBfvConfigs::new( + QIS, + DEC_SHARES_DECRYPTION_SHARE_BOUND, + DEC_SHARES_R1_BOUNDS, + DEC_SHARES_R2_BOUNDS, +); + +/************************************ +------------------------------------- +dec_share_agg_trbfv (CIRCUIT 7 - DECRYPTION SHARE AGGREGATION TRBFV) +------------------------------------- +************************************/ + +// dec_share_agg_trbfv - bit parameters +pub global DEC_SHARES_AGG_BIT_NOISE: u32 = 69; + +// dec_share_agg_trbfv - configs +pub global DEC_SHARES_AGG_CONFIGS: DecShareAggTrBfvConfigs = + DecShareAggTrBfvConfigs::new(QIS, PLAINTEXT_MODULUS, Q_INVERSE_MOD_T); diff --git a/circuits/lib/src/configs/mod.nr b/circuits/lib/src/configs/mod.nr new file mode 100644 index 0000000000..7c39344de7 --- /dev/null +++ b/circuits/lib/src/configs/mod.nr @@ -0,0 +1,2 @@ +pub mod insecure; +pub mod production; diff --git a/circuits/lib/src/configs/production/bfv.nr b/circuits/lib/src/configs/production/bfv.nr new file mode 100644 index 0000000000..b0524b292a --- /dev/null +++ b/circuits/lib/src/configs/production/bfv.nr @@ -0,0 +1,117 @@ +use crate::core::bfv_enc::Configs as BfvEncConfigs; + +// Global configs for BFV parameter set +pub global N: u32 = 8192; +pub global L_TRBFV: u32 = 4; +pub global L_PRIME: u32 = 2; +pub global L: u32 = 2; +pub global QIS: [Field; L] = [72057594082099201, 72057594062438401]; +pub global TRBFV_QIS: [Field; L_TRBFV] = + [2251799822204929, 4503599627763713, 4503599631433729, 4503599634579457]; +pub global Q_MOD_T: Field = 1082658244788225; +pub global PLAINTEXT_MODULUS: Field = 18014398509481984; +pub global Q_INVERSE_MOD_T: Field = 3634521516277761; +pub global T_INVERSE_MOD_Q: Field = 4144717358717138174408418870545186; + +/************************************ +------------------------------------- +pk_bfv (CIRCUIT 0 - PUBLIC KEY BFV) +------------------------------------- +************************************/ + +// pk_bfv - bit parameters + +pub global PK_BFV_BIT_PK: u32 = 57; + +/************************************ +------------------------------------- +enc_bfv (CIRCUIT 3a - BFV ENCRYPTION SK) +------------------------------------- +************************************/ + +// enc_bfv - bit parameters +pub global ENC_BFV_BIT_PK: u32 = 57; +pub global ENC_BFV_BIT_CT: u32 = 57; +pub global ENC_BFV_BIT_U: u32 = 2; +pub global ENC_BFV_BIT_E0: u32 = 6; +pub global ENC_BFV_BIT_E1: u32 = 6; +pub global ENC_BFV_BIT_MSG: u32 = 55; +pub global ENC_BFV_BIT_R1: u32 = 54; +pub global ENC_BFV_BIT_R2: u32 = 57; +pub global ENC_BFV_BIT_P1: u32 = 14; +pub global ENC_BFV_BIT_P2: u32 = 57; + +// enc_bfv - bounds +pub global ENC_BFV_T: Field = 18014398509481984; +pub global ENC_BFV_Q_MOD_T: Field = 1082658244788225; +pub global ENC_BFV_K0IS: [Field; L] = [70854796903366627, 47439047573780733]; +pub global ENC_BFV_PK_BOUNDS: [Field; L] = [36028797041049600, 36028797031219200]; +pub global ENC_BFV_E0_BOUND: Field = 20; +pub global ENC_BFV_E1_BOUND: Field = 20; +pub global ENC_BFV_U_BOUND: Field = 1; +pub global ENC_BFV_R1_LOW_BOUNDS: [Field; L] = [8856849607495681, 5929880944709633]; +pub global ENC_BFV_R1_UP_BOUNDS: [Field; L] = [8856849607495680, 5929880944709632]; +pub global ENC_BFV_R2_BOUNDS: [Field; L] = [36028797041049600, 36028797031219200]; +pub global ENC_BFV_P1_BOUNDS: [Field; L] = [4096, 4096]; +pub global ENC_BFV_P2_BOUNDS: [Field; L] = [36028797041049600, 36028797031219200]; +pub global ENC_BFV_MSG_BOUND: Field = 18014398509481983; + +// enc_bfv - configs +pub global ENC_BFV_CONFIGS_SK: BfvEncConfigs = BfvEncConfigs::new( + ENC_BFV_T, + ENC_BFV_Q_MOD_T, + QIS, + ENC_BFV_K0IS, + ENC_BFV_PK_BOUNDS, + ENC_BFV_E0_BOUND, + ENC_BFV_E1_BOUND, + ENC_BFV_U_BOUND, + ENC_BFV_R1_LOW_BOUNDS, + ENC_BFV_R1_UP_BOUNDS, + ENC_BFV_R2_BOUNDS, + ENC_BFV_P1_BOUNDS, + ENC_BFV_P2_BOUNDS, + ENC_BFV_MSG_BOUND, +); + +/************************************ +------------------------------------- +enc_bfv (CIRCUIT 3b - BFV ENCRYPTION E_SM) +------------------------------------- +************************************/ + +// enc_bfv E_SM uses the same bit parameters and bounds as SK +pub global ENC_BFV_CONFIGS_E_SM: BfvEncConfigs = BfvEncConfigs::new( + ENC_BFV_T, + ENC_BFV_Q_MOD_T, + QIS, + ENC_BFV_K0IS, + ENC_BFV_PK_BOUNDS, + ENC_BFV_E0_BOUND, + ENC_BFV_E1_BOUND, + ENC_BFV_U_BOUND, + ENC_BFV_R1_LOW_BOUNDS, + ENC_BFV_R1_UP_BOUNDS, + ENC_BFV_R2_BOUNDS, + ENC_BFV_P1_BOUNDS, + ENC_BFV_P2_BOUNDS, + ENC_BFV_MSG_BOUND, +); + +/************************************ +------------------------------------- +dec_bfv (CIRCUIT 4a - BFV DECRYPTION SK) +------------------------------------- +************************************/ + +// dec_bfv - bit parameters +pub global DEC_BFV_BIT_MSG_SK: u32 = 56; + +/************************************ +------------------------------------- +dec_bfv (CIRCUIT 4b - BFV DECRYPTION E_SM) +------------------------------------- +************************************/ + +// dec_bfv - bit parameters +pub global DEC_BFV_BIT_MSG_E_SM: u32 = 56; diff --git a/circuits/lib/src/configs/production/mod.nr b/circuits/lib/src/configs/production/mod.nr new file mode 100644 index 0000000000..0b3b884634 --- /dev/null +++ b/circuits/lib/src/configs/production/mod.nr @@ -0,0 +1,2 @@ +pub mod bfv; +pub mod trbfv; diff --git a/circuits/lib/src/configs/production/trbfv.nr b/circuits/lib/src/configs/production/trbfv.nr new file mode 100644 index 0000000000..9a8312a1c5 --- /dev/null +++ b/circuits/lib/src/configs/production/trbfv.nr @@ -0,0 +1,185 @@ +use crate::core::greco::Configs as GrecoConfigs; +use crate::core::trbfv_dec_share::Configs as DecShareTrBfvConfigs; +use crate::core::trbfv_dec_shares_agg::Configs as DecShareAggTrBfvConfigs; +use crate::core::trbfv_pk::Configs as TrbfvPkConfigs; +use crate::core::trbfv_pk_agg::Configs as PkAggTrBfvConfigs; +use crate::core::trbfv_verify_shares::Configs as VerifySharesConfigs; + +// Global configs for BFV parameter set +pub global N: u32 = 8192; +pub global L: u32 = 4; +pub global PLAINTEXT_MODULUS: Field = 100; +pub global QIS: [Field; L] = + [2251799822204929, 4503599627763713, 4503599631433729, 4503599634579457]; +pub global Q_MOD_T_MOD_P: Field = + 21888242871839275222246405745257275088548364400416034343698204186575808495598; +pub global Q_MOD_T: Field = 81; +pub global Q_INVERSE_MOD_T: Field = 21; +pub global T_INV_MOD_Q: Field = 162493576071160894262400971579825215135378801169890023914222388; + +/************************************ +------------------------------------- +pk_trbfv (CIRCUIT 1 - PUBLIC KEY THRESHOLD BFV) +------------------------------------- +************************************/ + +// pk_trbfv - bit parameters +pub global PK_TRBFV_BIT_EEK: u32 = 6; +pub global PK_TRBFV_BIT_SK: u32 = 2; +pub global PK_TRBFV_BIT_E_SM: u32 = 187; +pub global PK_TRBFV_BIT_R1: u32 = 18; +pub global PK_TRBFV_BIT_R2: u32 = 53; +pub global PK_TRBFV_BIT_PK: u32 = 53; + +// pk_trbfv - bounds +pub global PK_TRBFV_EEK_BOUND: Field = 20; +pub global PK_TRBFV_SK_BOUND: Field = 1; +pub global PK_TRBFV_E_SM_BOUND: Field = 66359003478811654788063765182202739927396573769378037760; +pub global PK_TRBFV_R1_BOUNDS: [Field; L] = [81920, 81920, 81920, 81920]; +pub global PK_TRBFV_R2_BOUNDS: [Field; L] = + [1125899911102464, 2251799813881856, 2251799815716864, 2251799817289728]; + +// pk_trbfv - configs +pub global PK_TRBFV_CONFIGS: TrbfvPkConfigs = TrbfvPkConfigs::new( + QIS, + PK_TRBFV_EEK_BOUND, + PK_TRBFV_SK_BOUND, + PK_TRBFV_E_SM_BOUND, + PK_TRBFV_R1_BOUNDS, + PK_TRBFV_R2_BOUNDS, +); + +/************************************ +------------------------------------- +verify_shares (CIRCUIT 2a - VERIFY SHARES SK) +------------------------------------- +************************************/ + +// verify_shares - bit parameters +pub global VERIFY_SHARES_BIT_SHARE: u32 = 54; +pub global VERIFY_SHARES_BIT_SECRET_SK: u32 = 2; + +// verify_shares - configs +pub global VERIFY_SHARES_CONFIGS_SK: VerifySharesConfigs = VerifySharesConfigs::new(QIS); + +/************************************ +------------------------------------- +verify_shares (CIRCUIT 2b - VERIFY SHARES E_SM) +------------------------------------- +************************************/ + +// verify_shares - bit parameters +pub global VERIFY_SHARES_BIT_SECRET_E_SM: u32 = 187; + +// verify_shares - configs +pub global VERIFY_SHARES_CONFIGS_E_SM: VerifySharesConfigs = VerifySharesConfigs::new(QIS); + +/************************************ +------------------------------------- +pk_agg_trbfv (CIRCUIT 5 - PUBLIC KEY AGGREGATION TRBFV) +------------------------------------- +************************************/ + +// pk_agg_trbfv - bit parameters +pub global PK_AGG_TRBFV_BIT_PK: u32 = 53; + +// pk_agg_trbfv - configs +pub global PK_AGG_TRBFV_CONFIGS: PkAggTrBfvConfigs = PkAggTrBfvConfigs::new(QIS); + +/************************************ +------------------------------------- +greco (USED FOR ENCRYPTION TRBFV x PVSS) +------------------------------------- +************************************/ + +// greco - bit parameters +pub global GRECO_BIT_PK: u32 = 52; +pub global GRECO_BIT_CT: u32 = 52; +pub global GRECO_BIT_U: u32 = 2; +pub global GRECO_BIT_E0: u32 = 107; +pub global GRECO_BIT_E1: u32 = 6; +pub global GRECO_BIT_K: u32 = 7; +pub global GRECO_BIT_R1: u32 = 14; +pub global GRECO_BIT_R2: u32 = 53; +pub global GRECO_BIT_P1: u32 = 14; +pub global GRECO_BIT_P2: u32 = 53; + +// greco - bounds +pub global GRECO_Q_MOD_T: Field = + 21888242871839275222246405745257275088548364400416034343698204186575808495598; +pub global GRECO_K0IS: [Field; L] = + [1553741877321401, 3467771713378059, 3107483745689273, 4188347660158895]; +pub global GRECO_PK_BOUNDS: [Field; L] = + [1125899911102464, 2251799813881856, 2251799815716864, 2251799817289728]; +pub global GRECO_E0_BOUND: Field = 54890881146011919040994244755389; +pub global GRECO_E1_BOUND: Field = 20; +pub global GRECO_U_BOUND: Field = 1; +pub global GRECO_K1_LOW_BOUND: Field = 50; +pub global GRECO_K1_UP_BOUND: Field = 49; +pub global GRECO_R1_LOW_BOUNDS: [Field; L] = [4132, 4136, 4131, 4143]; +pub global GRECO_R1_UP_BOUNDS: [Field; L] = [4131, 4135, 4131, 4142]; +pub global GRECO_R2_BOUNDS: [Field; L] = + [1125899911102464, 2251799813881856, 2251799815716864, 2251799817289728]; +pub global GRECO_P1_BOUNDS: [Field; L] = [4096, 4096, 4096, 4096]; +pub global GRECO_P2_BOUNDS: [Field; L] = + [1125899911102464, 2251799813881856, 2251799815716864, 2251799817289728]; + +// greco - configs +pub global GRECO_CONFIGS: GrecoConfigs = GrecoConfigs::new( + GRECO_Q_MOD_T, + QIS, + GRECO_K0IS, + GRECO_PK_BOUNDS, + GRECO_E0_BOUND, + GRECO_E1_BOUND, + GRECO_U_BOUND, + GRECO_R1_LOW_BOUNDS, + GRECO_R1_UP_BOUNDS, + GRECO_R2_BOUNDS, + GRECO_P1_BOUNDS, + GRECO_P2_BOUNDS, + GRECO_K1_LOW_BOUND, + GRECO_K1_UP_BOUND, +); + +/************************************ +------------------------------------- +dec_share_trbfv (CIRCUIT 6 - DECRYPTION SHARE TRBFV) +------------------------------------- +************************************/ + +// dec_share_trbfv - bit parameters +pub global DEC_SHARES_BIT_CT: u32 = 53; +pub global DEC_SHARES_BIT_S: u32 = 53; +pub global DEC_SHARES_BIT_E: u32 = 53; +pub global DEC_SHARES_BIT_R1: u32 = 65; +pub global DEC_SHARES_BIT_R2: u32 = 53; +pub global DEC_SHARES_BIT_D: u32 = 53; + +// dec_share_trbfv - bounds +pub global DEC_SHARES_DECRYPTION_SHARE_BOUND: Field = 2251799817289728; +pub global DEC_SHARES_R1_BOUNDS: [Field; L] = + [4611686035875690497, 9223372037660080129, 9223372045176272897, 9223372051618723841]; +pub global DEC_SHARES_R2_BOUNDS: [Field; L] = + [1125899911102464, 2251799813881856, 2251799815716864, 2251799817289728]; + +// dec_share_trbfv - configs +pub global DEC_SHARES_CONFIGS: DecShareTrBfvConfigs = DecShareTrBfvConfigs::new( + QIS, + DEC_SHARES_DECRYPTION_SHARE_BOUND, + DEC_SHARES_R1_BOUNDS, + DEC_SHARES_R2_BOUNDS, +); + +/************************************ +------------------------------------- +dec_share_agg_trbfv (CIRCUIT 7 - DECRYPTION SHARE AGGREGATION TRBFV) +------------------------------------- +************************************/ + +// dec_share_agg_trbfv - bit parameters +pub global DEC_SHARES_AGG_BIT_NOISE: u32 = 201; + +// dec_share_agg_trbfv - configs +pub global DEC_SHARES_AGG_CONFIGS: DecShareAggTrBfvConfigs = + DecShareAggTrBfvConfigs::new(QIS, PLAINTEXT_MODULUS, Q_INVERSE_MOD_T); diff --git a/circuits/lib/src/core/bfv_dec.nr b/circuits/lib/src/core/bfv_dec.nr new file mode 100644 index 0000000000..79d18f2fbe --- /dev/null +++ b/circuits/lib/src/core/bfv_dec.nr @@ -0,0 +1,78 @@ +use crate::math::commitments::{ + compute_aggregated_shares_commitment, compute_shares_party_modulus_commitment, + prepare_aggregated_shares_commitment_payload, prepare_single_polynomial_commitment_payload, +}; +use crate::math::polynomial::Polynomial; + +/// BFV Decryption Commitment Verification (Circuit 4). +/// +/// Verifies: +/// 1. Each decrypted share from H honest parties matches its commitment from Circuit 3 +/// 2. Computes sum of all shares +/// 3. Returns commitment to aggregated shares +pub struct BfvDecCommitVerify { + /// Expected commitments from Circuit 3 for H honest parties: [party_idx][mod_idx] + expected_commitments: [[Field; L]; H], + + /// Decrypted shares from H honest parties: [party_idx][mod_idx] + decrypted_shares: [[Polynomial; L]; H], +} + +impl BfvDecCommitVerify { + pub fn new( + expected_commitments: [[Field; L]; H], + decrypted_shares: [[Polynomial; L]; H], + ) -> Self { + BfvDecCommitVerify { expected_commitments, decrypted_shares } + } + + /// Verifies all decrypted shares match their expected commitments + fn verify_commitments(self) { + for party_idx in 0..H { + for mod_idx in 0..L { + let payload = prepare_single_polynomial_commitment_payload::( + self.decrypted_shares[party_idx][mod_idx], + ); + let computed = compute_shares_party_modulus_commitment(payload); + assert( + computed == self.expected_commitments[party_idx][mod_idx], + "Commitment mismatch", + ); + } + } + } + + /// Computes sum of all decrypted shares + fn compute_aggregated_shares(self) -> [Polynomial; L] { + let mut sum: [Polynomial; L] = [Polynomial::new([0; N]); L]; + + for mod_idx in 0..L { + let mut coeffs = [0 as Field; N]; + for coeff_idx in 0..N { + let mut total = 0 as Field; + for party_idx in 0..H { + total = + total + self.decrypted_shares[party_idx][mod_idx].coefficients[coeff_idx]; + } + coeffs[coeff_idx] = total; + } + sum[mod_idx] = Polynomial::new(coeffs); + } + + sum + } + + /// Main verification function + /// Returns commitment to aggregated shares + pub fn verify(self) -> Field { + // Step 1: Verify all commitments match + self.verify_commitments(); + + // Step 2: Compute aggregated shares + let aggregated = self.compute_aggregated_shares(); + + // Step 3: Return commitment to aggregated shares + let payload = prepare_aggregated_shares_commitment_payload::(aggregated); + compute_aggregated_shares_commitment(payload) + } +} diff --git a/circuits/lib/src/core/bfv_enc.nr b/circuits/lib/src/core/bfv_enc.nr new file mode 100644 index 0000000000..a7016293b4 --- /dev/null +++ b/circuits/lib/src/core/bfv_enc.nr @@ -0,0 +1,369 @@ +use crate::math::commitments::{ + compute_bfv_enc_challenge_commitment, compute_pk_bfv_commitment, + compute_shares_party_modulus_commitment, prepare_message_commitment_payload, + prepare_pk_commitment_payload, +}; +use crate::math::helpers::flatten; +use crate::math::modulo::U128::ModU128; +use crate::math::polynomial::Polynomial; + +/// Cryptographic parameters for BFV encryption circuit. +pub struct Configs { + /// Plaintext modulus t + pub t: Field, + /// Q mod t (for scaling message) + pub q_mod_t: Field, + /// CRT moduli for each basis: [q_0, q_1, ..., q_{L-1}] + pub qis: [Field; L], + /// Scaling factors for each basis: [k0_0, k0_1, ..., k0_{L-1}] + pub k0is: [Field; L], + /// Bounds for public key polynomials for each CRT basis + pub pk_bounds: [Field; L], + /// Bounds for error polynomials (e0) + pub e0_bound: Field, + /// Bounds for error polynomials (e1) + pub e1_bound: Field, + /// Bound for secret polynomial u (ternary distribution) + pub u_bound: Field, + /// Lower bounds for r1 polynomials (modulus switching quotients) + pub r1_low_bounds: [Field; L], + /// Upper bounds for r1 polynomials (modulus switching quotients) + pub r1_up_bounds: [Field; L], + /// Bounds for r2 polynomials (cyclotomic reduction quotients) + pub r2_bounds: [Field; L], + /// Bounds for p1 polynomials (modulus switching quotients) + pub p1_bounds: [Field; L], + /// Bounds for p2 polynomials (cyclotomic reduction quotients) + pub p2_bounds: [Field; L], + /// Bound for message polynomial (m) + pub msg_bound: Field, +} + +impl Configs { + pub fn new( + t: Field, + q_mod_t: Field, + qis: [Field; L], + k0is: [Field; L], + pk_bounds: [Field; L], + e0_bound: Field, + e1_bound: Field, + u_bound: Field, + r1_low_bounds: [Field; L], + r1_up_bounds: [Field; L], + r2_bounds: [Field; L], + p1_bounds: [Field; L], + p2_bounds: [Field; L], + msg_bound: Field, + ) -> Self { + Configs { + t, + q_mod_t, + qis, + k0is, + pk_bounds, + e0_bound, + e1_bound, + u_bound, + r1_low_bounds, + r1_up_bounds, + r2_bounds, + p1_bounds, + p2_bounds, + msg_bound, + } + } +} + +/// BFV Encryption Circuit (Circuit 3). +/// +/// Verifies: +/// 1. Public key commitment matches expected (from Circuit 0) +/// 2. Message commitment matches expected (from SK shares circuit) +/// 3. Correct BFV encryption: ct0[l] = pk0[l] * u + e0[l] + k1 * k0[l] + r1[l] * q[l] + r2[l] * (X^N + 1) +/// and ct1[l] = pk1[l] * u + e1 + p2[l] * (X^N + 1) + p1[l] * q[l] +pub struct EncryptionBfv { + /// Circuit parameters + configs: Configs, + /// Expected commitment to public key (from Circuit 0) + expected_pk_commitment: Field, + /// Expected commitment to message (from SK shares verification circuit) + expected_message_commitment: Field, + /// Public key component 0 for each CRT basis (public inputs) + pk0is: [Polynomial; L], + /// Public key component 1 for each CRT basis (public inputs) + pk1is: [Polynomial; L], + /// Ciphertext component 0 for each CRT basis (public inputs) + ct0is: [Polynomial; L], + /// Ciphertext component 1 for each CRT basis (public inputs) + ct1is: [Polynomial; L], + /// Random ternary polynomial u (secret witness) + u: Polynomial, + /// Error polynomial e0 (secret witness) + e0: Polynomial, + /// Per-basis error polynomials e0[l] (secret witnesses) + e0is: [Polynomial; L], + /// CRT quotients for e0 (secret witnesses) + e0_quotients: [Polynomial; L], + /// Error polynomial e1 (secret witness) + e1: Polynomial, + /// Raw message polynomial (secret witness) + message: Polynomial, + /// Modulus switching quotient polynomials r1 (secret witnesses, degree 2N-1) + r1is: [Polynomial<(2 * N) - 1>; L], + /// Cyclotomic reduction quotient polynomials r2 (secret witnesses, degree N-1) + r2is: [Polynomial; L], + /// Modulus switching quotient polynomials p1 (secret witnesses, degree 2N-1) + p1is: [Polynomial<(2 * N) - 1>; L], + /// Cyclotomic reduction quotient polynomials p2 (secret witnesses, degree N-1) + p2is: [Polynomial; L], +} + +impl EncryptionBfv { + pub fn new( + configs: Configs, + expected_pk_commitment: Field, + expected_message_commitment: Field, + pk0is: [Polynomial; L], + pk1is: [Polynomial; L], + ct0is: [Polynomial; L], + ct1is: [Polynomial; L], + u: Polynomial, + e0: Polynomial, + e0is: [Polynomial; L], + e0_quotients: [Polynomial; L], + e1: Polynomial, + message: Polynomial, + r1is: [Polynomial<2 * N - 1>; L], + r2is: [Polynomial; L], + p1is: [Polynomial<2 * N - 1>; L], + p2is: [Polynomial; L], + ) -> Self { + EncryptionBfv { + configs, + expected_pk_commitment, + expected_message_commitment, + pk0is, + pk1is, + ct0is, + ct1is, + u, + e0, + e0is, + e0_quotients, + e1, + message, + r1is, + r2is, + p1is, + p2is, + } + } + + /// Verifies that the public key hashes to the expected commitment + fn verify_pk_commitment(self) { + let payload = prepare_pk_commitment_payload::(self.pk0is, self.pk1is); + let computed_commitment = compute_pk_bfv_commitment(payload); + assert( + computed_commitment == self.expected_pk_commitment, + "Public key commitment mismatch", + ); + } + + /// Verifies that the message polynomial hashes to the expected commitment + fn verify_message_commitment(self) { + let payload = prepare_message_commitment_payload::(self.message); + let computed_commitment = compute_shares_party_modulus_commitment(payload); + assert( + computed_commitment == self.expected_message_commitment, + "Message commitment mismatch", + ); + } + + /// Computes the scaled message k1 from the raw message in centered form + /// k1[i] = (q_mod_t * message[i]) mod t, centered to [-t/2, t/2) + fn compute_scaled_message(self) -> Polynomial { + let t = self.configs.t; + let t_mod = ModU128::new(t); + let q_mod_t: Field = self.configs.q_mod_t; + let mut k1_coeffs: [Field; N] = [0; N]; + + // Integer division for t_half + let t_half: u128 = (t as u128) / 2; + + for i in 0..N { + let msg_i: Field = self.message.coefficients[i]; + let q_times_m_mod_t = t_mod.mul_mod(q_mod_t, msg_i); + + // Check if centering is needed (value > t/2 means negative in centered form) + let needs_centering = (q_times_m_mod_t as u128) > t_half; + + k1_coeffs[i] = if needs_centering { + // Value is in (t/2, t), negative in centered form + // Represent as P - magnitude (i.e., 0 - magnitude in Field) + let magnitude = t - q_times_m_mod_t; + 0 - magnitude + } else { + // Value is in [0, t/2], stays positive + q_times_m_mod_t + }; + } + + Polynomial { coefficients: k1_coeffs } + } + + /// Flattens all polynomial coefficients into a single array for Fiat-Shamir challenge generation + fn payload(self, k1: Polynomial) -> Vec { + let mut inputs = Vec::new(); + + // Use pk commitment instead of full pk polynomials + inputs.push(self.expected_pk_commitment); + + inputs = flatten::<_, _, BIT_CT>(inputs, self.ct0is); + inputs = flatten::<_, _, BIT_CT>(inputs, self.ct1is); + + inputs = flatten::<_, _, BIT_E0>(inputs, [self.e0]); + inputs = flatten::<_, _, BIT_E1>(inputs, [self.e1]); + inputs = flatten::<_, _, BIT_U>(inputs, [self.u]); + + // Use message commitment instead of full message + inputs.push(self.expected_message_commitment); + + // Include computed k1 in payload + for i in 0..N { + inputs.push(k1.coefficients[i]); + } + + inputs = flatten::<_, _, BIT_R1>(inputs, self.r1is); + inputs = flatten::<_, _, BIT_R2>(inputs, self.r2is); + inputs = flatten::<_, _, BIT_P1>(inputs, self.p1is); + inputs = flatten::<_, _, BIT_P2>(inputs, self.p2is); + + inputs + } + + /// Performs coefficient-wise CRT consistency check for the e0 error polynomial + fn check_e0_crt_consistency(self) { + for i in 0..L { + for j in 0..N { + assert( + self.e0.coefficients[j] + == self.e0is[i].coefficients[j] + + self.e0_quotients[i].coefficients[j] * self.configs.qis[i], + ); + } + } + } + + /// Main verification function + pub fn verify(self) -> bool { + // Step 1: Verify public key commitment matches expected + self.verify_pk_commitment(); + + // Step 2: Verify message commitment matches expected + self.verify_message_commitment(); + + // Step 3: Perform range checks + self.check_range_bounds(); + + // Step 4: Check CRT consistency for e0 + self.check_e0_crt_consistency(); + + // Step 5: Compute scaled message k1 from message + let k1 = self.compute_scaled_message(); + + // Step 6: Generate Fiat-Shamir challenges + let gammas = self.generate_challenge(k1); + + // Step 7: Verify encryption constraints + self.verify_evaluations(gammas, k1) + } + + /// Performs range checks on all secret witness polynomial coefficients + fn check_range_bounds(self) { + self.u.range_check_2bounds::(self.configs.u_bound, self.configs.u_bound); + self.e0.range_check_2bounds::(self.configs.e0_bound, self.configs.e0_bound); + self.e1.range_check_2bounds::(self.configs.e1_bound, self.configs.e1_bound); + + // Message should be in [0, t) + self.message.range_check_standard::(self.configs.msg_bound); + + for i in 0..L { + self.pk0is[i].range_check_2bounds::( + self.configs.pk_bounds[i], + self.configs.pk_bounds[i], + ); + self.pk1is[i].range_check_2bounds::( + self.configs.pk_bounds[i], + self.configs.pk_bounds[i], + ); + + self.r1is[i].range_check_2bounds::( + self.configs.r1_up_bounds[i], + self.configs.r1_low_bounds[i], + ); + self.r2is[i].range_check_2bounds::( + self.configs.r2_bounds[i], + self.configs.r2_bounds[i], + ); + + self.p1is[i].range_check_2bounds::( + self.configs.p1_bounds[i], + self.configs.p1_bounds[i], + ); + self.p2is[i].range_check_2bounds::( + self.configs.p2_bounds[i], + self.configs.p2_bounds[i], + ); + } + } + + /// Generates Fiat-Shamir challenge values using the SAFE cryptographic sponge + fn generate_challenge(self, k1: Polynomial) -> Vec { + let inputs = self.payload(k1); + + compute_bfv_enc_challenge_commitment::(inputs) + } + + /// Verifies BFV encryption constraints using Fiat-Shamir challenges and the Schwartz-Zippel lemma + fn verify_evaluations(self, gammas: Vec, k1: Polynomial) -> bool { + let gamma = gammas.get(0); + let cyclo_at_gamma = gamma.pow_32(N as Field) + 1; + let u_at_gamma = self.u.eval(gamma); + let e1_at_gamma = self.e1.eval(gamma); + let k1_at_gamma = k1.eval(gamma); + + let mut sum = (0, 0); + for i in 0..L { + let pk0is_at_gamma = self.pk0is[i].eval(gamma); + let r1i_at_gamma = self.r1is[i].eval(gamma); + let r2i_at_gamma = self.r2is[i].eval(gamma); + let e0is_at_gamma = self.e0is[i].eval(gamma); + + // Verify ct0 equation: ct0[i] = pk0[i]*u + e0[i] + k1*k0[i] + r1[i]*q[i] + r2[i]*cyclo + let mut ct0_rhs = (pk0is_at_gamma * u_at_gamma) + e0is_at_gamma; + ct0_rhs += k1_at_gamma * self.configs.k0is[i]; + ct0_rhs += r1i_at_gamma * self.configs.qis[i]; + ct0_rhs += r2i_at_gamma * cyclo_at_gamma; + let ct0_lhs = self.ct0is[i].eval(gamma); + + // Verify ct1 equation: ct1[i] = pk1[i]*u + e1 + p2[i]*cyclo + p1[i]*q[i] + let pk1is_at_gamma = self.pk1is[i].eval(gamma); + let p1is_at_gamma = self.p1is[i].eval(gamma); + let p2is_at_gamma = self.p2is[i].eval(gamma); + let mut ct1_rhs = (pk1is_at_gamma * u_at_gamma) + e1_at_gamma; + ct1_rhs += p2is_at_gamma * cyclo_at_gamma; + ct1_rhs += p1is_at_gamma * self.configs.qis[i]; + let ct1_lhs = self.ct1is[i].eval(gamma); + + // Accumulate weighted sums for batch verification + let gamma_i = if i == 0 { 1 } else { gammas.get(i) }; + sum = ( + sum.0 + ct0_lhs * gamma_i + ct1_lhs * gammas.get(i + L), + sum.1 + ct0_rhs * gamma_i + ct1_rhs * gammas.get(i + L), + ); + } + + sum.0 == sum.1 + } +} diff --git a/circuits/lib/src/core/bfv_pk.nr b/circuits/lib/src/core/bfv_pk.nr new file mode 100644 index 0000000000..1946b99217 --- /dev/null +++ b/circuits/lib/src/core/bfv_pk.nr @@ -0,0 +1,28 @@ +use crate::math::commitments::{compute_pk_bfv_commitment, prepare_pk_commitment_payload}; +use crate::math::polynomial::Polynomial; + +/// BFV Public Key Commitment Circuit (Circuit 0). +/// +/// commit to the BFV public key for later verification. +/// No validation of pk correctness - that's caught by decryption failures in Circuit 4. +pub struct BfvPkCommit { + /// BFV public key components (public input) + /// pk0[i] is the first component for modulus i + pk0: [Polynomial; L], + /// pk1[i] is the second component for modulus i + pk1: [Polynomial; L], +} + +impl BfvPkCommit { + pub fn new(pk0: [Polynomial; L], pk1: [Polynomial; L]) -> Self { + BfvPkCommit { pk0, pk1 } + } + + /// Main verification function + /// Returns commitment to BFV public key + pub fn verify(self) -> Field { + // Compute and return the pk bfv commitment + let payload = prepare_pk_commitment_payload::(self.pk0, self.pk1); + compute_pk_bfv_commitment(payload) + } +} diff --git a/circuits/crates/libs/greco/src/lib.nr b/circuits/lib/src/core/greco.nr similarity index 50% rename from circuits/crates/libs/greco/src/lib.nr rename to circuits/lib/src/core/greco.nr index 5096664af6..9a52fa1993 100644 --- a/circuits/crates/libs/greco/src/lib.nr +++ b/circuits/lib/src/core/greco.nr @@ -4,30 +4,18 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use polynomial::{flatten, Polynomial}; -use safe::SafeSponge; +use crate::math::commitments::compute_greco_challenge_commitment; +use crate::math::helpers::flatten; +use crate::math::polynomial::Polynomial; /// Cryptographic parameters for Greco circuit. -/// Contains the core mathematical constants used in the encryption scheme. -pub struct CryptographicParams { - /// Plaintext modulus: q mod t - pub q_mod_t: Field, - /// CRT moduli for each basis: [q_0, q_1, ..., q_{L-1}] +pub struct Configs { + /// CRT moduli: [q_0, q_1, ..., q_{L-1}] pub qis: [Field; L], + /// Plaintext modulus: q mod t mod p + pub q_mod_t_mod_p: Field, /// Scaling factors for each basis: [k0_0, k0_1, ..., k0_{L-1}] pub k0is: [Field; L], -} - -impl CryptographicParams { - /// Creates new cryptographic parameters - pub fn new(q_mod_t: Field, qis: [Field; L], k0is: [Field; L]) -> Self { - CryptographicParams { q_mod_t, qis, k0is } - } -} - -/// Bound parameters for range checking. -/// Contains all the bounds used to validate polynomial coefficients. -pub struct BoundParams { /// Bounds for public key polynomials for each CRT basis pub pk_bounds: [Field; L], /// Bounds for error polynomials (e0) @@ -52,9 +40,11 @@ pub struct BoundParams { pub k1_up_bound: Field, } -impl BoundParams { - /// Creates new bound parameters +impl Configs { pub fn new( + q_mod_t_mod_p: Field, + qis: [Field; L], + k0is: [Field; L], pk_bounds: [Field; L], e0_bound: Field, e1_bound: Field, @@ -67,7 +57,10 @@ impl BoundParams { k1_low_bound: Field, k1_up_bound: Field, ) -> Self { - BoundParams { + Configs { + qis, + q_mod_t_mod_p, + k0is, pk_bounds, e0_bound, e1_bound, @@ -83,106 +76,17 @@ impl BoundParams { } } -/// Complete parameters for Greco circuit. -/// Combines cryptographic parameters, bounds, and circuit-specific parameters. -pub struct Params { - /// Cryptographic parameters (moduli, scaling factors) - pub crypto: CryptographicParams, - /// Bound parameters for range checking - pub bounds: BoundParams, -} - -impl Params { - /// Creates new complete parameters - pub fn new( - q_mod_t: Field, - pk_bounds: [Field; L], - e0_bound: Field, - e1_bound: Field, - u_bound: Field, - r1_low_bounds: [Field; L], - r1_up_bounds: [Field; L], - r2_bounds: [Field; L], - p1_bounds: [Field; L], - p2_bounds: [Field; L], - k1_low_bound: Field, - k1_up_bound: Field, - qis: [Field; L], - k0is: [Field; L], - ) -> Self { - let crypto = CryptographicParams::new(q_mod_t, qis, k0is); - let bounds = BoundParams::new( - pk_bounds, - e0_bound, - e1_bound, - u_bound, - r1_low_bounds, - r1_up_bounds, - r2_bounds, - p1_bounds, - p2_bounds, - k1_low_bound, - k1_up_bound, - ); - - Params { crypto, bounds } - } - - /// Convenience method to access cryptographic parameters - pub fn crypto_params(self) -> CryptographicParams { - self.crypto - } - - /// Convenience method to access bound parameters - pub fn bound_params(self) -> BoundParams { - self.bounds - } -} - -/// Greco -/// Correct Encryption Circuit under BFV public key -/// -/// This circuit implements a zero-knowledge proof for the correct formation of a ciphertext -/// resulting from BFV (Brakerski-Fan-Vercauteren) public key encryption. The circuit verifies -/// that the ciphertext components (ct0, ct1) are correctly computed from the public key -/// components (pk0, pk1) and the encryption randomness. -/// -/// The circuit enforces the following core constraints: -/// 1. Range checks on all polynomial coefficients to ensure they are within expected bounds -/// 2. Correct encryption equations: -/// a. ct0i(gamma) = pk0i(gamma) * u(gamma) + e0(gamma) + k1(gamma) * k0i + r1i(gamma) * qi + r2i(gamma) * cyclo(gamma) -/// b. ct1i(gamma) = pk1i(gamma) * u(gamma) + e1(gamma) + p1i(gamma) * qi + p2i(gamma) * cyclo(gamma) +/// Greco: Correct Encryption Circuit under BFV public key /// -/// DISCLAIMER -/// The circuit is a porting of the Halo2 circuit from Greco paper author @ PSE. -/// Halo2 implementation is available at https://github.com/privacy-scaling-explorations/greco +/// Verifies: +/// 1. Range checks on all polynomial coefficients +/// 2. Correct encryption: ct0i = pk0i * u + e0 + k1 * k0i + r1i * qi + r2i * cyclo +/// and ct1i = pk1i * u + e1 + p1i * qi + p2i * cyclo /// -/// # Generic Parameters -/// * `N` - The degree of polynomials (ring dimension) -/// * `L` - The number of CRT (Chinese Remainder Theorem) bases -/// * `BIT_PK` - Bit-width bound per coefficient for public keys `pk0is`/`pk1is` -/// * `BIT_CT` - Bit-width bound per coefficient for cipher texts `ct0is`/`ct1is` -/// * `BIT_U` - Bit-width bound per coefficient for the ternary secret `u` -/// * `BIT_E0` - Bit-width bound per coefficient for error polynomial `e0` -/// * `BIT_E1` - Bit-width bound per coefficient for error polynomials `e1` -/// * `BIT_K` - Bit-width bound per coefficient for the scaled message polynomial `k1` -/// * `BIT_R1` - Bit-width bound per coefficient for randomness polynomials `r1is` -/// * `BIT_R2` - Bit-width bound per coefficient for randomness polynomials `r2is` -/// * `BIT_P1` - Bit-width bound per coefficient for randomness polynomials `p1is` -/// * `BIT_P2` - Bit-width bound per coefficient for randomness polynomials `p2is` -/// -/// # Circuit Inputs -/// * `pk_commitment` - Public key commitment -/// * `pk0is`, `pk1is` - Public key polynomials -/// * `ct0is`, `ct1is` - Ciphertext polynomials -/// * `u` - Secret polynomial sampled from ternary distribution -/// * `e0`, `e1` - Error polynomials sampled from discrete Gaussian distribution -/// * `k1` - Scaled message polynomial -/// * `r1is`, `r2is` - Randomness polynomials for each i-th CRT basis. -/// * `p1is`, `p2is` - Randomness polynomials for each i-th CRT basis. +/// DISCLAIMER: Ported from Halo2 circuit by Greco paper authors @ PSE. +/// Halo2 implementation: https://github.com/privacy-scaling-explorations/greco pub struct Greco { - /// Cryptographic parameters including bounds, moduli, and constants. - params: Params, + configs: Configs, pk_commitment: Field, pk0is: [Polynomial; L], pk1is: [Polynomial; L], @@ -201,33 +105,8 @@ pub struct Greco Greco { - /// Creates a new Greco instance. - /// - /// This constructor initializes all the polynomials and parameters needed for - /// the zero-knowledge proof of correct ciphertext formation. - /// - /// # Arguments - /// * `params` - Cryptographic parameters including bounds and moduli - /// * `pk_commitment` - Public key commitment - /// * `pk0is` - Public key polynomials pk0i = [ai*s + E] for each CRT basis - /// * `pk1is` - Public key polynomials pk1i = -[ai] for each CRT basis - /// * `ct0is` - First ciphertext component for each CRT basis - /// * `ct1is` - Second ciphertext component for each CRT basis - /// * `u` - Secret polynomial from ternary distribution - /// * `e0` - Error polynomial sampled from discrete Gaussian distribution - /// * `e0is` - CRT decomposition of e0 for each CRT basis - /// * `e0_quotients` - Quotient witnesses for CRT checking of e0 - /// * `e1` - Error polynomial sampled from discrete Gaussian distribution - /// * `k1` - Scaled message polynomial - /// * `r1is` - Randomness polynomials for ct0 computation - /// * `r2is` - Randomness polynomials for ct0 computation - /// * `p1is` - Randomness polynomials for ct1 computation - /// * `p2is` - Randomness polynomials for ct1 computation - /// - /// # Returns - /// A new Greco instance ready for constraint checking pub fn new( - params: Params, + configs: Configs, pk_commitment: Field, pk0is: [Polynomial; L], pk1is: [Polynomial; L], @@ -245,7 +124,7 @@ impl; L], ) -> Greco { Greco { - params, + configs, pk_commitment, pk0is, pk1is, @@ -264,6 +143,22 @@ impl Vec { + let mut inputs = Vec::new(); + + inputs = flatten::<_, _, BIT_PK>(inputs, self.pk0is); + inputs = flatten::<_, _, BIT_PK>(inputs, self.pk1is); + + inputs + } + /// Flattens all polynomials coefficients into a single array for challenge generation. /// /// This function serializes all polynomial coefficients into a 1D array to enable @@ -278,7 +173,6 @@ impl(inputs, self.ct0is); inputs = flatten::<_, _, BIT_CT>(inputs, self.ct1is); @@ -297,23 +191,6 @@ impl Vec { - let mut inputs = Vec::new(); - - // Flatten public key polynomials - inputs = flatten::<_, _, BIT_PK>(inputs, self.pk0is); - inputs = flatten::<_, _, BIT_PK>(inputs, self.pk1is); - - inputs - } - /// Performs coefficient-wise CRT consistency check for e0 polynomial. /// /// Verifies that for each CRT basis i and each coefficient j: @@ -327,8 +204,6 @@ impl(self.configs.u_bound, self.configs.u_bound); + self.e0.range_check_2bounds::(self.configs.e0_bound, self.configs.e0_bound); + self.e1.range_check_2bounds::(self.configs.e1_bound, self.configs.e1_bound); + self.k1.range_check_2bounds::(self.configs.k1_up_bound, self.configs.k1_low_bound); - // Common polynomials (used across all CRT bases) - self.u.range_check_2bounds::(bound_params.u_bound, bound_params.u_bound); - self.e0.range_check_2bounds::(bound_params.e0_bound, bound_params.e0_bound); - self.e1.range_check_2bounds::(bound_params.e1_bound, bound_params.e1_bound); - self.k1.range_check_2bounds::(bound_params.k1_up_bound, bound_params.k1_low_bound); - - // CRT basis-specific polynomials for i in 0..L { - // Public key polynomials must be within bounds for each CRT basis self.pk0is[i].range_check_2bounds::( - bound_params.pk_bounds[i], - bound_params.pk_bounds[i], + self.configs.pk_bounds[i], + self.configs.pk_bounds[i], ); self.pk1is[i].range_check_2bounds::( - bound_params.pk_bounds[i], - bound_params.pk_bounds[i], + self.configs.pk_bounds[i], + self.configs.pk_bounds[i], ); - // Randomness polynomials for ct0 computation self.r1is[i].range_check_2bounds::( - bound_params.r1_up_bounds[i], - bound_params.r1_low_bounds[i], + self.configs.r1_up_bounds[i], + self.configs.r1_low_bounds[i], ); self.r2is[i].range_check_2bounds::( - bound_params.r2_bounds[i], - bound_params.r2_bounds[i], + self.configs.r2_bounds[i], + self.configs.r2_bounds[i], ); - // Randomness polynomials for ct1 computation self.p1is[i].range_check_2bounds::( - bound_params.p1_bounds[i], - bound_params.p1_bounds[i], + self.configs.p1_bounds[i], + self.configs.p1_bounds[i], ); self.p2is[i].range_check_2bounds::( - bound_params.p2_bounds[i], - bound_params.p2_bounds[i], + self.configs.p2_bounds[i], + self.configs.p2_bounds[i], ); } } - /// Generates Fiat-Shamir challenge values using a cryptographic sponge + /// Generates Fiat-Shamir challenge values using the SAFE cryptographic sponge. + /// + /// This function implements the Fiat-Shamir transform for the Greco circuit: + /// 1. First, it computes and verifies the public key commitment by absorbing + /// all public key polynomials and squeezing a single commitment value. + /// 2. Then, it generates challenge values by absorbing all witness values + /// (ciphertexts, errors, randomness) and squeezing 2L challenge values. /// - /// The sponge absorbs all witness values and squeezes out deterministic random field elements - /// that will be used to evaluate polynomials for the Schwartz-Zippel lemma. + /// The sponge absorbs all witness values and squeezes out deterministic random + /// field elements that will be used to evaluate polynomials for the Schwartz-Zippel lemma. /// /// # Returns - /// Vector of challenge values [gamma_0, gamma_1, ..., gamma_{2L-1}] + /// Vector of challenge values [gamma_0, gamma_1, ..., gamma_{2L-1}] where: + /// - gamma_0 is used as the primary evaluation point + /// - gamma_1, ..., gamma_{L-1} are used for linear combination of ct0 constraints + /// - gamma_L, ..., gamma_{2L-1} are used for linear combination of ct1 constraints fn generate_challenge(self) -> Vec { - // Domain separator for Greco circuit - "Greco" in hex - let domain_separator = [ - 0x47, 0x72, 0x65, 0x63, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - ]; - - // IO Pattern: ABSORB(input_size), SQUEEZE(1) - let inputs = self.commitment_payload(); - let input_size = inputs.len(); - let io_pattern = [0x80000000 | input_size, 0x00000000 | 1]; - - let mut sponge = SafeSponge::start(io_pattern, domain_separator); - sponge.absorb(inputs); - let commitment = sponge.squeeze(); - sponge.finish(); - - assert_eq(commitment.get(0), self.pk_commitment); - - // IO Pattern: ABSORB(input_size), SQUEEZE(2*L) - let inputs = self.gammas_payload(); - let input_size = inputs.len(); - let io_pattern = [0x80000000 | input_size, 0x00000000 | (2 * L)]; - - let mut sponge = SafeSponge::start(io_pattern, domain_separator); - sponge.absorb(inputs); - let gammas = sponge.squeeze(); - - sponge.finish(); - gammas + let commitment_payload = self.commitment_payload(); + let gammas_payload = self.gammas_payload(); + + compute_greco_challenge_commitment::( + commitment_payload, + gammas_payload, + self.pk_commitment, + ) } - /// Verifies encryption constraints using Fiat-Shamir challenges + /// Verifies encryption constraints using Fiat-Shamir challenges. + /// + /// For each CRT basis i, this function verifies that the encryption equations hold + /// when evaluated at the challenge points. It uses the Schwartz-Zippel lemma: + /// if polynomial equations hold when evaluated at random points, then the polynomials + /// are identical with high probability. /// - /// For each CRT basis i, proves that LHS(gamma) = RHS(gamma) - /// This uses the Schwartz-Zippel lemma for polynomial identity testing. + /// The verification combines all CRT bases using a linear combination with the + /// challenge values to reduce the number of constraints while maintaining security. /// /// # Arguments /// * `gammas` - Vector of challenge values [gamma_0, gamma_1, ..., gamma_{2L-1}] + /// generated by `generate_challenge()` + /// + /// # Returns + /// `true` if all encryption constraints are satisfied, `false` otherwise. fn verify_evaluations(self, gammas: Vec) -> bool { - let crypto_params = self.params.crypto_params(); let gamma = gammas.get(0); - // Cyclotomic polynomial evaluation: cyclo(x) = x^N + 1 let cyclo_at_gamma = gamma.pow_32(N as Field) + 1; let u_at_gamma = self.u.eval(gamma); let e1_at_gamma = self.e1.eval(gamma); @@ -490,48 +353,24 @@ impl { + /// CRT moduli: [q_0, q_1, ..., q_{L-1}] + pub qis: [Field; L], + /// Bound for decryption share coefficients + pub decryption_share_bound: Field, + /// Bounds for r1 polynomials (modulus switching quotients) for each CRT basis + pub r1_bounds: [Field; L], + /// Bounds for r2 polynomials (cyclotomic reduction quotients) for each CRT basis + pub r2_bounds: [Field; L], +} + +impl Configs { + pub fn new( + qis: [Field; L], + decryption_share_bound: Field, + r1_bounds: [Field; L], + r2_bounds: [Field; L], + ) -> Self { + Configs { qis, decryption_share_bound, r1_bounds, r2_bounds } + } +} + +/// TRBFV Decryption Share Correctness (Circuit 6). +/// +/// Verifies: +/// 1. Commitment to s matches expected (from BFV decryption circuit) +/// 2. Commitment to e matches expected (from BFV decryption circuit) +/// 3. Correct computation: d = c_0 + c_1 * s + e + r_2 * (X^N + 1) + r_1 * q_i +pub struct DecryptionShare { + /// Circuit parameters including bounds and cryptographic constants + configs: Configs, + + /// Expected commitment to aggregated shares s (from BFV decryption circuit) + expected_s_commitment: Field, + + /// Expected commitment to aggregated noise e (from BFV decryption circuit) + expected_e_commitment: Field, + + /// Ciphertext components (public inputs) + /// c_0 components for each CRT basis (degree N-1 polynomials with N coefficients) + c_0: [Polynomial; L], + /// c_1 components for each CRT basis (degree N-1 polynomials with N coefficients) + c_1: [Polynomial; L], + + /// Aggregated sum of shares s (secret witness) + s: [Polynomial; L], + + /// Aggregated sum of noise e (secret witness, direct input) + /// e[basis] - sum of noise shares for each CRT basis (degree N-1 with N coefficients) + e: [Polynomial; L], + + /// Quotient polynomials for lifting to Z (secret witnesses) + r_1: [Polynomial<2 * N - 1>; L], + r_2: [Polynomial; L], + + /// Party's computed decryption share (public output) + d: [Polynomial; L], +} + +impl DecryptionShare { + pub fn new( + configs: Configs, + expected_s_commitment: Field, + expected_e_commitment: Field, + c_0: [Polynomial; L], + c_1: [Polynomial; L], + s: [Polynomial; L], + e: [Polynomial; L], + r_1: [Polynomial<2 * N - 1>; L], + r_2: [Polynomial; L], + d: [Polynomial; L], + ) -> Self { + DecryptionShare { + configs, + expected_s_commitment, + expected_e_commitment, + c_0, + c_1, + s, + e, + r_1, + r_2, + d, + } + } + + /// Verifies that s hashes to expected_s_commitment + fn verify_s_commitment(self) { + let payload = prepare_aggregated_shares_from_values_commitment_payload::(self.s); + let computed_commitment = compute_aggregated_shares_commitment(payload); + assert(computed_commitment == self.expected_s_commitment, "S commitment mismatch"); + } + + /// Verifies that e hashes to expected_e_commitment + fn verify_e_commitment(self) { + let payload = prepare_aggregated_shares_from_values_commitment_payload::(self.e); + let computed_commitment = compute_aggregated_shares_commitment(payload); + assert(computed_commitment == self.expected_e_commitment, "E commitment mismatch"); + } + + /// Flattens all witness data into a single array for Fiat-Shamir challenge generation. + /// + /// This function serializes all polynomial coefficients (both public inputs and + /// secret witnesses) into a 1D array in a deterministic order. The flattened data + /// is used to generate the Fiat-Shamir challenge via the SAFE sponge API. + /// + /// The order of serialization is: + /// 1. Ciphertext components `c_0` for each CRT basis + /// 2. Ciphertext components `c_1` for each CRT basis + /// 3. Aggregated secret shares `s` for each CRT basis + /// 4. Aggregated noise shares `e` for each CRT basis + /// 5. Quotient polynomials `r_1` for each CRT basis + /// 6. Quotient polynomials `r_2` for each CRT basis + /// 7. Decryption shares `d` for each CRT basis + /// + /// # Returns + /// A vector containing all polynomial coefficients in flattened form, ready for + /// hashing to generate the Fiat-Shamir challenge. + fn payload(self) -> Vec { + let mut inputs = Vec::new(); + + // Use commitments instead of full polynomials (saves constraints) + inputs.push(self.expected_s_commitment); + inputs.push(self.expected_e_commitment); + + // Flatten ciphertext components (public inputs) + inputs = flatten::<_, _, BIT_CT>(inputs, self.c_0); + inputs = flatten::<_, _, BIT_CT>(inputs, self.c_1); + + // Flatten quotient polynomials (secret witnesses) + inputs = flatten::<_, _, BIT_R1>(inputs, self.r_1); + inputs = flatten::<_, _, BIT_R2>(inputs, self.r_2); + + // Flatten decryption shares (public outputs) + inputs = flatten::<_, _, BIT_D>(inputs, self.d); + + inputs + } + + /// Main verification function + pub fn verify(self) { + // Step 1: Verify s commitment matches expected + self.verify_s_commitment(); + + // Step 2: Verify e commitment matches expected + self.verify_e_commitment(); + + // Step 3: Perform range checks on all secret witness values + self.check_range_bounds(); + + // Step 4: Generate Fiat-Shamir challenge from the transcript + let gamma = self.generate_challenge(); + + // Step 5: Verify decryption share computation for each CRT basis + for i in 0..L { + self.verify_decryption_share_computation(i, gamma); + } + } + + /// Performs range checks on all secret witness values. + /// + /// This function constrains all secret witnesses to be within their expected bounds + /// as specified in the `configs`. This is critical for security because it prevents + /// attacks where malicious provers provide out-of-range values that could break the + /// security properties of the threshold BFV scheme. + /// + /// The function checks: + /// - Aggregated secret shares `s` are within bounds for each CRT basis + /// - Aggregated noise shares `e` are within bounds for each CRT basis + /// - Quotient polynomials `r_1` and `r_2` are within bounds for each CRT basis + /// + /// # Panics + /// This function will cause the circuit to fail if any coefficient is outside + /// its expected bounds. The bounds are defined per polynomial type in the `configs`. + fn check_range_bounds(self) { + // Check aggregated sums are within bounds + for basis_idx in 0..L { + self.s[basis_idx].range_check_2bounds::( + self.configs.r2_bounds[basis_idx], + self.configs.r2_bounds[basis_idx], + ); + self.e[basis_idx].range_check_2bounds::( + self.configs.r2_bounds[basis_idx], + self.configs.r2_bounds[basis_idx], + ); + } + + // Check quotient polynomials are within bounds + for basis_idx in 0..L { + // r_1 quotients can be negative (modulus quotients) + self.r_1[basis_idx].range_check_2bounds::( + self.configs.r1_bounds[basis_idx], + self.configs.r1_bounds[basis_idx], + ); + // r_2 quotients (cyclotomic quotients) + self.r_2[basis_idx].range_check_2bounds::( + self.configs.r2_bounds[basis_idx], + self.configs.r2_bounds[basis_idx], + ); + } + } + + /// Generates Fiat-Shamir challenge value using the SAFE cryptographic sponge. + /// + /// This function implements the Fiat-Shamir transform for the decryption share circuit: + /// 1. Flattens all witness data (ciphertexts, secrets, quotients, shares) into a single array + /// 2. Absorbs the flattened data into the SAFE sponge + /// 3. Squeezes a single challenge value + /// + /// The challenge is used to evaluate polynomials for the Schwartz-Zippel lemma, + /// which allows verification of polynomial equations by checking them at a random + /// point rather than checking all coefficients. + /// + /// # Returns + /// A single challenge value `gamma` used as the evaluation point for verifying + /// the decryption share computation formula for all CRT bases. + fn generate_challenge(self) -> Field { + let inputs = self.payload(); + + compute_dec_share_challenge_commitment(inputs) + } + + /// Verifies the lifted decryption share computation formula for a specific CRT basis using the Schwartz-Zippel lemma. + /// + /// This function verifies that the decryption share for basis `i` satisfies: + /// `d_i(gamma) = c_0i(gamma) + c_1i(gamma) * s(gamma) + e_i(gamma) + r_2_i(gamma) * cyclo(gamma) + r_1_i(gamma) * q_i` + /// + /// Where: + /// - `c_0i`, `c_1i` are ciphertext components for basis i + /// - `s` is the aggregated secret key shares + /// - `e_i` is the aggregated noise shares + /// - `r_1_i`, `r_2_i` are quotient witnesses + /// - `cyclo(gamma) = gamma^N + 1` is the cyclotomic polynomial evaluated at gamma + /// - `q_i` is the CRT modulus for basis i + /// + /// The Schwartz-Zippel lemma ensures that if this equation holds at a random point + /// `gamma`, then the polynomials are identical with high probability. + /// + /// # Arguments + /// * `basis_idx` - The index of the CRT basis to verify (0 <= basis_idx < L) + /// * `gamma` - The Fiat-Shamir challenge value used as the evaluation point + /// + /// # Panics + /// The circuit will fail if the decryption share computation formula doesn't hold for the specified basis. + fn verify_decryption_share_computation(self, basis_idx: u32, gamma: Field) { + // Evaluate ciphertext components at gamma + let c_0_at_gamma = self.c_0[basis_idx].eval(gamma); + let c_1_at_gamma = self.c_1[basis_idx].eval(gamma); + + // Evaluate aggregated sums at gamma + let s_at_gamma = self.s[basis_idx].eval(gamma); + let e_at_gamma = self.e[basis_idx].eval(gamma); + + // Evaluate quotient polynomials at gamma + let r_1_at_gamma = self.r_1[basis_idx].eval(gamma); + let r_2_at_gamma = self.r_2[basis_idx].eval(gamma); + + // Evaluate cyclotomic polynomial X^N + 1 at gamma + let cyclo_at_gamma = gamma.pow_32(N as Field) + 1; + + // Compute expected decryption share using the lifted formula: + // d_i = c_0i + c_1i * s + e_i + r_2_i * (X^N + 1) + r_1_i * q_i + let expected_decryption_share = c_0_at_gamma + + c_1_at_gamma * s_at_gamma + + e_at_gamma + + r_2_at_gamma * cyclo_at_gamma + + r_1_at_gamma * self.configs.qis[basis_idx]; + + // Evaluate the party's claimed decryption share at gamma + let computed_decryption_share = self.d[basis_idx].eval(gamma); + + // Enforce equality: computed decryption share must match expected value + assert( + computed_decryption_share == expected_decryption_share, + "Decryption share computation failed", + ); + } +} diff --git a/circuits/lib/src/core/trbfv_dec_shares_agg.nr b/circuits/lib/src/core/trbfv_dec_shares_agg.nr new file mode 100644 index 0000000000..bc05136c36 --- /dev/null +++ b/circuits/lib/src/core/trbfv_dec_shares_agg.nr @@ -0,0 +1,321 @@ +use crate::math::modulo::U128::ModU128; +use crate::math::polynomial::Polynomial; +use dep::bignum::BigNum; +use dep::bignum::bignum::to_field; +use dep::bignum::Enclave_TRBFV_8192; + +/// Cryptographic parameters for decryption share aggregation circuit. +pub struct Configs { + /// CRT moduli: [q_0, q_1, ..., q_{L-1}] + pub qis: [Field; L], + /// Plaintext modulus (typically denoted as `t`) + pub plaintext_modulus: Field, + /// Precomputed value: `-Q^(-1) mod t` where Q is the product of all CRT moduli + pub q_inverse_mod_t: Field, +} + +impl Configs { + pub fn new(qis: [Field; L], plaintext_modulus: Field, q_inverse_mod_t: Field) -> Self { + Configs { qis, plaintext_modulus, q_inverse_mod_t } + } +} + +/// Decryption Share Aggregation Circuit (Circuit 7) +/// +/// Verifies: +/// 1. Lagrange interpolation to compute u^{(l)} for each CRT basis +/// 2. CRT reconstruction: u^{(l)} + r^{(l)} * q_l = u_global +/// 3. Decoding verification: message = -Q^{-1} * (t * u_global)_Q mod t +pub struct DecryptionSharesAggregation { + /// Circuit parameters including crypto constants + configs: Configs, + + /// Decryption shares from t+1 parties (public inputs) + decryption_shares: [[Polynomial; L]; T + 1], + + /// Party IDs (x-coordinates) for interpolation (public inputs) + party_ids: [Field; T + 1], + + /// Message polynomial m(x) (public output) + message: Polynomial, + + /// Global u polynomial (secret witness) + u_global: Polynomial, + + /// CRT quotient polynomials (secret witnesses) + crt_quotients: [Polynomial; L], +} + +impl DecryptionSharesAggregation { + pub fn new( + configs: Configs, + decryption_shares: [[Polynomial; L]; T + 1], + party_ids: [Field; T + 1], + message: Polynomial, + u_global: Polynomial, + crt_quotients: [Polynomial; L], + ) -> Self { + DecryptionSharesAggregation { + configs, + decryption_shares, + party_ids, + message, + u_global, + crt_quotients, + } + } + + /// Main verification function + pub fn verify(self) { + // Step 1: Compute Lagrange coefficients in-circuit + let lagrange_coeffs = self.compute_all_lagrange_coeffs(); + + // Step 2: Compute u^{(l)} for each CRT basis via Lagrange interpolation + let u_crts = self.compute_crt_components(lagrange_coeffs); + + // Step 3: Verify CRT reconstruction: u^{(l)} + r^{(l)} * q_l = u_global + self.verify_crt_reconstruction(u_crts); + + // Step 4: Verify decoding + self.verify_decoding(); + } + + /// Alternative verification function using efficient modular arithmetic without BigNum. + /// + /// Uses `ModU128` for decoding verification instead of BigNum. More efficient when + /// Q (the product of all CRT moduli) fits within u128 (e.g., 72 bits for insecure parameter sets). + pub fn verify_no_bn(self) { + // Step 1: Compute Lagrange coefficients in-circuit + let lagrange_coeffs = self.compute_all_lagrange_coeffs(); + + // Step 2: Compute u^{(l)} for each CRT basis via Lagrange interpolation + let u_crts = self.compute_crt_components(lagrange_coeffs); + + // Step 3: Verify CRT reconstruction: u^{(l)} + r^{(l)} * q_l = u_global + self.verify_crt_reconstruction(u_crts); + + // Step 4: Verify decoding + self.verify_decoding_no_bn(); + } + + /// Computes all Lagrange coefficients using optimized modular arithmetic + fn compute_all_lagrange_coeffs(self) -> [[Field; T + 1]; L] { + let mut lagrange_coeffs = [[0 as Field; T + 1]; L]; + + // Step 1: Cache |x_i - x_j| factors for all party pairs + let mut diffs = [[0 as Field; T + 1]; T + 1]; + for i in 0..(T + 1) { + for j in (i + 1)..(T + 1) { + let diff = self.party_ids[j] - self.party_ids[i]; + diffs[i][j] = diff; + diffs[j][i] = diff; + } + } + + // Step 2: Determine signs (same for all parties within a basis) + let numerator_sign_negative = (T % 2) == 1; + + // Step 3: For each CRT basis, compute Lagrange coefficients + for basis_idx in 0..L { + let q_l = self.configs.qis[basis_idx]; + let m = ModU128::new(q_l); + + // Compute product of all party IDs: PRODUCT(j=0..T) x_j mod q_l + let mut product_x = 1 as Field; + for j in 0..(T + 1) { + product_x = m.mul_mod(product_x, self.party_ids[j]); + } + + // For each party i, compute L_i(0) mod q_l + for party_idx in 0..(T + 1) { + // Numerator (absolute value): PRODUCT(j!=party_idx) x_j + let numerator_abs = m.div_mod(product_x, self.party_ids[party_idx]); + + // Denominator (absolute value): PRODUCT(j!=party_idx) |x_party_idx - x_j| + let mut denominator_abs = 1 as Field; + for j in 0..(T + 1) { + if j != party_idx { + denominator_abs = m.mul_mod(denominator_abs, diffs[party_idx][j]); + } + } + + // Determine denominator sign + let num_greater = T - party_idx; + let denom_sign_negative = (num_greater % 2) == 1; + + // Compute unsigned result: |numerator| / |denominator| mod q_l + let result_abs = m.div_mod(numerator_abs, denominator_abs); + + // Apply combined sign + let should_negate = numerator_sign_negative != denom_sign_negative; + let result = if should_negate { + m.reduce_mod(q_l - result_abs) + } else { + result_abs + }; + + lagrange_coeffs[basis_idx][party_idx] = result; + } + } + + lagrange_coeffs + } + + /// Computes u^{(l)} for each CRT basis via Lagrange interpolation + fn compute_crt_components( + self, + lagrange_coeffs: [[Field; T + 1]; L], + ) -> [Polynomial; L] { + let mut u_crts: [Polynomial; L] = + [Polynomial::new([0; MAX_MSG_NON_ZERO_COEFFS]); L]; + + for basis_idx in 0..L { + let q_l = self.configs.qis[basis_idx]; + let m = ModU128::new(q_l); + let mut u_coeffs = [0 as Field; MAX_MSG_NON_ZERO_COEFFS]; + + // For each coefficient position + for coeff_idx in 0..MAX_MSG_NON_ZERO_COEFFS { + let mut u_coeff = 0 as Field; + + // Sum all contributions: u = SUM(i=0..T) [d_i * L_i(0)] mod q_l + for party_idx in 0..(T + 1) { + let d_coeff = + self.decryption_shares[party_idx][basis_idx].coefficients[coeff_idx]; + let l_i_0 = lagrange_coeffs[basis_idx][party_idx]; + + let term = m.mul_mod(d_coeff, l_i_0); + u_coeff = m.reduce_mod(u_coeff + term); + } + + u_coeffs[coeff_idx] = u_coeff; + } + + u_crts[basis_idx] = Polynomial::new(u_coeffs); + } + + u_crts + } + + /// Verifies CRT reconstruction: u^{(l)} + r^{(l)} * q_l = u_global for all bases l + fn verify_crt_reconstruction(self, u_crts: [Polynomial; L]) { + for basis_idx in 0..L { + let q_l = self.configs.qis[basis_idx]; + + // Compute r^{(l)} * q_l + let r_times_q = self.crt_quotients[basis_idx].mul_scalar(q_l); + + // Compute u^{(l)} + r^{(l)} * q_l + let reconstructed = u_crts[basis_idx].add(r_times_q); + + // Verify: u^{(l)} + r^{(l)} * q_l = u_global + // Must hold for every coefficient + for coeff_idx in 0..MAX_MSG_NON_ZERO_COEFFS { + assert( + reconstructed.coefficients[coeff_idx] == self.u_global.coefficients[coeff_idx], + "CRT reconstruction verification failed", + ); + } + } + } + + /// Verifies decoding using BigNum for large Q values + fn verify_decoding(self) { + // Compute Q as product of all CRT moduli + let mut q_modulus = 1 as Field; + for l in 0..L { + q_modulus *= self.configs.qis[l]; + } + + // For centered arithmetic + let q_bn = Enclave_TRBFV_8192::from(q_modulus); + + let q_half_bn = q_bn.udiv(Enclave_TRBFV_8192::from(2)); + + for coeff_idx in 0..MAX_MSG_NON_ZERO_COEFFS { + // Compute (t * u_global) mod Q using BigNum + let u_bn_q = Enclave_TRBFV_8192::from(self.u_global.coefficients[coeff_idx]); + let t_bn_q = Enclave_TRBFV_8192::from(self.configs.plaintext_modulus); + let t_times_u_bn_q = t_bn_q * u_bn_q; + let m = ModU128::new(self.configs.plaintext_modulus); + + // Check if centering is needed + let needs_centering = t_times_u_bn_q > q_half_bn; + + let computed_message = if needs_centering { + // When (t*u) mod Q >= Q/2: treat as negative in centered form + // Centered value is conceptually negative: (t_times_u_mod_q - Q) + // -Q^{-1} * (negative) = positive result + let centered_positive = q_bn - t_times_u_bn_q; + let centered_positive_mod_t = centered_positive.umod(t_bn_q); + let centered_field = to_field(centered_positive_mod_t); + m.mul_mod(self.configs.q_inverse_mod_t, centered_field) + } else { + // When (t*u) mod Q < Q/2: stays positive in centered form + // -Q^{-1} * (positive) = negative result = t - result + let t_times_u_bn_t = t_times_u_bn_q.umod(t_bn_q); + let t_times_u_field = to_field(t_times_u_bn_t); + let product = m.mul_mod(self.configs.q_inverse_mod_t, t_times_u_field); + if product == 0 { + 0 + } else { + self.configs.plaintext_modulus - product + } + }; + + // Verify: only check non-zero coefficients + if self.message.coefficients[coeff_idx] != 0 { + assert(computed_message == self.message.coefficients[coeff_idx]); + } + } + } + + /// Alternative decoding verification using the formula: + /// message = -Q^{-1} * (t * u_global)_Q mod t + fn verify_decoding_no_bn(self) { + let t: Field = self.configs.plaintext_modulus; + // Compute Q as product of all CRT moduli + let mut q_modulus = 1; + for l in 0..L { + q_modulus *= self.configs.qis[l]; + } + + // For centered arithmetic + let q_half = q_modulus as u128 / 2; + + for coeff_idx in 0..MAX_MSG_NON_ZERO_COEFFS { + // Compute (t * u_global) mod Q using BigNum + let q_mod = ModU128::new(q_modulus); + let t_mod = ModU128::new(t); + + // Compute (t * u_global) mod Q using modular arithmetic functions + let t_times_u_mod_q = q_mod.mul_mod(t, self.u_global.coefficients[coeff_idx]); + let needs_centering = (t_times_u_mod_q as u128) > q_half; + + let computed_message = if needs_centering { + // When (t*u) mod Q >= Q/2: treat as negative in centered form + // Centered value is conceptually negative: (t_times_u_mod_q - Q) + // -Q^{-1} * (negative) = positive result + let centered_positive = q_modulus - t_times_u_mod_q; + let centered_positive_mod_t = t_mod.reduce_mod(centered_positive); + + t_mod.mul_mod(self.configs.q_inverse_mod_t, centered_positive_mod_t) + } else { + // When (t*u) mod Q < Q/2: stays positive in centered form + // -Q^{-1} * (positive) = negative result = t - result + let t_times_u_mod_t = t_mod.reduce_mod(t_times_u_mod_q); + let product = t_mod.mul_mod(self.configs.q_inverse_mod_t, t_times_u_mod_t); + if product == 0 { + 0 + } else { + t - product + } + }; + + // Verify: only check non-zero coefficients + if self.message.coefficients[coeff_idx] != 0 { + assert(computed_message == self.message.coefficients[coeff_idx]); + } + } + } +} diff --git a/circuits/lib/src/core/trbfv_pk.nr b/circuits/lib/src/core/trbfv_pk.nr new file mode 100644 index 0000000000..0f6c9cca53 --- /dev/null +++ b/circuits/lib/src/core/trbfv_pk.nr @@ -0,0 +1,216 @@ +use crate::math::commitments::{ + compute_pk_trbfv_commitment, compute_secret_commitment, compute_trbfv_pk_challenge_commitment, + prepare_pk_commitment_payload, prepare_single_polynomial_commitment_payload, +}; +use crate::math::helpers::flatten; +use crate::math::polynomial::Polynomial; + +/// Cryptographic parameters for TRBFV public key generation circuit. +pub struct Configs { + /// CRT moduli: [q_0, q_1, ..., q_{L-1}] + pub qis: [Field; L], + /// Bound for error polynomial (eek) coefficients + pub eek_bound: Field, + /// Bound for secret key polynomial (sk) coefficients + pub sk_bound: Field, + /// Bound for smudging noise polynomial (e_sm) coefficients + pub e_sm_bound: Field, + /// Bounds for r1 polynomials (modulus switching quotients) for each CRT basis + pub r1_bounds: [Field; L], + /// Bounds for r2 polynomials (cyclotomic reduction quotients) for each CRT basis + pub r2_bounds: [Field; L], +} + +impl Configs { + pub fn new( + qis: [Field; L], + eek_bound: Field, + sk_bound: Field, + e_sm_bound: Field, + r1_bounds: [Field; L], + r2_bounds: [Field; L], + ) -> Self { + Configs { qis, eek_bound, sk_bound, e_sm_bound, r1_bounds, r2_bounds } + } +} + +/// TRBFV Public Key Verification (Circuit 1). +/// +/// Verifies: +/// 1. Range checks on all secret witnesses (secret key, error, smudging noise, quotients) +/// 2. Correct public key generation: pk0_i = -a_i * sk + eek + r2_i * (X^N + 1) + r1_i * q_i +/// and pk1_i = a_i +/// +/// Outputs: +/// - commit(sk_trbfv) +/// - commit(pk_trbfv) +/// - commit(e_sm) +pub struct TrbfvPublicKey { + /// Cryptographic parameters including bounds, moduli, and constants. + configs: Configs, + + /// Common Reference String polynomials (public) + /// One polynomial per modulus i + a: [Polynomial; L], + + /// Error polynomial (secret witness) + /// Small coefficients sampled from error distribution + eek: Polynomial, + + /// Secret key polynomial (secret witness) + /// Small coefficients sampled from CBD (Centered Binomial Distribution) + sk: Polynomial, + + /// Smudging noise polynomial (secret witness) + /// Used for threshold decryption security + e_sm: Polynomial, + + /// Quotients from polynomial operations (secret witness) + /// r1[i] are quotients from modulus switching for modulus i (can be negative, degree 2*N-1) + r1: [Polynomial<2 * N - 1>; L], + /// r2[i] are quotients from cyclotomic reduction for modulus i (typically positive, degree N-1) + r2: [Polynomial; L], + + /// TRBFV public key components (public output) + /// pk0[i] is the first component of the public key for modulus i + pk0: [Polynomial; L], + /// pk1[i] is the second component of the public key for modulus i (should equal a[i]) + pk1: [Polynomial; L], +} + +impl TrbfvPublicKey { + pub fn new( + configs: Configs, + a: [Polynomial; L], + eek: Polynomial, + sk: Polynomial, + e_sm: Polynomial, + r1: [Polynomial<2 * N - 1>; L], + r2: [Polynomial; L], + pk0: [Polynomial; L], + pk1: [Polynomial; L], + ) -> Self { + TrbfvPublicKey { configs, a, eek, sk, e_sm, r1, r2, pk0, pk1 } + } + + /// Flattens all witness data into a single array for Fiat-Shamir challenge generation + fn payload( + self, + sk_commitment: Field, + pk_commitment: Field, + e_sm_commitment: Field, + ) -> Vec { + let mut inputs = Vec::new(); + + // Flatten CRS polynomials a (L polynomials of degree N) + inputs = flatten::<_, _, BIT_EEK>(inputs, self.a); + + // Flatten error polynomial eek (1 polynomial of degree N) + inputs = flatten::<_, _, BIT_EEK>(inputs, [self.eek]); + + // Use commitments instead of full polynomials + inputs.push(sk_commitment); + inputs.push(pk_commitment); + inputs.push(e_sm_commitment); + + // Flatten quotient polynomials (L polynomials each) + inputs = flatten::<_, _, BIT_R1>(inputs, self.r1); + inputs = flatten::<_, _, BIT_R2>(inputs, self.r2); + + inputs + } + + /// Main verification function + /// Returns (commit(sk), commit(pk), commit(e_sm)) + pub fn verify(self) -> (Field, Field, Field) { + // Step 1: Perform range checks on all secret witness values + self.perform_range_checks(); + + // Step 2: Compute commitments + let sk_payload = prepare_single_polynomial_commitment_payload::(self.sk); + let e_sm_payload = prepare_single_polynomial_commitment_payload::(self.e_sm); + let pk_payload = prepare_pk_commitment_payload::(self.pk0, self.pk1); + + let sk_commitment = compute_secret_commitment(sk_payload); + let e_sm_commitment = compute_secret_commitment(e_sm_payload); + let pk_commitment = compute_pk_trbfv_commitment(pk_payload); + + // Step 3: Generate Fiat-Shamir challenges using commitments + let gammas = self.generate_challenge(sk_commitment, pk_commitment, e_sm_commitment); + + // Step 4: Verify public key equations for each modulus + for i in 0..L { + let gamma = gammas.get(i); + self.verify_public_key_for_modulus(i, gamma); + } + + // Step 5: Return all commitments + (sk_commitment, pk_commitment, e_sm_commitment) + } + + /// Generates Fiat-Shamir challenge values using the SAFE cryptographic sponge + fn generate_challenge( + self, + sk_commitment: Field, + pk_commitment: Field, + e_sm_commitment: Field, + ) -> Vec { + let inputs = self.payload(sk_commitment, pk_commitment, e_sm_commitment); + + compute_trbfv_pk_challenge_commitment::(inputs) + } + + /// Performs range checks on all secret witness values + fn perform_range_checks(self) { + // Check that error polynomial has small coefficients + self.eek.range_check_2bounds::(self.configs.eek_bound, self.configs.eek_bound); + + // Check that secret key polynomial has small coefficients + self.sk.range_check_2bounds::(self.configs.sk_bound, self.configs.sk_bound); + + // Check that smudging noise polynomial has small coefficients + self.e_sm.range_check_2bounds::(self.configs.e_sm_bound, self.configs.e_sm_bound); + + // Check quotient terms are within expected bounds (per modulus) + for i in 0..L { + self.r1[i].range_check_2bounds::( + self.configs.r1_bounds[i], + self.configs.r1_bounds[i], + ); + + self.r2[i].range_check_2bounds::( + self.configs.r2_bounds[i], + self.configs.r2_bounds[i], + ); + } + } + + /// Verifies the TRBFV public key generation equations for a specific CRT basis + fn verify_public_key_for_modulus(self, i: u32, gamma: Field) { + // Evaluate all polynomials at the random challenge point gamma + let a_at_gamma = self.a.map(|a_poly| a_poly.eval(gamma)); + + let eek_at_gamma = self.eek.eval(gamma); + let sk_at_gamma = self.sk.eval(gamma); + + let r1_at_gamma = self.r1.map(|r1_poly| r1_poly.eval(gamma)); + let r2_at_gamma = self.r2.map(|r2_poly| r2_poly.eval(gamma)); + + let pk0_at_gamma = self.pk0.map(|pk0_poly| pk0_poly.eval(gamma)); + let pk1_at_gamma = self.pk1.map(|pk1_poly| pk1_poly.eval(gamma)); + + // Evaluate the cyclotomic polynomial X^N + 1 at gamma + let cyclo_at_gamma = gamma.pow_32(N as Field) + 1; + + // pk0_i = -a_i * sk + eek + r2_i * (X^N + 1) + r1_i * q_i + let expected_pk0 = -a_at_gamma[i] * sk_at_gamma + + eek_at_gamma + + r2_at_gamma[i] * cyclo_at_gamma + + r1_at_gamma[i] * self.configs.qis[i]; + + assert(pk0_at_gamma[i] == expected_pk0, "Public key equation 1 failed"); + + // Equation 2: pk1_i = a_i + assert(pk1_at_gamma[i] == a_at_gamma[i], "Public key equation 2 failed"); + } +} diff --git a/circuits/lib/src/core/trbfv_pk_agg.nr b/circuits/lib/src/core/trbfv_pk_agg.nr new file mode 100644 index 0000000000..24fabec909 --- /dev/null +++ b/circuits/lib/src/core/trbfv_pk_agg.nr @@ -0,0 +1,118 @@ +use crate::math::commitments::compute_greco_pk_agg_commitment; +use crate::math::commitments::{compute_pk_trbfv_commitment, prepare_pk_commitment_payload}; +use crate::math::modulo::U128::ModU128; +use crate::math::polynomial::Polynomial; + +/// Cryptographic parameters for TRBFV public key aggregation circuit. +pub struct Configs { + /// CRT moduli for each basis: [q_0, q_1, ..., q_{L-1}] + pub qis: [Field; L], +} + +impl Configs { + pub fn new(qis: [Field; L]) -> Self { + Configs { qis } + } +} + +/// TRBFV Public Key Aggregation (Circuit 5). +/// +/// Verifies that for each CRT basis l and each coefficient i: +/// - pk0_agg[l][i] = sum_h(pk0[h][l][i]) mod q_l +/// - pk1_agg[l][i] = sum_h(pk1[h][l][i]) mod q_l +pub struct TrbfvPublicKeyAggregation { + /// Circuit parameters including CRT moduli + configs: Configs, + + /// Expected commitments to public key TRBFV (from C1) + /// We need one comment from each honest party (H). + expected_pk_trbfv_commitments: [Field; H], + + /// Individual public keys from H honest parties (public inputs) + /// pk0[party_idx][basis_idx] - first component of public key for each party and CRT basis + pk0: [[Polynomial; L]; H], + /// pk1[party_idx][basis_idx] - second component of public key for each party and CRT basis + pk1: [[Polynomial; L]; H], + + /// Claimed aggregated public key (public inputs) + /// pk0_agg[basis_idx] - first component of aggregated public key for each CRT basis + pk0_agg: [Polynomial; L], + /// pk1_agg[basis_idx] - second component of aggregated public key for each CRT basis + pk1_agg: [Polynomial; L], +} + +impl TrbfvPublicKeyAggregation { + pub fn new( + configs: Configs, + expected_pk_trbfv_commitments: [Field; H], + pk0: [[Polynomial; L]; H], + pk1: [[Polynomial; L]; H], + pk0_agg: [Polynomial; L], + pk1_agg: [Polynomial; L], + ) -> Self { + TrbfvPublicKeyAggregation { + configs, + expected_pk_trbfv_commitments, + pk0, + pk1, + pk0_agg, + pk1_agg, + } + } + + /// Verifies that pk trbfv hashes to each expected_pk_trbfv_commitment + fn verify_pk_commitments(self) { + for i in 0..H { + let payload = prepare_pk_commitment_payload::(self.pk0[i], self.pk1[i]); + let computed_commitment = compute_pk_trbfv_commitment(payload); + assert( + computed_commitment == self.expected_pk_trbfv_commitments[i], + "PK commitment mismatch", + ); + } + } + + fn verify_pk_for_basis( + self, + pk: [[Polynomial; L]; H], + pk_agg: [Polynomial; L], + basis_idx: u32, + ) { + let q_l = self.configs.qis[basis_idx]; + let mod_q_l = ModU128::new(q_l); + + for coeff_idx in 0..N { + // Sum pk coefficients from all honest parties + let mut sum_pk: Field = 0; + for party_idx in 0..H { + sum_pk = sum_pk + pk[party_idx][basis_idx].coefficients[coeff_idx]; + } + + // Reduce mod q_l + let sum_pk_reduced = mod_q_l.reduce_mod(sum_pk); + + // Verify equality + assert( + sum_pk_reduced == pk_agg[basis_idx].coefficients[coeff_idx], + "pk aggregation mismatch", + ); + } + } + + /// Main verification function + /// Returns commitment to aggregated public key + pub fn verify(self) -> Field { + // 0. Verify pk commitments + self.verify_pk_commitments(); + + // 1. Verify pk & pk1 aggregations for each basis + for basis_idx in 0..L { + self.verify_pk_for_basis(self.pk0, self.pk0_agg, basis_idx); + self.verify_pk_for_basis(self.pk1, self.pk1_agg, basis_idx); + } + + // 2. Commit to aggregated public key + let payload = prepare_pk_commitment_payload::(self.pk0_agg, self.pk1_agg); + compute_greco_pk_agg_commitment(payload) + } +} diff --git a/circuits/lib/src/core/trbfv_verify_shares.nr b/circuits/lib/src/core/trbfv_verify_shares.nr new file mode 100644 index 0000000000..d8d27d546e --- /dev/null +++ b/circuits/lib/src/core/trbfv_verify_shares.nr @@ -0,0 +1,282 @@ +use crate::math::commitments::{ + compute_secret_commitment, compute_shares_party_modulus_commitment, + prepare_shares_party_modulus_commitment_payload, prepare_single_polynomial_commitment_payload, +}; +use crate::math::modulo::U128::ModU128; +use crate::math::polynomial::Polynomial; + +/// Cryptographic parameters for TRBFV secret share verification circuit. +pub struct Configs { + /// CRT moduli: [q_0, q_1, ..., q_{L-1}] + pub qis: [Field; L], +} + +impl Configs { + pub fn new(qis: [Field; L]) -> Self { + Configs { qis } + } +} + +/// TRBFV Secret Share Verification Circuit for secret key (Circuit 2a - VERIFY SHARES SK). +/// +/// Verifies: +/// 1. secret commitment: verify secret hashes to expected_secret_commitment +/// 2. secret consistency: y[i][j][0] == secret_sk[i] for all i, j +/// 3. Range check: shares are in [0, q_j) +/// 4. Parity check: H[j] * y[i][j]^T == 0 mod q_j for all i, j +/// +/// For SK: secret_sk is the trinary coefficients +pub struct VerifySharesSk { + configs: Configs, + /// Expected commitment to secret (from C1) + expected_secret_commitment: Field, + /// Secret key polynomial: Polynomial + /// trinary coefficients + secret_sk: Polynomial, + /// Shares: y[coeff_idx][mod_idx][0..N_PARTIES+1] + /// y[i][j][0] = secret_sk[i] = f(0), y[i][j][k] = f(k) for k = 1..N_PARTIES + y: [[[Field; N_PARTIES + 1]; L]; N], + /// Parity check matrices: H[mod_idx][row][col] + /// Size per modulus: (N_PARTIES - T) * (N_PARTIES + 1) + /// H * y^T = 0 mod q_j + h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], +} + +/// TRBFV Secret Share Verification Circuit for smudging noise (Circuit 2b - VERIFY SHARES E_SM). +/// +/// Verifies: +/// 1. secret commitment: verify secret hashes to expected_secret_commitment +/// 2. secret consistency: y[i][j][0] == e_sm[j][i] for all i, j +/// 3. Range check: shares are in [0, q_j) +/// 4. Parity check: H[j] * y[i][j]^T == 0 mod q_j for all i, j +/// +/// For ESM: e_sm[j] is the RNS representation at modulus j +pub struct VerifySharesEsm { + configs: Configs, + /// Expected commitment to secret (from C1) + /// This is computed from the first modulus's RNS representation. + expected_secret_commitment: Field, + /// Smudging noise polynomial per modulus: [Polynomial; L] + /// For ESM: each modulus has its own polynomial (RNS representation) + secret_e_sm: [Polynomial; L], + /// Shares: y[coeff_idx][mod_idx][0..N_PARTIES+1] + /// y[i][j][0] = e_sm[j][i] = f(0), y[i][j][k] = f(k) for k = 1..N_PARTIES + y: [[[Field; N_PARTIES + 1]; L]; N], + /// Parity check matrices: H[mod_idx][row][col] + /// Size per modulus: (N_PARTIES - T) * (N_PARTIES + 1) + /// H * y^T = 0 mod q_j + h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], +} + +impl VerifySharesSk { + pub fn new( + configs: Configs, + expected_secret_commitment: Field, + secret_sk: Polynomial, + y: [[[Field; N_PARTIES + 1]; L]; N], + h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], + ) -> Self { + VerifySharesSk { configs, expected_secret_commitment, secret_sk, y, h } + } + + /// Main verification function + pub fn verify(self) -> [[Field; L]; N_PARTIES] { + // Step 1: Verify secret commitment matches expected + self.verify_secret_commitment(); + + // Step 2: Verify secret consistency + self.verify_secret_consistency(); + + // Step 3: Range checks + check_range_bounds::(self.configs.qis, self.y); + + // Step 4: Verify parity check + verify_parity_check::(self.configs.qis, self.h, self.y); + + // Step 5: Commit to shares for each party and modulus + commit_to_party_shares::(self.y) + } + + /// Verifies that secret hashes to expected_secret_commitment + fn verify_secret_commitment(self) { + let payload = prepare_single_polynomial_commitment_payload::(self.secret_sk); + let computed_commitment = compute_secret_commitment(payload); + assert(computed_commitment == self.expected_secret_commitment, "SK commitment mismatch"); + } + + /// Verifies secret consistency: `y[i][j][0] == secret_sk[i]` for all i, j. + /// + /// This function ensures that for each coefficient i and CRT basis j, the share + /// at party ID 0 equals the corresponding secret coefficient for that modulus. + /// This is a fundamental property of Shamir secret sharing where the secret is the + /// evaluation of the sharing polynomial at point 0. + /// + /// secret_sk is the trinary coefficients, so y[i][j][0] is the same for all j. + /// + /// # Panics + /// The circuit will fail if secret consistency doesn't hold for any + /// coefficient or CRT basis. + fn verify_secret_consistency(self) { + for coeff_idx in 0..N { + let secret_coeff = self.secret_sk.coefficients[coeff_idx]; + + for mod_idx in 0..L { + assert(self.y[coeff_idx][mod_idx][0] == secret_coeff); + } + } + } +} + +impl VerifySharesEsm { + pub fn new( + configs: Configs, + expected_secret_commitment: Field, + secret_e_sm: [Polynomial; L], + y: [[[Field; N_PARTIES + 1]; L]; N], + h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], + ) -> Self { + VerifySharesEsm { configs, expected_secret_commitment, secret_e_sm, y, h } + } + + /// Main verification function + pub fn verify(self) -> [[Field; L]; N_PARTIES] { + // Step 1: Verify secret commitment matches expected + self.verify_secret_commitment(); + + // Step 2: Verify secret consistency + self.verify_secret_consistency(); + + // Step 3: Range checks + check_range_bounds::(self.configs.qis, self.y); + + // Step 4: Verify parity check + verify_parity_check::(self.configs.qis, self.h, self.y); + + // Step 5: Commit to shares for each party and modulus + commit_to_party_shares::(self.y) + } + + /// Verifies that secret hashes to expected_secret_commitment + /// For commitment verification, we use the first modulus's secret polynomial + /// (matches C1's computation which uses the first modulus's RNS representation) + fn verify_secret_commitment(self) { + let payload = + prepare_single_polynomial_commitment_payload::(self.secret_e_sm[0]); + let computed_commitment = compute_secret_commitment(payload); + assert(computed_commitment == self.expected_secret_commitment, "ESM commitment mismatch"); + } + + /// Verifies secret consistency: `y[i][j][0] == secret_e_sm[j][i]` for all i, j. + /// + /// This function ensures that for each coefficient i and CRT basis j, the share + /// at party ID 0 equals the corresponding secret coefficient for that modulus. + /// This is a fundamental property of Shamir secret sharing where the secret is the + /// evaluation of the sharing polynomial at point 0. + /// + /// secret_e_sm[j] is the RNS representation at modulus j, so y[i][j][0] varies per modulus. + /// + /// # Panics + /// The circuit will fail if secret consistency doesn't hold for any + /// coefficient or CRT basis. + fn verify_secret_consistency(self) { + for coeff_idx in 0..N { + for mod_idx in 0..L { + let secret_coeff = self.secret_e_sm[mod_idx].coefficients[coeff_idx]; + assert( + self.y[coeff_idx][mod_idx][0] == secret_coeff, + "Secret consistency check failed", + ); + } + } + } +} + +/// Performs range checks on secret key and share values. +/// +/// This function constrains all values to be within their expected bounds: +/// - Share values for parties k >= 1 must be in [0, q_j) for each CRT modulus q_j +/// +/// These bounds are critical for security and correctness of the threshold BFV scheme. +/// +/// # Panics +/// This function will cause the circuit to fail if any value is outside +/// its expected bounds. +pub fn check_range_bounds( + qis: [Field; L], + y: [[[Field; N_PARTIES + 1]; L]; N], +) { + // Shares y[i][j][k] for k >= 1 should be in [0, q_j) + for mod_idx in 0..L { + let q_j = qis[mod_idx]; + + for coeff_idx in 0..N { + for party_idx in 1..(N_PARTIES + 1) { + // Use range_check_standard from Polynomial by creating a single-coefficient polynomial + Polynomial::new([y[coeff_idx][mod_idx][party_idx]]) + .range_check_standard::(q_j); + } + } + } +} + +/// Verifies Reed-Solomon parity check: `H[j] * y[i][j]^T == 0 mod q_j` for all i, j. +/// +/// This function verifies that for each coefficient i and CRT basis j, the share +/// vector `y[i][j]` forms a valid Reed-Solomon codeword by satisfying the parity +/// check equation with the parity check matrix `H[j]`. +/// +/// The parity check matrix H[j] has dimensions `(N_PARTIES - T) * (N_PARTIES + 1)`, +/// and the share vector `y[i][j]` has length `N_PARTIES + 1`. The parity check +/// ensures that any T+1 shares can correctly reconstruct the secret key via +/// Lagrange interpolation. +/// +/// # Panics +/// The circuit will fail if the parity check doesn't hold for any coefficient, +/// CRT basis, or parity check row. +pub fn verify_parity_check( + qis: [Field; L], + h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], + y: [[[Field; N_PARTIES + 1]; L]; N], +) { + for coeff_idx in 0..N { + for mod_idx in 0..L { + let q_j = qis[mod_idx]; + + // For each row of H, compute dot product with y and verify == 0 + for row in 0..(N_PARTIES - T) { + let mut sum: Field = 0; + + for col in 0..(N_PARTIES + 1) { + sum = sum + h[mod_idx][row][col] * y[coeff_idx][mod_idx][col]; + } + + // Reduce mod q_j and verify == 0 + let m = ModU128::new(q_j); + let result = m.reduce_mod(sum); + assert(result == 0, "Parity check failed"); + } + } + } +} + +/// Commits to shares for each party and modulus +/// Returns [[Field; L]; N_PARTIES] where commitments[party_idx][mod_idx] +pub fn commit_to_party_shares( + y: [[[Field; N_PARTIES + 1]; L]; N], +) -> [[Field; L]; N_PARTIES] { + let mut commitments: [[Field; L]; N_PARTIES] = [[0; L]; N_PARTIES]; + + for party_idx in 0..N_PARTIES { + for mod_idx in 0..L { + let payload = prepare_shares_party_modulus_commitment_payload::( + y, + party_idx, + mod_idx, + ); + + commitments[party_idx][mod_idx] = compute_shares_party_modulus_commitment(payload); + } + } + + commitments +} diff --git a/circuits/lib/src/lib.nr b/circuits/lib/src/lib.nr new file mode 100644 index 0000000000..ec1ad02156 --- /dev/null +++ b/circuits/lib/src/lib.nr @@ -0,0 +1,11 @@ +//! # lib - Enclave Zero-Knowledge Cryptographic Library +//! - **`core`**: Core functions and structs for Public Verifiable +//! Secret Sharing (PVSS) circuits implementations. +//! - **`math`**: Mathematical utilities including polynomial operations, SAFE sponge +//! API implementation, and helper functions for circuit construction. +//! - **`configs`**: Cryptographic parameter configurations for different security +//! levels (insecure, production) and different circuit variants (BFV, TRBFV). + +pub mod math; +pub mod core; +pub mod configs; diff --git a/circuits/lib/src/math/commitments.nr b/circuits/lib/src/math/commitments.nr new file mode 100644 index 0000000000..3230adb7b1 --- /dev/null +++ b/circuits/lib/src/math/commitments.nr @@ -0,0 +1,303 @@ +use crate::math::helpers::{compute_safe, flatten}; +use crate::math::polynomial::Polynomial; + +/// Prepares the payload for TRBFV & BFV public key commitment +/// Flattens pk0 and pk1 polynomial arrays into a single Vec +/// Used in C0, C1, C3. +pub fn prepare_pk_commitment_payload( + pk0: [Polynomial; L], + pk1: [Polynomial; L], +) -> Vec { + let mut inputs = Vec::new(); + + // Flatten pk0 polynomials + inputs = flatten::<_, _, BIT_PK>(inputs, pk0); + + // Flatten pk1 polynomials + inputs = flatten::<_, _, BIT_PK>(inputs, pk1); + + inputs +} + +/// Flattens shares for a specific party and modulus into Vec +/// Returns N field elements: y[0][mod_idx][party_idx+1], ..., y[N-1][mod_idx][party_idx+1] +/// Used in C2. +pub fn prepare_shares_party_modulus_commitment_payload( + y: [[[Field; N_PARTIES + 1]; L]; N], + party_idx: u32, + mod_idx: u32, +) -> Vec { + let mut inputs = Vec::new(); + + for coeff_idx in 0..N { + inputs.push(y[coeff_idx][mod_idx][party_idx + 1]); + } + + // Include party_idx and mod_idx in the hash + inputs.push(party_idx as Field); + inputs.push(mod_idx as Field); + + inputs +} + +/// Prepares the payload for message commitment (must match C2). +/// Used in C3. +pub fn prepare_message_commitment_payload(message: Polynomial) -> Vec { + let mut inputs = Vec::new(); + + for i in 0..N { + inputs.push(message.coefficients[i]); + } + + inputs +} + +/// Prepares the payload for single polynomial commitment (must match C2). +/// Used in C1, C2, C4. +pub fn prepare_single_polynomial_commitment_payload( + poly: Polynomial, +) -> Vec { + flatten::<_, _, BIT_POLY>(Vec::new(), [poly]) +} + +/// Prepares the payload for aggregated shares commitment. +/// Used in C4. +pub fn prepare_aggregated_shares_commitment_payload( + aggregated: [Polynomial; L], +) -> Vec { + flatten::<_, _, BIT_MSG>(Vec::new(), aggregated) +} + +/// Prepares the payload for aggregated shares from values commitment. +/// Used in C6. +pub fn prepare_aggregated_shares_from_values_commitment_payload( + values: [Polynomial; L], +) -> Vec { + let mut inputs = Vec::new(); + + for basis_idx in 0..L { + for coeff_idx in 0..N { + inputs.push(values[basis_idx].coefficients[coeff_idx]); + } + } + + inputs +} + +/// Computes commitment to the BFV public key +/// Used in C0, C3. +pub fn compute_pk_bfv_commitment(payload: Vec) -> Field { + // Domain separator - "PVSS_pk_bfv" + let domain_separator = [ + 0x50, 0x56, 0x53, 0x53, 0x5f, 0x70, 0x6b, 0x5f, 0x62, 0x66, 0x76, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + compute_safe( + domain_separator, + payload, + [0x80000000 | payload.len(), 0x00000001], + ) + .get(0) +} + +/// Computes commitment to the TRBFV public key +/// Used in C1. +pub fn compute_pk_trbfv_commitment(payload: Vec) -> Field { + // Domain separator - "PVSS_pk_trbfv" in hex + let domain_separator = [ + 0x50, 0x56, 0x53, 0x53, 0x5f, 0x70, 0x6b, 0x5f, 0x74, 0x72, 0x62, 0x66, 0x76, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + compute_safe( + domain_separator, + payload, + [0x80000000 | payload.len(), 0x00000001], + ) + .get(0) +} + +/// Computes commitment to the secret (either sk_trbfv or e_sm) +/// Used in C1, C2. +pub fn compute_secret_commitment(payload: Vec) -> Field { + // Domain separator - "PVSS_secret" in hex + let domain_separator = [ + 0x50, 0x56, 0x53, 0x53, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + compute_safe( + domain_separator, + payload, + [0x80000000 | payload.len(), 0x00000001], + ) + .get(0) +} + +/// Computes share party-modulus commitment (either sk_shares or e_sm_shares) +/// Used in C2, C3 (message), C4 (single polynomial). +pub fn compute_shares_party_modulus_commitment(payload: Vec) -> Field { + // Domain separator - "PVSS_sh_pm" (shares party-modulus) + let domain_separator = [ + 0x50, 0x56, 0x53, 0x53, 0x5f, 0x73, 0x68, 0x5f, 0x70, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + compute_safe( + domain_separator, + payload, + [0x80000000 | payload.len(), 0x00000001], + ) + .get(0) +} + +/// Computes aggregated shares commitment (either sk_shares or e_sm_shares) +/// Used in C4. +pub fn compute_aggregated_shares_commitment(payload: Vec) -> Field { + // Domain separator - "PVSS_agg_sh" + let domain_separator = [ + 0x50, 0x56, 0x53, 0x53, 0x5f, 0x61, 0x67, 0x67, 0x5f, 0x73, 0x68, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + compute_safe( + domain_separator, + payload, + [0x80000000 | payload.len(), 0x00000001], + ) + .get(0) +} + +/// Computes decryption share challenge commitment +/// Used in C6. +pub fn compute_dec_share_challenge_commitment(payload: Vec) -> Field { + // Domain separator for decryption share circuit - "DecShare" in hex + let domain_separator = [ + 0x44, 0x65, 0x63, 0x53, 0x68, 0x61, 0x72, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + // IO Pattern: ABSORB(input_size), SQUEEZE(1) + let input_size = payload.len(); + let io_pattern = [0x80000000 | input_size, 0x00000001]; + + compute_safe(domain_separator, payload, io_pattern).get(0) +} + +/// Computes TRBFV pk challenge commitment +/// Used in C1. +pub fn compute_trbfv_pk_challenge_commitment(payload: Vec) -> Vec { + // Domain separator for trbfv_pk circuit - "trbfv_pk" in hex + let domain_separator = [ + 0x74, 0x72, 0x62, 0x66, 0x76, 0x5f, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + // IO Pattern: ABSORB(input_size), SQUEEZE(2 * L) + let input_size = payload.len(); + let io_pattern = [0x80000000 | input_size, 0x00000000 | (2 * L)]; + + compute_safe(domain_separator, payload, io_pattern) +} + +/// Computes Greco pk agg commitment +/// Used in Greco, C5. +pub fn compute_greco_pk_agg_commitment(payload: Vec) -> Field { + // Domain separator - "Greco" + let domain_separator = [ + 0x47, 0x72, 0x65, 0x63, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + // IO Pattern: ABSORB(input_size), SQUEEZE(1) + let input_size = payload.len(); + let io_pattern = [0x80000000 | input_size, 0x00000000 | 1]; + + compute_safe(domain_separator, payload, io_pattern).get(0) +} + +/// Computes Greco challenge commitment +/// Used in Greco. +pub fn compute_greco_challenge_commitment( + commitment_payload: Vec, + gammas_payload: Vec, + pk_commitment: Field, +) -> Vec { + // Domain separator - "Greco" + let domain_separator = [ + 0x47, 0x72, 0x65, 0x63, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + assert(compute_greco_pk_agg_commitment(commitment_payload) == pk_commitment); + + // IO Pattern: ABSORB(input_size), SQUEEZE(2*L) + let input_size = gammas_payload.len(); + let io_pattern = [0x80000000 | input_size, 0x00000000 | (2 * L)]; + + compute_safe(domain_separator, gammas_payload, io_pattern) +} + +/// Computes BFV encryption challenge commitment +/// Used in C3. +pub fn compute_bfv_enc_challenge_commitment(payload: Vec) -> Vec { + // Domain separator - "EncBfv" + let domain_separator = [ + 0x45, 0x6e, 0x63, 0x42, 0x66, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + let input_size = payload.len(); + let io_pattern = [0x80000000 | input_size, 0x00000000 | (2 * L)]; + + compute_safe(domain_separator, payload, io_pattern) +} + +/// Computes aggregation commitment +/// Used in aggregation circuits. +pub fn compute_aggregation_commitment(payload: Vec) -> Field { + // Domain separator - "Aggregation" + let domain_separator = [ + 0x41, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]; + + // IO Pattern: ABSORB(payload.len()), SQUEEZE(1) + let io_pattern = [0x80000000 | payload.len(), 0x00000001]; + + compute_safe(domain_separator, payload, io_pattern).get(0) +} diff --git a/circuits/crates/libs/polynomial/src/lib.nr b/circuits/lib/src/math/helpers.nr similarity index 53% rename from circuits/crates/libs/polynomial/src/lib.nr rename to circuits/lib/src/math/helpers.nr index fa1bdd5a86..79165bdae2 100644 --- a/circuits/crates/libs/polynomial/src/lib.nr +++ b/circuits/lib/src/math/helpers.nr @@ -1,140 +1,11 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. - -/// Polynomial structure representing a polynomial of degree N-1. -/// -/// A polynomial P(X) = a_{N-1} * X^{N-1} + a_{N-2} * X^{N-2} + ... + a_1 * X + a_0 -/// is represented as an array of coefficients where coefficients[0] = a_{N-1} (highest degree) -/// and coefficients[N-1] = a_0 (constant term). -pub struct Polynomial { - /// Array of polynomial coefficients in descending degree order - /// coefficients[0] = coefficient of X^{N-1} (highest degree term) - /// coefficients[N-1] = constant term (degree 0) - pub coefficients: [Field; N], -} - -impl Polynomial { - /// Creates a new polynomial from an array of coefficients. - /// - /// # Arguments - /// * `coefficients` - Array of N coefficients in descending degree order - /// coefficients[0] = coefficient of X^{N-1} - /// coefficients[N-1] = constant term - /// - /// # Returns - /// A new Polynomial instance with the specified coefficients - pub fn new(coefficients: [Field; N]) -> Self { - Polynomial { coefficients } - } - - /// Adds two polynomials. - /// - /// # Arguments - /// * `other` - The polynomial to add to the current polynomial. - /// - /// # Returns - /// A new polynomial with the coefficients added. - pub fn add(self, other: Self) -> Self { - let mut result = Self::new([0; N]); - - for i in 0..N { - result.coefficients[i] = self.coefficients[i] + other.coefficients[i]; - } - - result - } - - /// Subtracts two polynomials. - /// - /// # Arguments - /// * `other` - The polynomial to subtract from the current polynomial. - /// - /// # Returns - /// A new polynomial with the coefficients subtracted. - pub fn sub(self, other: Self) -> Self { - let mut result = Self::new([0; N]); - - for i in 0..N { - result.coefficients[i] = self.coefficients[i] - other.coefficients[i]; - } - - result - } - - /// Multiplies a polynomial by a scalar. - /// - /// # Arguments - /// * `scalar` - The scalar to multiply the polynomial by. - /// - /// # Returns - /// A new polynomial with the coefficients multiplied by the scalar. - pub fn mul_scalar(self, scalar: Field) -> Self { - let mut result = Self::new([0; N]); - - for i in 0..N { - result.coefficients[i] = self.coefficients[i] * scalar; - } - - result - } - - /// Evaluates the polynomial at a given point using Horner's method. - /// - /// Horner's method computes P(x) = a_{N-1} * x^{N-1} + ... + a_1 * x + a_0 - /// as ((...((a_{N-1} * x + a_{N-2}) * x + a_{N-3}) * x + ...) * x + a_0) - /// This approach require n multiplications and n additions to evaluate the polynomial. - /// - /// # Arguments - /// * `x` - The point at which to evaluate the polynomial. - /// - /// # Returns - /// The value of the polynomial at point x: P(x). - pub fn eval(self, x: Field) -> Field { - let mut result = self.coefficients[0]; - - for i in 1..self.coefficients.len() { - result = result * x + self.coefficients[i]; - } - - result - } - - /// Performs range checking on polynomial coefficients using asymmetric bounds - /// - /// This function constrains all polynomial coefficients to be in the range [lower_bound, upper_bound]. - /// Similar to range_check_1bound, it uses a shifting technique to avoid negative numbers: - /// 1. Shifts each coefficient by adding -lower_bound: c' = c - lower_bound - /// 2. Checks that shifted coefficients are in [0, upper_bound - lower_bound] - /// 3. This ensures original coefficients are in [lower_bound, upper_bound] - /// - /// Set `BIT` to the bit-length of the total range `upper_bound - lower_bound` - /// (choose `BIT` so `upper_bound - lower_bound < 2^BIT`). Since all checked values lie in - /// `[0, upper_bound - lower_bound]`, they cannot exceed `BIT + 1` bits, which is - /// why we use `assert_max_bit_size::()`. - /// - /// # Arguments - /// * `upper_bound` - The upper bound for coefficient range checking - /// * `lower_bound` - The lower bound for coefficient range checking (must be positive Field value) - /// Coefficients must satisfy: lower_bound <= c <= upper_bound - pub fn range_check_2bounds(self, upper_bound: Field, lower_bound: Field) { - let range_size = lower_bound + upper_bound; - - for i in 0..self.coefficients.len() { - let shifted_coefficient = self.coefficients[i] + lower_bound; - - shifted_coefficient.assert_max_bit_size::(); - (range_size - shifted_coefficient).assert_max_bit_size::(); - } - } -} +//! Helper functions for circuit construction and cryptographic operations. +use crate::math::polynomial::Polynomial; +use crate::math::safe::SafeSponge; /// Compute hex-aligned packing parameters for a given `BIT`. /// /// # Purpose -/// Returns `(nibble_bits, group)` for use by packer/flatten so layout stays consistent. +/// Returns `(nibble_bits, group)` for use by pack/flatten so layout stays consistent. /// - `nibble_bits`: ceil (`BIT`) to the next multiple of 4 (nibble alignment). /// - Examples: `BIT = 7 -> 8`, `BIT = 8 -> 8`, `BIT = 9 -> 12`, `BIT = 10 -> 12`, `BIT = 11 -> 12`, /// `BIT=16 -> 16`, `BIT = 17 -> 20`. @@ -168,9 +39,9 @@ fn packing_layout() -> (u32, u32) { /// /// ## What this does /// - For each CRT limb `j` in `0..L`, it packs the coefficients of `poly[j]` -/// with `packer::` and appends all resulting carriers to `inputs`. +/// with `pack::` and appends all resulting carriers to `inputs`. /// - The packing layout (nibble-aligned width and `group` size) is taken from -/// `packing_layout::()` and must match what `packer` uses. +/// `packing_layout::()` and must match what `pack` uses. /// /// ## Determinism & order /// - Preserves a stable order: iterate `j = 0..L`, then for each `j` append @@ -190,7 +61,7 @@ pub fn flatten( ) -> Vec { for j in 0..L { // Pack its A coefficients into `num_chunks` carriers using the same BIT layout. - let packed = packer::(poly[j].coefficients); + let packed = pack::(poly[j].coefficients); // Append carriers in-order to `inputs` to keep a stable transcript layout. for i in 0..packed.len() { @@ -221,7 +92,7 @@ pub fn flatten( /// /// ## Preconditions / Notes /// - Call with the raw coefficients whose magnitudes already satisfy the BIT bound -/// (as enforced by the upstream range checks); `packer` performs the signed -> unsigned +/// (as enforced by the upstream range checks); `pack` performs the signed -> unsigned /// shift internally via `v + base`. /// - `group >= 1` is enforced by `packing_layout::()`. /// - Padding with `digit = 2^nibble_bits` encodes `zero limb` consistently. @@ -229,7 +100,7 @@ pub fn flatten( /// ## Returns /// - A `Vec` where each element is a concatenation of up to `group` limbs, /// suitable for hashing or transcript I/O. -pub fn packer(values: [Field; A]) -> Vec { +pub fn pack(values: [Field; A]) -> Vec { // Layout parameters: nibble-aligned width and limbs-per-carrier group size. let (nibble_bits, group) = packing_layout::(); @@ -263,46 +134,34 @@ pub fn packer(values: [Field; A]) -> Vec { out } -#[test] -fn test_polynomial_eval() { - let coeffs = [1, 2, 3]; // represents 1x^2 + 2x + 3 - let poly = Polynomial::new(coeffs); - - let x = 2; // evaluate at x = 2 - let result = poly.eval(x); - - // (1 * 2^2) + (2 * 2) + 3 = 4 + 4 + 3 = 11 - assert_eq(result, 11); -} - -#[test] -fn test_polynomial_eval_zero() { - let coeffs = [1, -2, 1]; // x^2 - 2x + 1 = (x-1)^2 - let poly = Polynomial::new(coeffs); - - let x = 1; // evaluate at x = 1, should be 0 - let result = poly.eval(x); - - assert_eq(result, 0); -} - -#[test] -fn test_polynomial_bounds() { - let coeffs = [-16, 240, 242]; - let poly = Polynomial::new(coeffs); - - // Test double bounds check - constrains to [-240, 242] - poly.range_check_2bounds::<8>(242, 240); -} - -#[test(should_fail_with = "assert_max_bit_size")] -fn test_polynomial_out_of_bounds_coefficients() { - let coeffs = [-100]; - let poly = Polynomial::new(coeffs); +/// Computes a cryptographic hash using the SAFE (Sponge API for Field Elements) protocol. +/// +/// This is a convenience wrapper around the SAFE sponge API that handles the full +/// lifecycle: initialization, absorption, squeezing, and finalization. It's designed +/// for use in Fiat-Shamir challenge generation and commitment schemes within zero-knowledge circuits. +/// +/// # Arguments +/// * `domain_separator` - A 64-byte domain separator used to differentiate between +/// different protocol instances and prevent cross-protocol attacks. +/// * `inputs` - Vector of field elements to be absorbed into the sponge. +/// * `io_pattern` - A 2-element array encoding the I/O pattern: +/// - `io_pattern[0]`: Encoded ABSORB operation (MSB=1, lower 31 bits = length) +/// - `io_pattern[1]`: Encoded SQUEEZE operation (MSB=0, lower 31 bits = length) +/// +/// # Returns +/// A vector of field elements squeezed from the sponge, with length determined by +/// the SQUEEZE operation in the IO pattern. +pub fn compute_safe( + domain_separator: [u8; 64], + inputs: Vec, + io_pattern: [u32; 2], +) -> Vec { + let mut sponge = SafeSponge::start(io_pattern, domain_separator); + sponge.absorb(inputs); + let digests = sponge.squeeze(); + sponge.finish(); - // Test double bounds check - constrains to [-98, 99] - // Should fail because -100 is out of bounds. - poly.range_check_2bounds::<7>(99, 98); + digests } #[test] @@ -322,9 +181,9 @@ fn test_flatten() { // Verify the flattened coefficients are in the correct positions // Every value shifted 1 nibble incase of negative integers - assert_eq(result.get(0), 0x11121310101010101010101010101010101010101010101010101010101010); - assert_eq(result.get(1), 0x14001610101010101010101010101010101010101010101010101010101010); // -16 became 00 at 0x 14 00 16, - assert_eq(result.get(2), 0x09181910101010101010101010101010101010101010101010101010101010); // -7 became 09 at 0x 09 18 19(16 - 7 = 9) + assert(result.get(0) == 0x11121310101010101010101010101010101010101010101010101010101010); + assert(result.get(1) == 0x14001610101010101010101010101010101010101010101010101010101010); // -16 became 00 at 0x 14 00 16, + assert(result.get(2) == 0x09181910101010101010101010101010101010101010101010101010101010); // -7 became 09 at 0x 09 18 19(16 - 7 = 9) } #[test] @@ -384,12 +243,12 @@ fn test_flatten_big() { // base - 5921327228407753 = 0xeaf69591f3b037 (negative coefficient shifted) // base - 3644467483862151 = 0xf30d604a3a9b79 (negative coefficient shifted) // base + 5430119342984413 = 0x1134aaa2e86ccdd - assert_eq(result.get(0), 0x1065d1a8b8b718a0eaf69591f3b0370f30d604a3a9b791134aaa2e86ccdd); - assert_eq(result.get(1), 0x1028105ab1b789411fa010339db66b0fc220f1326bc8e0f1e3f4cc1e02e1); - assert_eq(result.get(2), 0x0f23dfbe7cd76c90f4901299312ddf10a569efe35acef11c0d76f005412b); - assert_eq(result.get(3), 0x107624a8f605dc50f0638a368960421022ecb3cf36b7911d73ff2c27ec14); - assert_eq(result.get(4), 0x0f6013a24e1b9a90f4fd2c158a08481180c2dba8af4cc10242413515171c); - assert_eq(result.get(5), 0x11b0964eb898ce411076805680b85410729c962da53a40f4b44412d0f6ed); + assert(result.get(0) == 0x1065d1a8b8b718a0eaf69591f3b0370f30d604a3a9b791134aaa2e86ccdd); + assert(result.get(1) == 0x1028105ab1b789411fa010339db66b0fc220f1326bc8e0f1e3f4cc1e02e1); + assert(result.get(2) == 0x0f23dfbe7cd76c90f4901299312ddf10a569efe35acef11c0d76f005412b); + assert(result.get(3) == 0x107624a8f605dc50f0638a368960421022ecb3cf36b7911d73ff2c27ec14); + assert(result.get(4) == 0x0f6013a24e1b9a90f4fd2c158a08481180c2dba8af4cc10242413515171c); + assert(result.get(5) == 0x11b0964eb898ce411076805680b85410729c962da53a40f4b44412d0f6ed); } #[test] @@ -407,7 +266,69 @@ fn test_flatten_small() { // Flatten the polynomials let result = flatten::<_, _, 20>(inputs, polynomials); - assert_eq(result.get(0), 0x1ade991199991f423f17a12110007b19fbf110004d100000100000100000); - assert_eq(result.get(1), 0x10000117ffff1d9038105ba01087071badf8100000100000100000100000); - assert_eq(result.get(2), 0x16c81c15161513640e11b2071f120613c41a10350b100000100000100000); + assert(result.get(0) == 0x1ade991199991f423f17a12110007b19fbf110004d100000100000100000); + assert(result.get(1) == 0x10000117ffff1d9038105ba01087071badf8100000100000100000100000); + assert(result.get(2) == 0x16c81c15161513640e11b2071f120613c41a10350b100000100000100000); +} + +#[test] +fn test_safe_hashing_with_safe_helper() { + // Verifies basic hash functionality with a simple ABSORB(3) + SQUEEZE(1) pattern. + let domain_separator = [ + 0x41, 0x42, 0x43, 0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + ]; + let elements = Vec::from_slice(&[1, 2, 3]); + + // Pattern: ABSORB(3), SQUEEZE(1) + let io_pattern = [0x80000003, 0x00000001]; + let digests1 = compute_safe(domain_separator, elements, io_pattern); + + assert(digests1.len() == 1); + assert(digests1.get(0) != 0); + + // Test determinism + let digests2 = compute_safe(domain_separator, elements, io_pattern); + + assert(digests2.len() == 1); + assert(digests2.get(0) != 0); +} + +#[test] +fn test_pack() { + // Test pack function directly with small values + let values = [1, 2, 3, 4]; + let packed = pack::<4, 4>(values); + + // With BIT=4, nibble_bits=4, group should be floor(254/(4+4)) = 31 + // So all 4 values should fit in one carrier + assert(packed.len() >= 1); + + // Test with negative values + let values_neg = [-1, 2, -3, 4]; + let packed_neg = pack::<4, 4>(values_neg); + assert(packed_neg.len() >= 1); +} + +#[test] +fn test_pack_single_value() { + // Test packing a single value + let values = [42]; + let packed = pack::<1, 8>(values); + assert(packed.len() == 1); + assert(packed.get(0) != 0); +} + +#[test] +fn test_pack_determinism() { + // Test that packing is deterministic + let values = [10, 20, 30]; + let packed1 = pack::<3, 8>(values); + let packed2 = pack::<3, 8>(values); + + assert(packed1.len() == packed2.len()); + for i in 0..packed1.len() { + assert(packed1.get(i) == packed2.get(i)); + } } diff --git a/circuits/lib/src/math/mod.nr b/circuits/lib/src/math/mod.nr new file mode 100644 index 0000000000..2cd07d265d --- /dev/null +++ b/circuits/lib/src/math/mod.nr @@ -0,0 +1,5 @@ +pub mod polynomial; +pub mod safe; +pub mod helpers; +pub mod modulo; +pub mod commitments; diff --git a/circuits/lib/src/math/modulo/U128.nr b/circuits/lib/src/math/modulo/U128.nr new file mode 100644 index 0000000000..858b9acc86 --- /dev/null +++ b/circuits/lib/src/math/modulo/U128.nr @@ -0,0 +1,592 @@ +//! Constrained modular arithmetic operations for u128 values. +//! +//! This module provides a `ModU128` struct that implements modular arithmetic operations +//! with full constraint generation for zero-knowledge proof circuits. All operations +//! are verified in-circuit to ensure correctness. +use super::unconstrained_U128::{ + __compute_mod_reduction, __div_mod, __inv_mod, __neg, __sub_with_underflow, +}; + +/// Modular arithmetic context for u128 values. +/// +/// This struct holds a modulus and provides methods for performing modular arithmetic +/// operations with full constraint generation. All operations are verified in-circuit. +/// +/// # Generic Parameters +/// +/// The operations work with `Field` values, but are designed for u128-sized integers. +/// The modulus must be a positive value less than 2^128. +pub struct ModU128 { + /// The modulus for all operations + pub m: Field, +} + +impl ModU128 { + /// Creates a new modular arithmetic context with the given modulus. + /// + /// # Arguments + /// * `m` - The modulus for all operations. Must be positive. + /// + /// # Returns + /// A new `ModU128` instance configured with the specified modulus. + pub fn new(m: Field) -> Self { + ModU128 { m } + } + + /// Returns the modulus as a Field value. + /// + /// # Returns + /// The modulus value used by this context. + pub fn get_mod_field(self) -> Field { + self.m + } + + /// Reduces a value modulo the modulus. + /// + /// Computes `n mod m` and returns the result in the range [0, m). + /// This operation is fully constrained and verified in-circuit. + /// + /// # Arguments + /// * `n` - The value to reduce + /// + /// # Returns + /// The value `n mod m` in the range [0, m) + /// + /// # Panics + /// The circuit will fail if the reduction is incorrect. + pub fn reduce_mod(self, n: Field) -> Field { + // Safety: __compute_mod_reduction is safe to call here because we assert the properties of the output + let (q, r) = unsafe { __compute_mod_reduction(n, self.m) }; + + // Ensure remainder is in [0, q) + assert(r as u128 < self.m as u128); + // Verify the reduction is correct + assert(n == q * self.m + r); + + r + } + + /// Adds two values with modular reduction. + /// + /// Computes `(lhs + rhs) mod m` and returns the result. + /// Handles overflow correctly by reducing modulo the modulus. + /// + /// # Arguments + /// * `lhs` - Left-hand side value + /// * `rhs` - Right-hand side value + /// + /// # Returns + /// The result of `(lhs + rhs) mod m` + pub fn add(self, lhs: Field, rhs: Field) -> Field { + self.reduce_mod(lhs + rhs) + } + + /// Subtracts two values with modular reduction. + /// + /// Computes `(lhs - rhs) mod m` and returns the result. + /// Handles underflow correctly by adding the modulus when needed. + /// + /// # Arguments + /// * `lhs` - Left-hand side value (minuend) + /// * `rhs` - Right-hand side value (subtrahend) + /// + /// # Returns + /// The result of `(lhs - rhs) mod m` + pub fn sub(self, lhs: Field, rhs: Field) -> Field { + // Safety: __sub_with_underflow is safe because we verify the subtraction equation below + let (result, underflow) = unsafe { __sub_with_underflow(lhs, rhs, self.m) }; + + // Verify the subtraction + if underflow { + assert(lhs + self.m == rhs + result, "Subtraction with underflow verification failed"); + } else { + assert(lhs == rhs + result, "Subtraction verification failed"); + } + + result + } + + /// Multiplies two values with modular reduction. + /// + /// Computes `(lhs * rhs) mod m` and returns the result. + /// The product is computed first, then reduced modulo the modulus. + /// + /// # Arguments + /// * `lhs` - Left-hand side value + /// * `rhs` - Right-hand side value + /// + /// # Returns + /// The result of `(lhs * rhs) mod m` + pub fn mul_mod(self, lhs: Field, rhs: Field) -> Field { + self.reduce_mod(lhs * rhs) + } + + /// Computes modular division: `lhs * rhs^(-1) mod m`. + /// + /// This is equivalent to multiplying `lhs` by the modular inverse of `rhs`. + /// The result satisfies: `(result * rhs) mod m = lhs mod m`. + /// + /// # Arguments + /// * `lhs` - The numerator + /// * `rhs` - The denominator (must be coprime with the modulus) + /// + /// # Returns + /// The result of `(lhs * rhs^(-1)) mod m` + /// + /// # Panics + /// The circuit will fail if `rhs` is not invertible modulo `m` (i.e., if + /// `gcd(rhs, m) != 1`). For prime moduli, any non-zero `rhs` is invertible. + pub fn div_mod(self, lhs: Field, rhs: Field) -> Field { + // Safety: __div_mod is safe because we verify result * rhs = lhs (mod m) below + let result = unsafe { __div_mod(lhs, rhs, self.m) }; + + // Verify: (result * rhs) mod m == lhs mod m + assert( + self.mul_mod(result, rhs) == self.reduce_mod(lhs), + "Division verification failed: result * rhs ≠ lhs (mod m)", + ); + + result + } + + /// Negates a value modulo m. + /// + /// Computes the additive inverse: `(-val) mod m = (m - val) mod m`. + /// Special case: negation of zero is zero. + /// + /// # Arguments + /// * `val` - The value to negate + /// + /// # Returns + /// The result of `(-val) mod m`, which satisfies `(val + result) mod m = 0` + pub fn neg(self, val: Field) -> Field { + // Safety: __neg is safe because we verify val + result = 0 (mod m) below + let result = unsafe { __neg(val, self.m) }; + + // Verify: val + result = 0 (mod m) + // Special case: if val = 0, result should be 0 + if val == 0 { + assert(result == 0, "Negation of zero should be zero"); + } else { + assert(val + result == self.m, "Negation verification failed"); + } + + result + } + + /// Computes the modular multiplicative inverse using Fermat's Little Theorem. + /// + /// For a prime modulus `m` and value `val` coprime to `m`, computes `val^(-1) mod m` + /// such that `(val * result) mod m = 1`. + /// + /// The implementation uses Fermat's Little Theorem: `val^(m-1) = 1 (mod m)`, + /// so `val^(-1) = val^(m-2) (mod m)`. + /// + /// # Arguments + /// * `val` - The value to invert (must be coprime with the modulus) + /// + /// # Returns + /// The modular inverse `val^(-1) mod m` such that `(val * result) mod m = 1` + /// + /// # Panics + /// The circuit will fail if `val` is not invertible modulo `m` (i.e., if + /// `gcd(val, m) != 1`). For prime moduli, any non-zero `val` is invertible. + pub fn inv_mod(self, val: Field) -> Field { + // Safety: __inv_mod is safe because we verify val * result = 1 (mod m) below + let result = unsafe { __inv_mod(val, self.m) }; + + // Verify: val * result = 1 (mod m) + assert(self.mul_mod(val, result) == 1, "Inverse verification failed"); + + result + } +} + +#[test] +fn test_reduce_mod_already_reduced() { + let value = 42; + let m = ModU128::new(100); + let result = m.reduce_mod(value); + assert(result == 42); +} + +#[test] +fn test_reduce_mod_needs_reduction() { + let value = 250; + let m = ModU128::new(100); + let result = m.reduce_mod(value); + assert(result == 50); +} + +#[test] +fn test_reduce_mod_exact_multiple() { + let value = 300; + let m = ModU128::new(100); + let result = m.reduce_mod(value); + assert(result == 0); +} + +#[test] +fn test_reduce_mod_large_value() { + let value = 123456789; + let m = ModU128::new(1000); + let result = m.reduce_mod(value); + assert(result == 789); +} + +#[test] +fn test_add_no_overflow() { + let a = 30; + let b = 40; + let m = ModU128::new(100); + let result = m.add(a, b); + assert(result == 70); +} + +#[test] +fn test_add_with_overflow() { + let a = 60; + let b = 50; + let m = ModU128::new(100); + let result = m.add(a, b); + assert(result == 10); // (60 + 50) mod 100 = 10 +} + +#[test] +fn test_add_exact_modulus() { + let a = 50; + let b = 50; + let m = ModU128::new(100); + let result = m.add(a, b); + assert(result == 0); +} + +#[test] +fn test_add_with_zero() { + let a = 42; + let b = 0; + let m = ModU128::new(100); + let result = m.add(a, b); + assert(result == 42); +} + +#[test] +fn test_sub_no_underflow() { + let a = 50; + let b = 30; + let m = ModU128::new(100); + let result = m.sub(a, b); + assert(result == 20); +} + +#[test] +fn test_sub_with_underflow() { + let a = 30; + let b = 50; + let m = ModU128::new(100); + let result = m.sub(a, b); + assert(result == 80); // (30 - 50 + 100) mod 100 = 80 +} + +#[test] +fn test_sub_equal_values() { + let a = 42; + let b = 42; + let m = ModU128::new(100); + let result = m.sub(a, b); + assert(result == 0); +} + +#[test] +fn test_sub_subtract_zero() { + let a = 42; + let b = 0; + let m = ModU128::new(100); + let result = m.sub(a, b); + assert(result == 42); +} +#[test] +fn test_mul_mod_small_values() { + let a = 6; + let b = 7; + let m = ModU128::new(100); + let result = m.mul_mod(a, b); + assert(result == 42); +} + +#[test] +fn test_mul_mod_with_reduction() { + let a = 12; + let b = 15; + let m = ModU128::new(100); + let result = m.mul_mod(a, b); + assert(result == 80); // 12 * 15 = 180, 180 mod 100 = 80 +} + +#[test] +fn test_mul_mod_result_zero() { + let a = 5; + let b = 20; + let m = ModU128::new(100); + let result = m.mul_mod(a, b); + assert(result == 0); // 5 * 20 = 100, 100 mod 100 = 0 +} + +#[test] +fn test_mul_mod_with_zero() { + let a = 42; + let b = 0; + let m = ModU128::new(100); + let result = m.mul_mod(a, b); + assert(result == 0); +} + +#[test] +fn test_mul_mod_large_values() { + let a = 123; + let b = 456; + let m = ModU128::new(1000); + let result = m.mul_mod(a, b); + assert(result == 88); // 123 * 456 = 56088, 56088 mod 1000 = 88 +} + +#[test] +fn test_neg_non_zero() { + let val = 30; + let m = ModU128::new(100); + let result = m.neg(val); + assert(result == 70); // 100 - 30 = 70 +} + +#[test] +fn test_neg_zero() { + let val = 0; + let m = ModU128::new(100); + let result = m.neg(val); + assert(result == 0); // Negation of 0 is 0, not m +} + +#[test] +fn test_neg_large_modulus() { + let val = 12345; + let m = ModU128::new(1000000); + let result = m.neg(val); + assert(result == 987655); // 1000000 - 12345 = 987655 +} + +#[test] +fn test_inv_mod_simple() { + let val = 3; + let m = ModU128::new(11); + let result = m.inv_mod(val); + // 3 * 4 = 12 = 1 (mod 11), so 3^(-1) = 4 (mod 11) + assert(result == 4); + // Verify: 3 * result = 1 (mod 11) + assert(m.mul_mod(val, result) == 1); +} + +#[test] +fn test_inv_mod_larger_prime() { + let val = 7; + let m = ModU128::new(13); + let result = m.inv_mod(val); + // Verify: 7 * result = 1 (mod 13) + assert(m.mul_mod(val, result) == 1); +} + +#[test] +fn test_inv_mod_with_result_verification() { + let val = 5; + let m = ModU128::new(17); + let result = m.inv_mod(val); + // Verify the inverse property + let product = m.mul_mod(val, result); + assert(product == 1); +} + +#[test] +fn test_inv_mod_coprime_values() { + let val = 9; + let m = ModU128::new(23); + let result = m.inv_mod(val); + assert(m.mul_mod(val, result) == 1); +} + +#[test] +fn test_div_mod_simple() { + let a = 6; + let b = 2; + let m = ModU128::new(11); + let result = m.div_mod(a, b); + assert(result == 3); // 6 / 2 = 3 +} + +#[test] +fn test_div_mod_with_inverse() { + let a = 7; + let b = 3; + let m = ModU128::new(11); + let result = m.div_mod(a, b); + // 3^(-1) mod 11 = 4 (since 3 * 4 = 12 = 1 mod 11) + // 7 * 4 = 28 = 6 (mod 11) + assert(result == 6); + // Verify: result * b = a (mod m) + assert(m.mul_mod(result, b) == a); +} + +#[test] +fn test_div_mod_verification() { + let a = 10; + let b = 3; + let m = ModU128::new(17); + let result = m.div_mod(a, b); + // Verify: result * b = a (mod m) + assert(m.mul_mod(result, b) == m.reduce_mod(a)); +} + +#[test] +fn test_div_mod_larger_values() { + let a = 250; + let b = 7; + let m = ModU128::new(97); + let result = m.div_mod(a, b); + // Verify: result * b = a (mod m) + let a_reduced = m.reduce_mod(a); // 250 mod 100 = 50 + assert(m.mul_mod(result, b) == a_reduced); +} + +#[test] +fn test_reduce_mod_function() { + let m = ModU128::new(7); + + // Test reduce_mod directly first + assert(m.reduce_mod(38) == 3); + assert(m.reduce_mod(6) == 6); + assert(m.reduce_mod(7) == 0); + assert(m.reduce_mod(14) == 0); +} + +#[test] +fn test_field_properties_additive_identity() { + let a = 42; + let m = ModU128::new(100); + // a + 0 = a + assert(m.add(a, 0) == a); +} + +#[test] +fn test_field_properties_multiplicative_identity() { + let a = 42; + let m = ModU128::new(100); + // a * 1 = a + assert(m.mul_mod(a, 1) == a); +} + +#[test] +fn test_field_properties_additive_inverse() { + let a = 42; + let m = ModU128::new(100); + let neg_a = m.sub(0, a); + // a + (-a) = 0 + assert(m.add(a, neg_a) == 0); +} + +#[test] +fn test_field_properties_commutativity_add() { + let a = 35; + let b = 47; + let m = ModU128::new(100); + // a + b = b + a + assert(m.add(a, b) == m.add(b, a)); +} + +#[test] +fn test_field_properties_commutativity_mul() { + let a = 7; + let b = 9; + let m = ModU128::new(100); + // a * b = b * a + assert(m.mul_mod(a, b) == m.mul_mod(b, a)); +} + +#[test] +fn test_field_properties_associativity_add() { + let a = 23; + let b = 34; + let c = 45; + let m = ModU128::new(100); + // (a + b) + c = a + (b + c) + let left = m.add(m.add(a, b), c); + let right = m.add(a, m.add(b, c)); + assert(left == right); +} + +#[test] +fn test_field_properties_associativity_mul() { + let a = 3; + let b = 7; + let c = 11; + let m = ModU128::new(100); + // (a * b) * c = a * (b * c) + let left = m.mul_mod(m.mul_mod(a, b), c); + let right = m.mul_mod(a, m.mul_mod(b, c)); + assert(left == right); +} + +#[test] +fn test_field_properties_distributivity() { + let a = 5; + let b = 7; + let c = 9; + let m = ModU128::new(100); + // a * (b + c) = (a * b) + (a * c) + let left = m.mul_mod(a, m.add(b, c)); + let right = m.add(m.mul_mod(a, b), m.mul_mod(a, c)); + assert(left == right); +} +#[test] +fn test_division_multiplication_inverse() { + let a = 35; + let b = 7; + let m = ModU128::new(97); + let quotient = m.div_mod(a, b); + let product = m.mul_mod(quotient, b); + assert(product == m.reduce_mod(a)); +} + +#[test] +fn test_inverse_of_inverse() { + let a = 7; + let m = ModU128::new(11); + // (a^(-1))^(-1) = a + let inv_a = m.inv_mod(a); + let inv_inv_a = m.inv_mod(inv_a); + assert(inv_inv_a == a); +} + +#[test] +fn test_operations_with_prime_modulus() { + let m = ModU128::new(97); // Prime number + let a = 42; + let b = 13; + + // Test addition + let sum = m.add(a, b); + assert(sum == 55); // 42 + 13 = 55 + + // Test subtraction + let diff = m.sub(a, b); + assert(diff == 29); // 42 - 13 = 29 + + // Test multiplication + let prod = m.mul_mod(a, b); + assert(prod == 61); // (42 * 13) mod 97 = 546 mod 97 = 61 + + // Test inverse: b * b^(-1) = 1 (mod m) + let inv = m.inv_mod(b); + assert(m.mul_mod(b, inv) == 1); + + // Test division: (a / b) * b = a (mod m) + let quot = m.div_mod(a, b); + assert(m.mul_mod(quot, b) == a); +} diff --git a/circuits/lib/src/math/modulo/mod.nr b/circuits/lib/src/math/modulo/mod.nr new file mode 100644 index 0000000000..d6a40f4211 --- /dev/null +++ b/circuits/lib/src/math/modulo/mod.nr @@ -0,0 +1,2 @@ +pub mod unconstrained_U128; +pub mod U128; diff --git a/circuits/lib/src/math/modulo/unconstrained_U128.nr b/circuits/lib/src/math/modulo/unconstrained_U128.nr new file mode 100644 index 0000000000..b721da8c35 --- /dev/null +++ b/circuits/lib/src/math/modulo/unconstrained_U128.nr @@ -0,0 +1,593 @@ +//! Unconstrained functions for modular u128 arithmetic. +//! +//! This module provides unconstrained functions that perform modular arithmetic +//! computations without generating circuit constraints. These functions are used +//! internally by the constrained operations in `U128` and should not be called +//! directly in circuits without proper verification. + +/// Computes quotient and remainder for value modulo q (unconstrained). +/// +/// This function performs integer division and modulo operations to compute +/// `value = q * quotient + remainder` where `0 <= remainder < q`. +/// +/// # Arguments +/// * `value` - The value to reduce +/// * `q` - The modulus +/// +/// # Returns +/// A tuple `(quotient, remainder)` where: +/// - `quotient = value / q` +/// - `remainder = value % q` +/// +/// # Safety +/// This is an unconstrained function. The result must be verified in constrained code. +pub unconstrained fn __compute_mod_reduction(value: Field, q: Field) -> (Field, Field) { + let value_u128 = value as u128; + let q_u128 = q as u128; + + let quotient_u128 = value_u128 / q_u128; + let remainder_u128 = value_u128 % q_u128; + + (quotient_u128 as Field, remainder_u128 as Field) +} + +/// Computes the negation of a value modulo m (unconstrained). +/// +/// Returns `(m - val) mod m`, with special handling for zero (returns 0). +/// +/// # Arguments +/// * `val` - The value to negate +/// * `m` - The modulus +/// +/// # Returns +/// The additive inverse `(-val) mod m` +/// +/// # Safety +/// This is an unconstrained function. The result must be verified in constrained code. +pub unconstrained fn __neg(val: Field, m: Field) -> Field { + if val == 0 { + 0 + } else { + m - val + } +} + +/// Subtracts two values with underflow handling (unconstrained). +/// +/// Computes `(lhs - rhs) mod m`, handling the case where `lhs < rhs` by adding +/// the modulus. Returns both the result and a flag indicating if underflow occurred. +/// +/// # Arguments +/// * `lhs` - Left-hand side value (minuend) +/// * `rhs` - Right-hand side value (subtrahend) +/// * `m` - The modulus +/// +/// # Returns +/// A tuple `(result, underflow)` where: +/// - `result = (lhs - rhs) mod m` +/// - `underflow = true` if `lhs < rhs`, `false` otherwise +/// +/// # Safety +/// This is an unconstrained function. The result must be verified in constrained code. +pub unconstrained fn __sub_with_underflow(lhs: Field, rhs: Field, m: Field) -> (Field, bool) { + let lhs_u128 = lhs as u128; + let rhs_u128 = rhs as u128; + let m_u128 = m as u128; + + let underflow = lhs_u128 < rhs_u128; + let result = if underflow { + (lhs_u128 + m_u128 - rhs_u128) as Field + } else { + (lhs_u128 - rhs_u128) as Field + }; + (result, underflow) +} + +/// Multiplies two values and returns both quotient and remainder (unconstrained). +/// +/// Computes `lhs * rhs = m * quotient + remainder` where `0 <= remainder < m`. +/// +/// # Arguments +/// * `lhs` - Left-hand side value +/// * `rhs` - Right-hand side value +/// * `m` - The modulus +/// +/// # Returns +/// A tuple `(quotient, remainder)` where `lhs * rhs = m * quotient + remainder` +/// +/// # Note +/// For u128 values, the product can overflow Field, but for typical use cases +/// (e.g., party IDs <= 100), this is safe. +/// +/// # Safety +/// This is an unconstrained function. The result must be verified in constrained code. +pub unconstrained fn __mul_with_quotient(lhs: Field, rhs: Field, m: Field) -> (Field, Field) { + // For u128 values, product can overflow Field + // But since our values are small (party IDs <= 100), this is safe + let product = lhs * rhs; + __compute_mod_reduction(product, m) +} + +/// Computes the modular multiplicative inverse using Fermat's Little Theorem (unconstrained). +/// +/// For a prime modulus `m` and value `val` coprime to `m`, computes `val^(-1) mod m` +/// using the identity: val^(-1) = val^(m-2) (mod m) (from Fermat's Little Theorem). +/// +/// # Arguments +/// * `val` - The value to invert (must be coprime with the modulus) +/// * `m` - The modulus (should be prime for this method to work correctly) +/// +/// # Returns +/// The modular inverse `val^(-1) mod m` such that `(val * result) mod m = 1` +/// +/// # Safety +/// This is an unconstrained function. The result must be verified in constrained code. +pub unconstrained fn __inv_mod(val: Field, m: Field) -> Field { + // by Fermat's Little Theorem: val^(m-1)= 1 mod m + __pow_mod(val, m - 2, m) +} + +/// Computes modular division: `lhs * rhs^(-1) mod m` (unconstrained). +/// +/// This is equivalent to multiplying `lhs` by the modular inverse of `rhs`. +/// +/// # Arguments +/// * `lhs` - The numerator +/// * `rhs` - The denominator (must be coprime with the modulus) +/// * `m` - The modulus +/// +/// # Returns +/// The result of `(lhs * rhs^(-1)) mod m` +/// +/// # Safety +/// This is an unconstrained function. The result must be verified in constrained code. +pub unconstrained fn __div_mod(lhs: Field, rhs: Field, m: Field) -> Field { + let rhs_inv = __inv_mod(rhs, m); + __mul_mod(lhs, rhs_inv, m) +} + +/// Computes modular exponentiation: `base^exp mod m` (unconstrained). +/// +/// Uses the binary exponentiation method (also known as square-and-multiply) +/// for efficient computation of large powers. +/// +/// # Arguments +/// * `base` - The base value +/// * `exp` - The exponent +/// * `m` - The modulus +/// +/// # Returns +/// The result of `base^exp mod m` +/// +/// # Safety +/// This is an unconstrained function. The result must be verified in constrained code. +pub unconstrained fn __pow_mod(base: Field, exp: Field, m: Field) -> Field { + let mut result = 1 as Field; + let (_, base_mod) = __compute_mod_reduction(base, m); + let mut current_base = base_mod; + let mut e = exp as u128; + + while e > 0 { + if (e % 2) == 1 { + result = __mul_mod(result, current_base, m); + } + current_base = __mul_mod(current_base, current_base, m); + e = e / 2; + } + + result +} + +/// Multiplies two values with modular reduction (unconstrained). +/// +/// Computes `(lhs * rhs) mod m` and returns only the remainder. +/// +/// # Arguments +/// * `lhs` - Left-hand side value +/// * `rhs` - Right-hand side value +/// * `m` - The modulus +/// +/// # Returns +/// The result of `(lhs * rhs) mod m` +/// +/// # Safety +/// This is an unconstrained function. The result must be verified in constrained code. +pub unconstrained fn __mul_mod(lhs: Field, rhs: Field, m: Field) -> Field { + let (_, r) = __mul_with_quotient(lhs, rhs, m); + r +} + +// ------------------------------ TESTS ------------------------------ +// Note: All unsafe blocks in the following tests are safe because we are testing +// unconstrained functions in a controlled test environment. These functions are +// designed to be called from unsafe blocks or other unconstrained functions. +// Each unsafe block is used to call an unconstrained function for testing purposes. + +#[test] +fn test_compute_mod_reduction_simple() { + // Safety: Test function calling unconstrained helper + let (q, r) = unsafe { __compute_mod_reduction(42, 10) }; + assert(q == 4); // 42 / 10 = 4 + assert(r == 2); // 42 % 10 = 2 + // Verify: 42 = 10 * 4 + 2 + assert(10 * q + r == 42); +} + +#[test] +fn test_compute_mod_reduction_exact_multiple() { + // Safety: Test function calling unconstrained helper + let (q, r) = unsafe { __compute_mod_reduction(100, 10) }; + assert(q == 10); // 100 / 10 = 10 + assert(r == 0); // 100 % 10 = 0 + assert(10 * q + r == 100); +} + +#[test] +fn test_compute_mod_reduction_large_value() { + // Safety: Test function calling unconstrained helper + let (q, r) = unsafe { __compute_mod_reduction(12345, 100) }; + assert(q == 123); // 12345 / 100 = 123 + assert(r == 45); // 12345 % 100 = 45 + assert(100 * q + r == 12345); +} + +#[test] +fn test_compute_mod_reduction_smaller_than_modulus() { + // Safety: Test function calling unconstrained helper + let (q, r) = unsafe { __compute_mod_reduction(7, 10) }; + assert(q == 0); // 7 / 10 = 0 + assert(r == 7); // 7 % 10 = 7 + assert(10 * q + r == 7); +} + +#[test] +fn test_neg_zero() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __neg(0, 100) }; + assert(result == 0); // Negation of zero is zero +} + +#[test] +fn test_neg_non_zero() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __neg(30, 100) }; + assert(result == 70); // 100 - 30 = 70 +} + +#[test] +fn test_neg_large_value() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __neg(12345, 100000) }; + assert(result == 87655); // 100000 - 12345 = 87655 +} + +#[test] +fn test_neg_verification() { + let val: Field = 42; + let m: Field = 97; + // Safety: Test function calling unconstrained helper + let neg_val = unsafe { __neg(val, m) }; + // Verify: val + neg_val = 0 (mod m) + let sum = val + neg_val; + // Safety: Test function calling unconstrained helper + let (_, remainder) = unsafe { __compute_mod_reduction(sum, m) }; + assert(remainder == 0); +} + +#[test] +fn test_sub_with_underflow_no_underflow() { + // Safety: Test function calling unconstrained helper + let (result, underflow) = unsafe { __sub_with_underflow(50, 30, 100) }; + assert(underflow == false); + assert(result == 20); // 50 - 30 = 20 +} + +#[test] +fn test_sub_with_underflow_with_underflow() { + // Safety: Test function calling unconstrained helper + let (result, underflow) = unsafe { __sub_with_underflow(30, 50, 100) }; + assert(underflow == true); + assert(result == 80); // (30 - 50 + 100) mod 100 = 80 +} + +#[test] +fn test_sub_with_underflow_equal_values() { + // Safety: Test function calling unconstrained helper + let (result, underflow) = unsafe { __sub_with_underflow(42, 42, 100) }; + assert(underflow == false); + assert(result == 0); +} + +#[test] +fn test_sub_with_underflow_verification() { + let lhs: Field = 30; + let rhs: Field = 50; + let m: Field = 100; + // Safety: Test function calling unconstrained helper + let (result, underflow) = unsafe { __sub_with_underflow(lhs, rhs, m) }; + + if underflow { + // Verify: lhs + m = rhs + result + assert(lhs + m == rhs + result); + } else { + // Verify: lhs = rhs + result + assert(lhs == rhs + result); + } +} + +#[test] +fn test_mul_with_quotient_simple() { + // Safety: Test function calling unconstrained helper + let (q, r) = unsafe { __mul_with_quotient(6, 7, 10) }; + assert(q == 4); // (6 * 7) / 10 = 42 / 10 = 4 + assert(r == 2); // (6 * 7) % 10 = 42 % 10 = 2 + // Verify: 6 * 7 = 10 * 4 + 2 + assert(6 * 7 == 10 * q + r); +} + +#[test] +fn test_mul_with_quotient_with_reduction() { + // Safety: Test function calling unconstrained helper + let (q, r) = unsafe { __mul_with_quotient(12, 15, 100) }; + assert(q == 1); // (12 * 15) / 100 = 180 / 100 = 1 + assert(r == 80); // (12 * 15) % 100 = 180 % 100 = 80 + assert(12 * 15 == 100 * q + r); +} + +#[test] +fn test_mul_with_quotient_exact_multiple() { + // Safety: Test function calling unconstrained helper + let (q, r) = unsafe { __mul_with_quotient(5, 20, 100) }; + assert(q == 1); // (5 * 20) / 100 = 100 / 100 = 1 + assert(r == 0); // (5 * 20) % 100 = 100 % 100 = 0 + assert(5 * 20 == 100 * q + r); +} + +#[test] +fn test_mul_with_quotient_verification() { + let lhs: Field = 123; + let rhs: Field = 456; + let m: Field = 1000; + // Safety: Test function calling unconstrained helper + let (q, r) = unsafe { __mul_with_quotient(lhs, rhs, m) }; + // Verify: lhs * rhs = m * q + r + assert(lhs * rhs == m * q + r); + // Verify remainder is in range [0, m) + assert((r as u128) < (m as u128)); +} + +#[test] +fn test_mul_mod_simple() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __mul_mod(6, 7, 10) }; + assert(result == 2); // (6 * 7) mod 10 = 42 mod 10 = 2 +} + +#[test] +fn test_mul_mod_with_reduction() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __mul_mod(12, 15, 100) }; + assert(result == 80); // (12 * 15) mod 100 = 180 mod 100 = 80 +} + +#[test] +fn test_mul_mod_exact_multiple() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __mul_mod(5, 20, 100) }; + assert(result == 0); // (5 * 20) mod 100 = 100 mod 100 = 0 +} + +#[test] +fn test_mul_mod_with_zero() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __mul_mod(42, 0, 100) }; + assert(result == 0); +} + +#[test] +fn test_mul_mod_commutative() { + let a: Field = 7; + let b: Field = 9; + let m: Field = 100; + // Safety: Test function calling unconstrained helper + let mul_a_b = unsafe { __mul_mod(a, b, m) }; + // Safety: Test function calling unconstrained helper + let mul_b_a = unsafe { __mul_mod(b, a, m) }; + // Verify: a * b = b * a + assert(mul_a_b == mul_b_a); +} + +#[test] +fn test_pow_mod_simple() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __pow_mod(2, 3, 10) }; + assert(result == 8); // 2^3 mod 10 = 8 mod 10 = 8 +} + +#[test] +fn test_pow_mod_with_reduction() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __pow_mod(2, 10, 100) }; + assert(result == 24); // 2^10 = 1024, 1024 mod 100 = 24 +} + +#[test] +fn test_pow_mod_exponent_one() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __pow_mod(7, 1, 100) }; + assert(result == 7); // 7^1 mod 100 = 7 +} + +#[test] +fn test_pow_mod_exponent_zero() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __pow_mod(7, 0, 100) }; + assert(result == 1); // 7^0 mod 100 = 1 +} + +#[test] +fn test_pow_mod_base_zero() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __pow_mod(0, 5, 100) }; + assert(result == 0); // 0^5 mod 100 = 0 +} + +#[test] +fn test_pow_mod_large_exponent() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __pow_mod(3, 7, 97) }; + // 3^7 = 2187, 2187 mod 97 = 53 + assert(result == 53); +} + +#[test] +fn test_pow_mod_fermat_little_theorem() { + // For prime modulus p and value a, a^(p-1) = 1 (mod p) + let a: Field = 3; + let p: Field = 11; // Prime + // Safety: Test function calling unconstrained helper + let result = unsafe { __pow_mod(a, p - 1, p) }; + assert(result == 1); +} + +#[test] +fn test_inv_mod_simple() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __inv_mod(3, 11) }; + // 3 * 4 = 12 = 1 (mod 11), so 3^(-1) = 4 (mod 11) + assert(result == 4); + // Verify: 3 * result = 1 (mod 11) + // Safety: Test function calling unconstrained helper + assert(unsafe { __mul_mod(3, result, 11) } == 1); +} + +#[test] +fn test_inv_mod_larger_prime() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __inv_mod(7, 13) }; + // Verify: 7 * result = 1 (mod 13) + // Safety: Test function calling unconstrained helper + assert(unsafe { __mul_mod(7, result, 13) } == 1); +} + +#[test] +fn test_inv_mod_another_prime() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __inv_mod(5, 17) }; + // Verify: 5 * result = 1 (mod 17) + // Safety: Test function calling unconstrained helper + assert(unsafe { __mul_mod(5, result, 17) } == 1); +} + +#[test] +fn test_inv_mod_inverse_of_inverse() { + let a: Field = 7; + let m: Field = 11; + // Safety: Test function calling unconstrained helper + let inv_a = unsafe { __inv_mod(a, m) }; + // Safety: Test function calling unconstrained helper + let inv_inv_a = unsafe { __inv_mod(inv_a, m) }; + // (a^(-1))^(-1) = a + assert(inv_inv_a == a); +} + +#[test] +fn test_div_mod_simple() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __div_mod(6, 2, 11) }; + assert(result == 3); // 6 / 2 = 3 + // Verify: result * 2 = 6 (mod 11) + // Safety: Test function calling unconstrained helper + assert(unsafe { __mul_mod(result, 2, 11) } == 6); +} + +#[test] +fn test_div_mod_with_inverse() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __div_mod(7, 3, 11) }; + // 3^(-1) mod 11 = 4 (since 3 * 4 = 12 = 1 mod 11) + // 7 * 4 = 28 = 6 (mod 11) + assert(result == 6); + // Verify: result * 3 = 7 (mod 11) + // Safety: Test function calling unconstrained helper + assert(unsafe { __mul_mod(result, 3, 11) } == 7); +} + +#[test] +fn test_div_mod_verification() { + let a: Field = 10; + let b: Field = 3; + let m: Field = 17; + // Safety: Test function calling unconstrained helper + let result = unsafe { __div_mod(a, b, m) }; + // Verify: result * b = a (mod m) + // Safety: Test function calling unconstrained helper + assert(unsafe { __mul_mod(result, b, m) } == a); +} + +#[test] +fn test_div_mod_larger_values() { + let a: Field = 250; + let b: Field = 7; + let m: Field = 97; + // Safety: Test function calling unconstrained helper + let result = unsafe { __div_mod(a, b, m) }; + // Verify: result * b = a (mod m) + // Safety: Test function calling unconstrained helper + let (_, a_reduced) = unsafe { __compute_mod_reduction(a, m) }; // 250 mod 97 = 56 + // Safety: Test function calling unconstrained helper + assert(unsafe { __mul_mod(result, b, m) } == a_reduced); +} + +#[test] +fn test_div_mod_by_one() { + // Safety: Test function calling unconstrained helper + let result = unsafe { __div_mod(42, 1, 100) }; + assert(result == 42); // 42 / 1 = 42 + // Safety: Test function calling unconstrained helper + assert(unsafe { __mul_mod(result, 1, 100) } == 42); +} + +#[test] +fn test_all_operations_consistency() { + // Test that all operations work together correctly + let m: Field = 97; // Prime + let a: Field = 42; + let b: Field = 13; + + // Test: (a + b) mod m + let sum = a + b; + // Safety: Test function calling unconstrained helper + let (_, sum_reduced) = unsafe { __compute_mod_reduction(sum, m) }; + assert(sum_reduced == 55); + + // Test: (a - b) mod m using subtraction + // Safety: Test function calling unconstrained helper + let (diff, _) = unsafe { __sub_with_underflow(a, b, m) }; + assert(diff == 29); + + // Test: (a * b) mod m + // Safety: Test function calling unconstrained helper + let prod = unsafe { __mul_mod(a, b, m) }; + assert(prod == 61); // (42 * 13) mod 97 = 546 mod 97 = 61 + + // Test: b^(-1) mod m + // Safety: Test function calling unconstrained helper + let inv = unsafe { __inv_mod(b, m) }; + // Safety: Test function calling unconstrained helper + assert(unsafe { __mul_mod(b, inv, m) } == 1); + + // Test: (a / b) mod m + // Safety: Test function calling unconstrained helper + let quot = unsafe { __div_mod(a, b, m) }; + // Safety: Test function calling unconstrained helper + assert(unsafe { __mul_mod(quot, b, m) } == a); + + // Test: (-a) mod m + // Safety: Test function calling unconstrained helper + let neg = unsafe { __neg(a, m) }; + let sum_neg = a + neg; + // Safety: Test function calling unconstrained helper + let (_, sum_neg_reduced) = unsafe { __compute_mod_reduction(sum_neg, m) }; + assert(sum_neg_reduced == 0); +} diff --git a/circuits/lib/src/math/polynomial.nr b/circuits/lib/src/math/polynomial.nr new file mode 100644 index 0000000000..f034f8786f --- /dev/null +++ b/circuits/lib/src/math/polynomial.nr @@ -0,0 +1,457 @@ +use super::modulo::U128::ModU128; + +/// Polynomial structure representing a polynomial of degree N-1. +/// +/// A polynomial P(X) = a_{N-1} * X^{N-1} + a_{N-2} * X^{N-2} + ... + a_1 * X + a_0 +/// is represented as an array of coefficients where coefficients[0] = a_{N-1} (highest degree) +/// and coefficients[N-1] = a_0 (constant term). +pub struct Polynomial { + /// Array of polynomial coefficients in descending degree order + /// coefficients[0] = coefficient of X^{N-1} (highest degree term) + /// coefficients[N-1] = constant term (degree 0) + pub coefficients: [Field; N], +} + +impl Polynomial { + /// Creates a new polynomial from an array of coefficients. + /// + /// # Arguments + /// * `coefficients` - Array of N coefficients in descending degree order + /// coefficients[0] = coefficient of X^{N-1} + /// coefficients[N-1] = constant term + /// + /// # Returns + /// A new Polynomial instance with the specified coefficients + pub fn new(coefficients: [Field; N]) -> Self { + Polynomial { coefficients } + } + + /// Adds two polynomials. + /// + /// # Arguments + /// * `other` - The polynomial to add to the current polynomial. + /// + /// # Returns + /// A new polynomial with the coefficients added. + pub fn add(self, other: Self) -> Self { + let mut result = Self::new([0; N]); + + for i in 0..N { + result.coefficients[i] = self.coefficients[i] + other.coefficients[i]; + } + + result + } + + /// Subtracts two polynomials. + /// + /// # Arguments + /// * `other` - The polynomial to subtract from the current polynomial. + /// + /// # Returns + /// A new polynomial with the coefficients subtracted. + pub fn sub(self, other: Self) -> Self { + let mut result = Self::new([0; N]); + + for i in 0..N { + result.coefficients[i] = self.coefficients[i] - other.coefficients[i]; + } + + result + } + + /// Multiplies a polynomial by a scalar. + /// + /// # Arguments + /// * `scalar` - The scalar to multiply the polynomial by. + /// + /// # Returns + /// A new polynomial with the coefficients multiplied by the scalar. + pub fn mul_scalar(self, scalar: Field) -> Self { + let mut result = Self::new([0; N]); + + for i in 0..N { + result.coefficients[i] = self.coefficients[i] * scalar; + } + + result + } + + /// Evaluates the polynomial at a given point using Horner's method. + /// + /// Horner's method computes P(x) = a_{N-1} * x^{N-1} + ... + a_1 * x + a_0 + /// as ((...((a_{N-1} * x + a_{N-2}) * x + a_{N-3}) * x + ...) * x + a_0) + /// This approach require n multiplications and n additions to evaluate the polynomial. + /// + /// # Arguments + /// * `x` - The point at which to evaluate the polynomial. + /// + /// # Returns + /// The value of the polynomial at point x: P(x). + pub fn eval(self, x: Field) -> Field { + let mut result = self.coefficients[0]; + + for i in 1..self.coefficients.len() { + result = result * x + self.coefficients[i]; + } + + result + } + + /// Evaluates the polynomial at a given point with modular reduction. + /// + /// This function computes `P(x) mod q` using Horner's method with intermediate + /// modular reductions to prevent overflow. The result is guaranteed to be in + /// the range `[0, q)`. + /// + /// The function performs lazy reduction: it only reduces the accumulator modulo + /// `q` when it exceeds the modulus, which is more efficient than reducing after + /// every operation while still preventing overflow. + /// + /// # Arguments + /// * `x` - The point at which to evaluate the polynomial + /// * `q` - The modular arithmetic context containing the modulus + /// + /// # Returns + /// The value `P(x) mod q` in the range `[0, q)` + pub fn eval_mod(self, x: Field, q: ModU128) -> Field { + let m = q.get_mod_field(); + let mut acc = self.coefficients[0]; + let len = self.coefficients.len(); + + for i in 1..len { + acc = acc * x + self.coefficients[i]; + // Only reduce if accumulator exceeds q + if acc as u64 >= m as u64 { + acc = q.reduce_mod(acc); + } + } + + // Final reduction to ensure result is in [0, q) + if acc as u64 >= m as u64 { + q.reduce_mod(acc) + } else { + acc + } + } + + /// Performs range checking on polynomial coefficients using asymmetric bounds. + /// + /// This function constrains all polynomial coefficients to be in the range [lower_bound, upper_bound]. + /// It uses a shifting technique to handle negative numbers efficiently: + /// 1. Shifts each coefficient by adding `lower_bound`: c' = c + lower_bound + /// 2. Checks that shifted coefficients are in [0, upper_bound + lower_bound] using bit-size assertions + /// 3. This ensures original coefficients are in [lower_bound, upper_bound] + /// + /// The function uses two bit-size checks per coefficient to ensure the value is within bounds: + /// - `shifted_coefficient.assert_max_bit_size::()` ensures c' >= 0 + /// - `(range_size - shifted_coefficient).assert_max_bit_size::()` ensures c' <= range_size + /// + /// # Arguments + /// * `upper_bound` - The upper bound for coefficient range checking + /// * `lower_bound` - The lower bound for coefficient range checking + /// Coefficients must satisfy: lower_bound <= c <= upper_bound + /// + /// # Generic Parameters + /// * `BIT` - The bit-length of the total range `upper_bound - lower_bound` + /// (choose `BIT` so `upper_bound - lower_bound < 2^BIT`). Since all checked + /// values lie in `[0, upper_bound + lower_bound]`, they cannot exceed `BIT + 1` bits. + /// + /// # Panics + /// This function will cause the circuit to fail if any coefficient is outside + /// the specified bounds. + pub fn range_check_2bounds(self, upper_bound: Field, lower_bound: Field) { + let range_size = lower_bound + upper_bound; + + for i in 0..self.coefficients.len() { + let shifted_coefficient = self.coefficients[i] + lower_bound; + + shifted_coefficient.assert_max_bit_size::(); + (range_size - shifted_coefficient).assert_max_bit_size::(); + } + } + + /// Performs range checking on polynomial coefficients for the range [0, upper_bound). + /// + /// This function constrains all polynomial coefficients to be non-negative and + /// strictly less than `upper_bound`. It uses bit-size assertions to verify that + /// coefficients are in the valid range. + /// + /// The function performs two checks per coefficient: + /// 1. `coeff.assert_max_bit_size::()` ensures `coeff >= 0` and `coeff < 2^BIT` + /// 2. `(upper_bound - 1 - coeff).assert_max_bit_size::()` ensures `coeff < upper_bound` + /// + /// # Arguments + /// * `upper_bound` - The exclusive upper bound for coefficient range checking. + /// Coefficients must satisfy: `0 <= c < upper_bound` + /// + /// # Generic Parameters + /// * `BIT` - The bit-length parameter. Must satisfy `upper_bound <= 2^BIT` for + /// the range check to work correctly. + /// + /// # Panics + /// This function will cause the circuit to fail if any coefficient is outside + /// the range `[0, upper_bound)`. + pub fn range_check_standard(self, upper_bound: Field) { + for i in 0..self.coefficients.len() { + let coeff = self.coefficients[i]; + // Check coeff >= 0 and coeff < 2^BIT + coeff.assert_max_bit_size::(); + // Check coeff <= upper_bound - 1 (i.e., coeff < upper_bound) + (upper_bound - 1 - coeff).assert_max_bit_size::(); + } + } + + /// Performs range checking on polynomial coefficients for the range [0, 2^BIT). + /// + /// This is a specialized range check for coefficients that must be non-negative + /// and less than a power of two. It's more efficient than `range_check_standard` + /// when the upper bound is exactly `2^BIT` because it only needs a single + /// bit-size assertion per coefficient. + /// + /// The function verifies that each coefficient satisfies: + /// - `coeff >= 0` (implicit from bit-size check) + /// - `coeff < 2^BIT` (enforced by `assert_max_bit_size::()`) + /// + /// # Generic Parameters + /// * `BIT` - The bit-length parameter. Coefficients must satisfy: `0 <= c < 2^BIT` + /// + /// # Panics + /// This function will cause the circuit to fail if any coefficient is outside + /// the range `[0, 2^BIT)`. + pub fn range_check_power_of_two(self) { + for i in 0..self.coefficients.len() { + self.coefficients[i].assert_max_bit_size::(); + } + } +} + +#[test] +fn test_polynomial_eval() { + let coeffs = [1, 2, 3]; // represents 1x^2 + 2x + 3 + let poly = Polynomial::new(coeffs); + + let x = 2; // evaluate at x = 2 + let result = poly.eval(x); + + // (1 * 2^2) + (2 * 2) + 3 = 4 + 4 + 3 = 11 + assert(result == 11); +} + +#[test] +fn test_polynomial_eval_zero() { + let coeffs = [1, -2, 1]; // x^2 - 2x + 1 = (x-1)^2 + let poly = Polynomial::new(coeffs); + + let x = 1; // evaluate at x = 1, should be 0 + let result = poly.eval(x); + + assert(result == 0); +} + +#[test] +fn test_polynomial_bounds() { + let coeffs = [-16, 240, 242]; + let poly = Polynomial::new(coeffs); + + // Test double bounds check - constrains to [-240, 242] + poly.range_check_2bounds::<8>(242, 240); +} + +#[test(should_fail_with = "assert_max_bit_size")] +fn test_polynomial_out_of_bounds_coefficients() { + let coeffs = [-100]; + let poly = Polynomial::new(coeffs); + + // Test double bounds check - constrains to [-98, 99] + // Should fail because -100 is out of bounds. + poly.range_check_2bounds::<7>(99, 98); +} + +#[test] +fn test_polynomial_add() { + let coeffs1 = [1, 2, 3]; // 1x^2 + 2x + 3 + let coeffs2 = [4, 5, 6]; // 4x^2 + 5x + 6 + let poly1 = Polynomial::new(coeffs1); + let poly2 = Polynomial::new(coeffs2); + + let result = poly1.add(poly2); + + // Expected: (1+4)x^2 + (2+5)x + (3+6) = 5x^2 + 7x + 9 + assert(result.coefficients[0] == 5); + assert(result.coefficients[1] == 7); + assert(result.coefficients[2] == 9); +} + +#[test] +fn test_polynomial_sub() { + let coeffs1 = [5, 7, 9]; // 5x^2 + 7x + 9 + let coeffs2 = [1, 2, 3]; // 1x^2 + 2x + 3 + let poly1 = Polynomial::new(coeffs1); + let poly2 = Polynomial::new(coeffs2); + + let result = poly1.sub(poly2); + + // Expected: (5-1)x^2 + (7-2)x + (9-3) = 4x^2 + 5x + 6 + assert(result.coefficients[0] == 4); + assert(result.coefficients[1] == 5); + assert(result.coefficients[2] == 6); +} + +#[test] +fn test_polynomial_mul_scalar() { + let coeffs = [1, 2, 3]; // 1x^2 + 2x + 3 + let poly = Polynomial::new(coeffs); + let scalar = 5; + + let result = poly.mul_scalar(scalar); + + // Expected: 5x^2 + 10x + 15 + assert(result.coefficients[0] == 5); + assert(result.coefficients[1] == 10); + assert(result.coefficients[2] == 15); +} + +#[test] +fn test_polynomial_mul_scalar_zero() { + let coeffs = [1, 2, 3]; + let poly = Polynomial::new(coeffs); + let scalar = 0; + + let result = poly.mul_scalar(scalar); + + // Expected: 0x^2 + 0x + 0 = 0 + assert(result.coefficients[0] == 0); + assert(result.coefficients[1] == 0); + assert(result.coefficients[2] == 0); +} + +#[test] +fn test_eval_mod_simple() { + // Test without initial reduction - simple case + // p(x) = x + 1 at x=5od 7 + // Expected: (5 + 1) mod 7 = 6 + let q = ModU128::new(7); + + let poly1 = Polynomial::new([1, 1]); + let result1 = poly1.eval_mod(5, q); + assert(result1 == 6); + + // Test: p(x) = 2x + 3 at x=5od 7 + // Expected: (10 + 3) mod 7 = 13 mod 7 = 6 + let poly2 = Polynomial::new([2, 3]); + let result2 = poly2.eval_mod(5, q); + assert(result2 == 6); +} + +#[test] +fn test_eval_mod_degree_2() { + // p(x) = x^2 + 2x + 3 at x=5od 7 + // Using Horner's method: ((1)*5 + 2)*5 + 3 = (5+2)*5 + 3 = 7*5 + 3 = 35 + 3 = 38 + // 38 mod 7 = 3 (since 38 = 5*7 + 3) + let q = ModU128::new(7); + + let poly = Polynomial::new([1, 2, 3]); + let result = poly.eval_mod(5, q); + assert(result == 3); +} + +#[test] +fn test_eval_mod() { + // Test 1: Simple polynomial x^2 + 2x + 3 at x=5od 7 + // Expected: (25 + 10 + 3) mod 7 = 38 mod 7 = 3 + let q = ModU128::new(7); + + let poly1 = Polynomial::new([1, 2, 3]); + let result1 = poly1.eval_mod(5, q); + assert(result1 == 3); + + // Test 2: Higher degree polynomialod small prime + // p(x) = x^3 + x^2 + x + 1 at x=2od 11 + // Expected: (8 + 4 + 2 + 1) mod 11 = 15 mod 11 = 4 + let q = ModU128::new(11); + + let poly2 = Polynomial::new([1, 1, 1, 1]); + let result2 = poly2.eval_mod(2, q); + assert(result2 == 4); + + // Test 3: Polynomial with larger coefficients + // p(x) = 100x^2 + 50x + 25 at x=10od 73 + // Expected: (10000 + 500 + 25) mod 73 = 10525 mod 73 = 13 + let q = ModU128::new(73); + + let poly3 = Polynomial::new([100, 50, 25]); + let result3 = poly3.eval_mod(10, q); + assert(result3 == 13); + + // Test 4: Result should be less than modulus + let poly4 = Polynomial::new([5, 3, 7]); + let q = ModU128::new(17); + let result4 = poly4.eval_mod(4, q); + assert(result4 as u64 < q.get_mod_field() as u64); + + // Test 5: Compare with regular eval for small values + let poly5 = Polynomial::new([1, 2, 1]); + let x = 3; + let q = ModU128::new(1000); + let result5 = poly5.eval_mod(x, q); + let expected5 = poly5.eval(x); + assert(result5 == expected5); + + // Test 6: Zero polynomial + let poly6 = Polynomial::new([0, 0, 0]); + let q = ModU128::new(13); + let result6 = poly6.eval_mod(100, q); + assert(result6 == 0); +} + +#[test] +fn test_large_party_ids_scenario() { + // Simulating party IDs in range [1, 100] + let party_id_1 = 42; + let party_id_2 = 73; + let m = ModU128::new(288230376151711717); // ~58 bits + + // Operations that would be used in Lagrange coefficients + let product = m.mul_mod(party_id_1, party_id_2); + let diff = m.sub(party_id_2, party_id_1); + + assert(product == 3066); + assert(diff == 31); +} + +#[test] +fn test_eval_vs_eval_mod() { + // Compare eval and eval_mod for small values where no reduction should occur + let poly = Polynomial::new([1, 2, 3]); + let x = 2; + let q = ModU128::new(1000); // Large enough that no reduction happens + + let result_normal = poly.eval(x); + let result_mod = poly.eval_mod(x, q); + + // They should be equal: (1)*2 + 2)*2 + 3 = (2+2)*2 + 3 = 4*2 + 3 = 11 + assert(result_normal == 11); + assert(result_mod == 11); +} + +#[test] +fn test_eval_mod_step_by_step() { + // p(x) = x + 1 at x=5od 7 + // Step by step: acc = 1, then acc = 1*5 + 1 = 6 + let poly = Polynomial::new([1, 1]); + + // Manually compute + let mut acc = 1; // coefficients[0] + acc = acc * 5 + 1; // = 6 + assert(acc == 6); + + // Now with reduce_mod + let m = ModU128::new(7); + let reduced = m.reduce_mod(acc); + assert(reduced == 6); + + // Now test the actual function + let result = poly.eval_mod(5, m); + assert(result == 6); +} diff --git a/circuits/crates/libs/safe/src/lib.nr b/circuits/lib/src/math/safe.nr similarity index 100% rename from circuits/crates/libs/safe/src/lib.nr rename to circuits/lib/src/math/safe.nr diff --git a/scripts/lint-circuits.sh b/scripts/lint-circuits.sh index 12301ad3aa..709891b74e 100755 --- a/scripts/lint-circuits.sh +++ b/scripts/lint-circuits.sh @@ -10,18 +10,44 @@ fi # Ensure we're in the right directory. cd circuits -# Checking circuit format. -echo "Checking circuit format..." -if ! (nargo fmt --check); then - echo "Error: Circuit format check failed" - exit 1 -fi +# Directories to check +DIRS=("lib" "bin/aggregation" "bin/insecure" "bin/production") -# Check/validate the circuit libraries. -echo "Checking Noir circuit libraries..." -if ! (nargo check --workspace); then - echo "Error: Noir circuit check failed" - exit 1 -fi +for dir in "${DIRS[@]}"; do + if [ ! -d "$dir" ]; then + echo "Warning: Directory $dir does not exist, skipping..." + continue + fi + + echo "Checking $dir..." + cd "$dir" + + # Find all package directories and create empty Prover.toml to prevent nargo from creating them + created_files=() + while IFS= read -r -d '' pkg_dir; do + prover_file="${pkg_dir}/Prover.toml" + if [ ! -f "$prover_file" ]; then + touch "$prover_file" + created_files+=("$prover_file") + fi + done < <(find . -name "Nargo.toml" -type f -print0 2>/dev/null | xargs -0 dirname 2>/dev/null || true) + + # Checking circuit format. + if ! (nargo fmt --check); then + echo "Error: Circuit format check failed in $dir" + exit 1 + fi + + # Check/validate the circuit libraries. + if ! (nargo check); then + echo "Error: Noir circuit check failed in $dir" + exit 1 + fi + + # Remove all Prover.toml files (they're generated by nargo and in .gitignore) + find . -name "Prover.toml" -type f -delete + + cd - > /dev/null +done echo "Noir circuits checked successfully" diff --git a/scripts/test-circuits.sh b/scripts/test-circuits.sh index 591b8817eb..d77eacd839 100755 --- a/scripts/test-circuits.sh +++ b/scripts/test-circuits.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -cd circuits +cd circuits/lib nargo test --workspace echo "Noir circuits tested successfully" \ No newline at end of file From b875a0474e50ddb0ae538808ac7c25480a031c36 Mon Sep 17 00:00:00 2001 From: Cedoor Date: Fri, 16 Jan 2026 16:34:51 +0100 Subject: [PATCH 02/30] refactor: update crisp circuits to use new pvss circuits --- examples/CRISP/circuits/Nargo.toml | 4 +- .../CRISP/circuits/src/ciphertext_addition.nr | 16 ++-- examples/CRISP/circuits/src/hash.nr | 5 +- examples/CRISP/circuits/src/main.nr | 67 +++++++------- examples/CRISP/circuits/src/utils.nr | 2 +- .../contracts/CRISPVerifier.sol | 90 +++++++++---------- 6 files changed, 93 insertions(+), 91 deletions(-) diff --git a/examples/CRISP/circuits/Nargo.toml b/examples/CRISP/circuits/Nargo.toml index dc002856f5..82d2db6719 100644 --- a/examples/CRISP/circuits/Nargo.toml +++ b/examples/CRISP/circuits/Nargo.toml @@ -6,9 +6,7 @@ authors = ["Gnosis Guild / Enclave"] license = "MIT" [dependencies] -greco = { path = "../../../circuits/crates/libs/greco" } -polynomial = { path = "../../../circuits/crates/libs/polynomial" } -safe = { path = "../../../circuits/crates/libs/safe" } +lib = { path = "../../../circuits/lib" } keccak256 = { tag = "v0.1.0", git = "https://github.com/noir-lang/keccak256" } poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } binary_merkle_root = { git = "https://github.com/zk-kit/zk-kit.noir", tag = "binary-merkle-root-v0.0.1", directory = "packages/binary-merkle-root" } \ No newline at end of file diff --git a/examples/CRISP/circuits/src/ciphertext_addition.nr b/examples/CRISP/circuits/src/ciphertext_addition.nr index 6c2cdfc6c1..72c81cad7b 100644 --- a/examples/CRISP/circuits/src/ciphertext_addition.nr +++ b/examples/CRISP/circuits/src/ciphertext_addition.nr @@ -39,8 +39,8 @@ //! 3. Verifies the addition equations hold at these points //! 4. Checks range constraints on all coefficients -use greco::CryptographicParams; -use polynomial::Polynomial; +use lib::core::greco::Configs as GrecoConfigs; +use lib::math::polynomial::Polynomial; use crate::hash::generate_hash; @@ -53,7 +53,7 @@ use crate::hash::generate_hash; /// * `BIT_PREV_CT` - Bit-width bound per coefficient for previous ciphertext polynomials `prev_ct0is`/`prev_ct1is`. /// * `BIT_SUM_CT` - Bit-width bound per coefficient for sum ciphertext polynomials `sum_ct0is`/`sum_ct1is`. pub struct CiphertextAddition { - crypto_params: CryptographicParams, + configs: GrecoConfigs, ct0is: [Polynomial; L], ct1is: [Polynomial; L], ct_commitment: Field, @@ -71,13 +71,13 @@ impl, + configs: GrecoConfigs, ct0is: [Polynomial; L], ct1is: [Polynomial; L], ct_commitment: Field, @@ -91,7 +91,7 @@ impl; L], ) -> Self { Self { - crypto_params, + configs, ct0is, ct1is, ct_commitment, @@ -253,7 +253,7 @@ impl; 2], - prev_ct1is: [Polynomial<512>; 2], + prev_ct0is: [Polynomial; L], + prev_ct1is: [Polynomial; L], prev_ct_commitment: pub Field, - sum_ct0is: [Polynomial<512>; 2], - sum_ct1is: [Polynomial<512>; 2], - sum_r0is: [Polynomial<512>; 2], - sum_r1is: [Polynomial<512>; 2], + sum_ct0is: [Polynomial; L], + sum_ct1is: [Polynomial; L], + sum_r0is: [Polynomial; L], + sum_r1is: [Polynomial; L], // Greco Section. - params: Params<512, 2>, // todo: make this pub pk_commitment: pub Field, - pk0is: [Polynomial<512>; 2], - pk1is: [Polynomial<512>; 2], - ct0is: [Polynomial<512>; 2], - ct1is: [Polynomial<512>; 2], - u: Polynomial<512>, - e0: Polynomial<512>, - e0is: [Polynomial<512>; 2], - e0_quotients: [Polynomial<512>; 2], - e1: Polynomial<512>, - k1: Polynomial<512>, - r1is: [Polynomial<1023>; 2], - r2is: [Polynomial<511>; 2], - p1is: [Polynomial<1023>; 2], - p2is: [Polynomial<511>; 2], + pk0is: [Polynomial; L], + pk1is: [Polynomial; L], + ct0is: [Polynomial; L], + ct1is: [Polynomial; L], + u: Polynomial, + e0: Polynomial, + e0is: [Polynomial; L], + e0_quotients: [Polynomial; L], + e1: Polynomial, + k1: Polynomial, + r1is: [Polynomial<(2 * N) - 1>; L], + r2is: [Polynomial; L], + p1is: [Polynomial<(2 * N) - 1>; L], + p2is: [Polynomial; L], // ECDSA Section. public_key_x: [u8; 32], public_key_y: [u8; 32], signature: [u8; 64], hashed_message: [u8; 32], // Merkle Tree Section. - merkle_root: pub Field, // todo: make this pub + merkle_root: pub Field, merkle_proof_length: u32, merkle_proof_indices: [u1; 20], merkle_proof_siblings: [Field; 20], @@ -132,8 +135,8 @@ fn main( // This check applies to BOTH cases: // - For actual votes: verifies the vote ciphertext is correctly formed // - For mask votes: verifies the zero vote ciphertext is correctly formed - let greco: Greco<512, 2, 36, 36, 2, 6, 6, 4, 10, 36, 10, 36> = Greco::new( - params, + let greco: Greco = Greco::new( + GRECO_CONFIGS, pk_commitment, pk0is, pk1is, @@ -175,12 +178,12 @@ fn main( // to verify). The commitments are then used in the Fiat-Shamir transform to generate // random challenges for the Schwartz-Zippel lemma verification, ensuring the addition // equations hold without revealing the full polynomial coefficients. - let _prev_ct_commitment = generate_commitment::<512, 2, 36>(prev_ct0is, prev_ct1is); - let ct_commitment = generate_commitment::<512, 2, 36>(ct0is, ct1is); - let sum_ct_commitment = generate_commitment::<512, 2, 36>(sum_ct0is, sum_ct1is); + let _prev_ct_commitment = generate_commitment::(prev_ct0is, prev_ct1is); + let ct_commitment = generate_commitment::(ct0is, ct1is); + let sum_ct_commitment = generate_commitment::(sum_ct0is, sum_ct1is); - let ct_add: CiphertextAddition<512, 2, 36, 36, 36> = CiphertextAddition::new( - params.crypto_params(), + let ct_add: CiphertextAddition = CiphertextAddition::new( + GRECO_CONFIGS, ct0is, ct1is, ct_commitment, @@ -214,7 +217,7 @@ fn main( // - If first vote in slot: return zero ciphertext (ct0is, ct1is) // - If updating slot: verify addition and return sum of previous votes if (is_signature_valid == true) & (slot_address == address) { - check_coefficient_values_with_balance(k1, params.crypto_params().q_mod_t, balance); + check_coefficient_values_with_balance(k1, Q_MOD_T, balance); ct_commitment } else { diff --git a/examples/CRISP/circuits/src/utils.nr b/examples/CRISP/circuits/src/utils.nr index 0688a019f4..f4426e94a3 100644 --- a/examples/CRISP/circuits/src/utils.nr +++ b/examples/CRISP/circuits/src/utils.nr @@ -4,7 +4,7 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use polynomial::Polynomial; +use lib::math::polynomial::Polynomial; use crate::constants::HALF_LARGEST_MINIMUM_DEGREE; diff --git a/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol b/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol index a78f635973..e98174c288 100644 --- a/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol +++ b/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol @@ -8,7 +8,7 @@ pragma solidity >=0.8.21; uint256 constant N = 262144; uint256 constant LOG_N = 18; uint256 constant NUMBER_OF_PUBLIC_INPUTS = 22; -uint256 constant VK_HASH = 0x0d53ba57f65358b21e53cf07b91c27906ac4d24b9205fda35494e1a44ba7242a; +uint256 constant VK_HASH = 0x1b70cd4645c6848a427928287d3a522940046ad3a0a07830d9ed5402ad0687f5; library HonkVerificationKey { function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) { Honk.VerificationKey memory vk = Honk.VerificationKey({ @@ -16,76 +16,76 @@ library HonkVerificationKey { logCircuitSize: uint256(18), publicInputsSize: uint256(22), ql: Honk.G1Point({ - x: uint256(0x112a6aa13787457ce92f268d8f6719287c1add28a224712ea3e2e7d96e2bc70b), - y: uint256(0x14dcf6e306f1dc722638d4984332053df53689114040ccd69d5926f485219e15) + x: uint256(0x14a0a19af87c2b7df627250d1ac6c5d55d75a58778f8e29595157428ac287a34), + y: uint256(0x287a5a5edc8f75bef06b3d796c2fc1654d9eea0a329fdfcfb8a19e32250daf5d) }), qr: Honk.G1Point({ - x: uint256(0x22a648530332803c4a992d98fd94a036c8ff1341c3d0ba385210b8851049206c), - y: uint256(0x0b891280448cdaee82da9caec22fb4820e3140558570c252669508b4f90fba2b) + x: uint256(0x2cf44e06d8100798cfc546de969e62bcf6c63a3fe6377d3aa284d9d251e72087), + y: uint256(0x08f2440e536e19058e644f53357f040c6123dc028cccec4fda5b4f030e38ea94) }), qo: Honk.G1Point({ - x: uint256(0x1ca6c37b9177a348c574f214e0683da82632df5c0d10addde3f372cda3f8978a), - y: uint256(0x22ce8ff67ba39a26d4ad603fbe668d9eb3f34f80b4e21e5cbf421d873f6ca040) + x: uint256(0x1dbe107d6bbb601e6540648740aab1cc45e94a288a20a78d6a352a79d04fc275), + y: uint256(0x2e53fd16a06904f737552331152035e335c6dd8f0017b21cbf52a340cdb6ac1f) }), q4: Honk.G1Point({ - x: uint256(0x0af0446ba584e461430e07a1f990aaee46d7b5088ad9f54d4a1350d57fa37ab6), - y: uint256(0x152ab3b635c7f88c62d6bb37fdff5bed5e42e01e0f9894058c10deea1994e4ef) + x: uint256(0x1269f80c74d44ecdc655a54a58e1a3a08672f5cac849df0750fbad95a5600440), + y: uint256(0x1389a9781486db51b657860a0825aea9fbb52939ce4cc37fb2c7448ba6ca8e97) }), qm: Honk.G1Point({ - x: uint256(0x2493bb0b6575f4240fa4ca66ab503effe7ad653c552cfe608e662e18e8ce5eb8), - y: uint256(0x1b5829dbe6ee24d5f1a776ddc4e27a90888310a3f384fe8f70cd86c2f9eebf7e) + x: uint256(0x2106f38ee711d176a0e31c843755d8bee2b3d0b09b008e72da3f3922a291a8e2), + y: uint256(0x291b9c179f0182baf30499124e134af98dd048ddd768edf3a1c1d83101f7ec00) }), qc: Honk.G1Point({ - x: uint256(0x2ccaa4f079bfc85f3887807ba17bffd69c73402d557395f6730d31cf1f208e53), - y: uint256(0x11e38adba343d4c9839c5b4ed4d54c38d7d0e17b0c3890add1544aa18a53f805) + x: uint256(0x2965ca056bec0d32a078f476f1dbef37c0ba7f69512db8beef4d7a80f1e0c61c), + y: uint256(0x2fa4f0f839d6ce583dada1ea6f6ad12e5c860762df31579a2cddefd45f50a593) }), qLookup: Honk.G1Point({ x: uint256(0x111ada27d4243c5df982e1cd77f2d9aff394ba4f2ba2faf8ec1a8e5b6d78d1e7), y: uint256(0x1cf81a5fe339ef18222213e43155e149d0211317fe0a68d795681f31ef25ad0f) }), qArith: Honk.G1Point({ - x: uint256(0x2771f716f503f8552b69271a62ec8cd7ab492b67f4859d8ff0321ce075e0361e), - y: uint256(0x0a7762803ccc6145a73d9df81cb83b8d7125f07f998525b8ec888bb39ff32658) + x: uint256(0x300512e679e6cfe651462108d36e34fe7d8a43e3ec97a783c4c9388068e12457), + y: uint256(0x16a3ce5bee48993935216e3fa2edc60b6a288b33e5f2cd234fc9220eb7112429) }), qDeltaRange: Honk.G1Point({ - x: uint256(0x0188abc30c433d60b371a87b89bef69474c4de9748b2b4b4e01d3e423cc2e975), - y: uint256(0x2bbddad8b0e16ca7d71b0ca54b0f6251ea7c4457d76ba3327982171026423a40) + x: uint256(0x1ab91e3b8f5c1bafc8584036f1ec35eafdc7848f87501496cd968e7b125a45b0), + y: uint256(0x26e370885ee010f8ca60ec6fc07e726364caf11898fb12421ddfede3532bd853) }), qElliptic: Honk.G1Point({ - x: uint256(0x1a2e2850cfbe3912c8f6a4c0099bc93bc50841ce22d665b83b081753ce664a24), - y: uint256(0x1976524b69c879a83c4d704ff5cb39397679528681ad378e6753e8b63457c40e) + x: uint256(0x2aeaf72123d84c2f1f09c5f4c08ee6984e4091f1568f9f6b6035ba5cd99bfc11), + y: uint256(0x2a28c9082b851a9475790e461e1e06942fc1a33dea3fb775e8f6f0174945fbf9) }), qMemory: Honk.G1Point({ - x: uint256(0x2e569e263fc7a1cfa7b839e1d01a24bb6e07a396cbe93280eaa5f428f9bfcda3), - y: uint256(0x232683b772e71e0839c2c22a0325540c142df09d86ad281e95c9a8526c8a8b1d) + x: uint256(0x0bca7506936c66cc981136b256890b3e42a7714ea686a3b254599cead5ac1b76), + y: uint256(0x18f570d280eb8c0f0e405caf98a465655d46a09b7214c629e3cb7df65c44d3a1) }), qNnf: Honk.G1Point({ - x: uint256(0x21cdfcabf16e6fa296718413cc974b48e44c715143907a9c5cc722aa737b74b0), - y: uint256(0x2280bd00b21340373b65aa88a619fa5f770435b772e1620701f76d769d041ea4) + x: uint256(0x12ddf7790f78e99382578be0be2b774f653f4699feb3cc75146d608c07b23cc0), + y: uint256(0x1c7aa57374e663ac28c52b9e89d85d5b43950e653a257b93ee93908ba172452a) }), qPoseidon2External: Honk.G1Point({ - x: uint256(0x0e5cb0521c16b7e51540251b51adb95e4ce6d507a75c32e0c33377c21853d058), - y: uint256(0x2ca91c89d04305640dcd8eefc8d33d78d27efee8fda3ac261150c8d675dff0d3) + x: uint256(0x02b883bf735f0495c00706750202af048a9fb1236565dbd8a4bd9cd65d62cd45), + y: uint256(0x1df068483fd21a1324c66e3edfddf4cf262a49018d868f06137f9967a768d434) }), qPoseidon2Internal: Honk.G1Point({ - x: uint256(0x1e7842d12cae260b5fabe275ae67fc449e3a55615f7f83da87b1ea7c9e8f0500), - y: uint256(0x1ea86788529c46dc304e64c22662f3c8c4e3e2e347500ccf539780071a293aad) + x: uint256(0x0e591142555a9892f389e3878f9c223bd6aefdb2da5fa052e9412c8a32813f59), + y: uint256(0x228b08999e84933242faba6b29da88a0d3d5bfebee3ab34ec4a3e58dffde9209) }), s1: Honk.G1Point({ - x: uint256(0x0e90e964ef25f8c1aec26541f31cc9320b50fd36e39520d025d13e032037727e), - y: uint256(0x1089017a718fae9b93f24789f8ef17aeed176bf9d16edb535a63d32648528a92) + x: uint256(0x01c1d72a9fce26c9dd80a3e741e41cc6de658192d055ef797dd05d425ab2a60d), + y: uint256(0x2571424507bb289eb1f165fbb5d0cccd2f73a3c9655af27d65b89ee81a335eb2) }), s2: Honk.G1Point({ - x: uint256(0x1aacf9506f5763680928c04b60d8217d4db189f8e148fd444a114ea18338fc8c), - y: uint256(0x0b260dbc5d61e1b32e055570a5dd0a835b4f9672cd12dad8314aaa58eea62dd4) + x: uint256(0x049262a1d79e194a1787580c7592d66a8276b129379e3215d2cf1e76245f5f5d), + y: uint256(0x0015a76d65bfb1bc143f558a48a0396305275edd989bae9ababc97c932df9a7f) }), s3: Honk.G1Point({ - x: uint256(0x00357d87f2822ca4102863d9736d121154762e65008fb88d0851b22f7d564c5f), - y: uint256(0x261b2a08cf2c8f3df7c5758aa7532df230d3348c1ad7b6ff1cf75dce3e8a03c7) + x: uint256(0x2368a0e09e8963f9e6e1ea99e6ac4d412af1c30962ca6e5dd45fb405753ed53e), + y: uint256(0x07a32010169e8592f4f4b7c9dbc6a617859acdd13b4ad329bf6ca5b385b3c3ea) }), s4: Honk.G1Point({ - x: uint256(0x063add626791aade9be4f0371c6bb601295f7715cd35c540a64881892bb9015f), - y: uint256(0x242cfc11084db62679ffc86ae33655c2adf2c60ee9a18c3fda51910194358f18) + x: uint256(0x29ab00032fef2aba36b00340b4690ced045e22811e62fd7b2bf7e2ecc83b8996), + y: uint256(0x2293b532735e839c9c0d9658f75145c0a71f00d9143fb0bdbf9bad99ed811308) }), t1: Honk.G1Point({ x: uint256(0x1f16b037f0b4c96ea2a30a118a44e139881c0db8a4d6c9fde7db5c1c1738e61f), @@ -104,28 +104,28 @@ library HonkVerificationKey { y: uint256(0x2d7e8c1ecb92e2490049b50efc811df63f1ca97e58d5e82852dbec0c29715d71) }), id1: Honk.G1Point({ - x: uint256(0x1dab2791b5e739b6eda84ec6578132dd1f9295f16540f1a221a615f137c750d0), - y: uint256(0x0be694840789fada394fb3182a06d50f0c313775cea2b52e6ec3d09705d4ed13) + x: uint256(0x0f763a39c7f1d60c34ffd472e45528e457d514a647c4aab115ff131b88fcf78b), + y: uint256(0x0d8784fb3171af6e6dd0c199eb2a1b9d8e4a989e12cf8aed9827a42ede7bb472) }), id2: Honk.G1Point({ - x: uint256(0x2922506083c612268913dac1af860cae5d49406ce01679ccfc17f95f1ab2a95f), - y: uint256(0x29b3e2aa20c02de724c5142a941fdc7578c80fa8e2984882ffdf2c3a98ab8877) + x: uint256(0x23c5218d4ca0a7973ff8355621a7ea8c074e6ce5f2b45c3cbf35805a7c4f8e06), + y: uint256(0x234dfd63fe6fd61f2414c254cb4c9632dbf49696cb1e9b01c681336dd0ec070d) }), id3: Honk.G1Point({ - x: uint256(0x021afc0b974f923bb6e3116b7a7d04af835678e17a0e8ef3e9e723ca2c2122e9), - y: uint256(0x1a1a18df93aba1975b374fd27695da35bbc0e243edbbcf67ec6e58c3441198fb) + x: uint256(0x02b0c39f64b037a63141f38b238f184b9c9f3c42496f92ef699f1c4e233c3762), + y: uint256(0x2d3e477b946ebdc896aad38a7f226c98b8fc32ad79522512948d1a22b491cea5) }), id4: Honk.G1Point({ - x: uint256(0x22c8713ddae54a7bb0751e8e2d97049735a71cf2e840c5a8c4e3d94af4bad28b), - y: uint256(0x12b05267a7d72d33761c4742e8b03365cbdb383efd91743447b64d1714259595) + x: uint256(0x27fe3dbc937a376a1c3f13470a4c8cc06aff2d1de9076059876150b7274be830), + y: uint256(0x102d1f66d257589a309544e8857e925c71f7f17706480014e3307783a67914ba) }), lagrangeFirst: Honk.G1Point({ x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002) }), lagrangeLast: Honk.G1Point({ - x: uint256(0x23322d7d1115f6d1ee1e781cf348e56fbdf96c6853625397732a472b0711fa65), - y: uint256(0x0359cc7c66a45d683d935dfaac2ada72634fd94dec1136ddf9dda711219be516) + x: uint256(0x0abc96b13980d69bf46819cc4b5008a18a549b52251ae0ef596f13e9149f2c31), + y: uint256(0x0301acf167c28438e607bcc3fc7c29b802b1f9787f24c29e13db0a03528f3a9c) }) }); return vk; From 5f2a834241897a526fa3bd60ebe4d66e33fadd13 Mon Sep 17 00:00:00 2001 From: Cedoor Date: Fri, 16 Jan 2026 16:37:33 +0100 Subject: [PATCH 03/30] refactor: update pvss lib name --- circuits/lib/Nargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circuits/lib/Nargo.toml b/circuits/lib/Nargo.toml index 9bc2479aea..cf47352b02 100644 --- a/circuits/lib/Nargo.toml +++ b/circuits/lib/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "lib" +name = "pvss_lib" type = "lib" authors = ["Gnosis Guild / Enclave"] version = "1.0.0-beta.15" From e05604aa47c25ab5ae2995085db90e70d92010d0 Mon Sep 17 00:00:00 2001 From: Cedoor Date: Fri, 16 Jan 2026 16:39:33 +0100 Subject: [PATCH 04/30] chore: add license to pvss circuits --- circuits/bin/aggregation/fold/src/main.nr | 6 ++++++ .../insecure/verify_shares_trbfv_wrapper/src/main.nr | 6 ++++++ circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr | 6 ++++++ .../production/verify_shares_trbfv_wrapper/src/main.nr | 6 ++++++ circuits/bin/insecure/dec_bfv_e_sm/src/main.nr | 6 ++++++ circuits/bin/insecure/dec_bfv_sk/src/main.nr | 6 ++++++ circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr | 6 ++++++ circuits/bin/insecure/dec_share_trbfv/src/main.nr | 6 ++++++ circuits/bin/insecure/enc_bfv_e_sm/src/main.nr | 6 ++++++ circuits/bin/insecure/enc_bfv_sk/src/main.nr | 6 ++++++ circuits/bin/insecure/greco/src/main.nr | 6 ++++++ circuits/bin/insecure/pk_agg_trbfv/src/main.nr | 6 ++++++ circuits/bin/insecure/pk_bfv/src/main.nr | 6 ++++++ circuits/bin/insecure/pk_trbfv/src/main.nr | 6 ++++++ circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr | 6 ++++++ circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr | 6 ++++++ circuits/bin/production/dec_bfv_e_sm/src/main.nr | 6 ++++++ circuits/bin/production/dec_bfv_sk/src/main.nr | 6 ++++++ circuits/bin/production/dec_share_agg_trbfv/src/main.nr | 6 ++++++ circuits/bin/production/dec_share_trbfv/src/main.nr | 6 ++++++ circuits/bin/production/enc_bfv_e_sm/src/main.nr | 6 ++++++ circuits/bin/production/enc_bfv_sk/src/main.nr | 6 ++++++ circuits/bin/production/greco/src/main.nr | 6 ++++++ circuits/bin/production/pk_agg_trbfv/src/main.nr | 6 ++++++ circuits/bin/production/pk_bfv/src/main.nr | 6 ++++++ circuits/bin/production/pk_trbfv/src/main.nr | 6 ++++++ .../bin/production/verify_shares_trbfv_e_sm/src/main.nr | 6 ++++++ circuits/bin/production/verify_shares_trbfv_sk/src/main.nr | 6 ++++++ circuits/lib/src/configs/insecure/bfv.nr | 6 ++++++ circuits/lib/src/configs/insecure/mod.nr | 6 ++++++ circuits/lib/src/configs/insecure/trbfv.nr | 6 ++++++ circuits/lib/src/configs/mod.nr | 6 ++++++ circuits/lib/src/configs/production/bfv.nr | 6 ++++++ circuits/lib/src/configs/production/mod.nr | 6 ++++++ circuits/lib/src/configs/production/trbfv.nr | 6 ++++++ circuits/lib/src/core/bfv_dec.nr | 6 ++++++ circuits/lib/src/core/bfv_enc.nr | 6 ++++++ circuits/lib/src/core/bfv_pk.nr | 6 ++++++ circuits/lib/src/core/mod.nr | 6 ++++++ circuits/lib/src/core/trbfv_dec_share.nr | 6 ++++++ circuits/lib/src/core/trbfv_dec_shares_agg.nr | 6 ++++++ circuits/lib/src/core/trbfv_pk.nr | 6 ++++++ circuits/lib/src/core/trbfv_pk_agg.nr | 6 ++++++ circuits/lib/src/core/trbfv_verify_shares.nr | 6 ++++++ circuits/lib/src/lib.nr | 6 ++++++ circuits/lib/src/math/commitments.nr | 6 ++++++ circuits/lib/src/math/helpers.nr | 6 ++++++ circuits/lib/src/math/mod.nr | 6 ++++++ circuits/lib/src/math/modulo/U128.nr | 6 ++++++ circuits/lib/src/math/modulo/mod.nr | 6 ++++++ circuits/lib/src/math/modulo/unconstrained_U128.nr | 6 ++++++ circuits/lib/src/math/polynomial.nr | 6 ++++++ 52 files changed, 312 insertions(+) diff --git a/circuits/bin/aggregation/fold/src/main.nr b/circuits/bin/aggregation/fold/src/main.nr index 78d01486bb..6f1d298d59 100644 --- a/circuits/bin/aggregation/fold/src/main.nr +++ b/circuits/bin/aggregation/fold/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; use lib::math::commitments::compute_aggregation_commitment; diff --git a/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr index 4055e81f9a..76cecde836 100644 --- a/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr +++ b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; use lib::math::commitments::compute_aggregation_commitment; diff --git a/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr index 96574b1104..3d464e7464 100644 --- a/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr +++ b/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; use lib::math::commitments::compute_aggregation_commitment; diff --git a/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr index 4d963513d4..7dcf4333b9 100644 --- a/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr +++ b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; use lib::math::commitments::compute_aggregation_commitment; diff --git a/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr b/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr index 6f1cb56626..fe956181e3 100644 --- a/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr +++ b/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::bfv::{DEC_BFV_BIT_MSG_E_SM, L_TRBFV, N}; use lib::core::bfv_dec::BfvDecCommitVerify; use lib::math::polynomial::Polynomial; diff --git a/circuits/bin/insecure/dec_bfv_sk/src/main.nr b/circuits/bin/insecure/dec_bfv_sk/src/main.nr index 3c83cf74db..02d3b66008 100644 --- a/circuits/bin/insecure/dec_bfv_sk/src/main.nr +++ b/circuits/bin/insecure/dec_bfv_sk/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::bfv::{DEC_BFV_BIT_MSG_SK, L_TRBFV, N}; use lib::core::bfv_dec::BfvDecCommitVerify; use lib::math::polynomial::Polynomial; diff --git a/circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr b/circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr index b21cc5c599..ec32da92e4 100644 --- a/circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr +++ b/circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::trbfv::{DEC_SHARES_AGG_BIT_NOISE, DEC_SHARES_AGG_CONFIGS, L}; use lib::core::trbfv_dec_shares_agg::DecryptionSharesAggregation; use lib::math::polynomial::Polynomial; diff --git a/circuits/bin/insecure/dec_share_trbfv/src/main.nr b/circuits/bin/insecure/dec_share_trbfv/src/main.nr index 8ee5883b40..2ee4c57ab0 100644 --- a/circuits/bin/insecure/dec_share_trbfv/src/main.nr +++ b/circuits/bin/insecure/dec_share_trbfv/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::trbfv::{ DEC_SHARES_BIT_CT, DEC_SHARES_BIT_D, DEC_SHARES_BIT_E, DEC_SHARES_BIT_R1, DEC_SHARES_BIT_R2, DEC_SHARES_BIT_S, DEC_SHARES_CONFIGS, L, N, diff --git a/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr b/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr index 2ec4f122bc..9be56e0e3c 100644 --- a/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr +++ b/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::bfv::{ ENC_BFV_BIT_CT, ENC_BFV_BIT_E0, ENC_BFV_BIT_E1, ENC_BFV_BIT_MSG, ENC_BFV_BIT_P1, ENC_BFV_BIT_P2, ENC_BFV_BIT_PK, ENC_BFV_BIT_R1, ENC_BFV_BIT_R2, ENC_BFV_BIT_U, ENC_BFV_CONFIGS_E_SM, L, N, diff --git a/circuits/bin/insecure/enc_bfv_sk/src/main.nr b/circuits/bin/insecure/enc_bfv_sk/src/main.nr index 875eaada2c..9dd2244b17 100644 --- a/circuits/bin/insecure/enc_bfv_sk/src/main.nr +++ b/circuits/bin/insecure/enc_bfv_sk/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::bfv::{ ENC_BFV_BIT_CT, ENC_BFV_BIT_E0, ENC_BFV_BIT_E1, ENC_BFV_BIT_MSG, ENC_BFV_BIT_P1, ENC_BFV_BIT_P2, ENC_BFV_BIT_PK, ENC_BFV_BIT_R1, ENC_BFV_BIT_R2, ENC_BFV_BIT_U, ENC_BFV_CONFIGS_SK, L, N, diff --git a/circuits/bin/insecure/greco/src/main.nr b/circuits/bin/insecure/greco/src/main.nr index 8c46634a2e..6ac6942e64 100644 --- a/circuits/bin/insecure/greco/src/main.nr +++ b/circuits/bin/insecure/greco/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::trbfv::{ GRECO_BIT_CT, GRECO_BIT_E0, GRECO_BIT_E1, GRECO_BIT_K, GRECO_BIT_P1, GRECO_BIT_P2, GRECO_BIT_PK, GRECO_BIT_R1, GRECO_BIT_R2, GRECO_BIT_U, GRECO_CONFIGS, L, N, diff --git a/circuits/bin/insecure/pk_agg_trbfv/src/main.nr b/circuits/bin/insecure/pk_agg_trbfv/src/main.nr index 1fc67723e2..187926e96c 100644 --- a/circuits/bin/insecure/pk_agg_trbfv/src/main.nr +++ b/circuits/bin/insecure/pk_agg_trbfv/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::trbfv::{L, N, PK_AGG_TRBFV_BIT_PK, PK_AGG_TRBFV_CONFIGS}; use lib::core::trbfv_pk_agg::TrbfvPublicKeyAggregation; use lib::math::polynomial::Polynomial; diff --git a/circuits/bin/insecure/pk_bfv/src/main.nr b/circuits/bin/insecure/pk_bfv/src/main.nr index 6235e35eaf..986ae868bd 100644 --- a/circuits/bin/insecure/pk_bfv/src/main.nr +++ b/circuits/bin/insecure/pk_bfv/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::bfv::{L, N, PK_BFV_BIT_PK}; use lib::core::bfv_pk::BfvPkCommit; use lib::math::polynomial::Polynomial; diff --git a/circuits/bin/insecure/pk_trbfv/src/main.nr b/circuits/bin/insecure/pk_trbfv/src/main.nr index 5bbfd3fa7a..fa2699c1c5 100644 --- a/circuits/bin/insecure/pk_trbfv/src/main.nr +++ b/circuits/bin/insecure/pk_trbfv/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::trbfv::{ L, N, PK_TRBFV_BIT_E_SM, PK_TRBFV_BIT_EEK, PK_TRBFV_BIT_PK, PK_TRBFV_BIT_R1, PK_TRBFV_BIT_R2, PK_TRBFV_BIT_SK, PK_TRBFV_CONFIGS, diff --git a/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr b/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr index 0970b9472c..a65373768f 100644 --- a/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr +++ b/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::trbfv::{ L, N, VERIFY_SHARES_BIT_SECRET_E_SM, VERIFY_SHARES_BIT_SHARE, VERIFY_SHARES_CONFIGS_E_SM, }; diff --git a/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr b/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr index ca6087adc4..b18cf4660d 100644 --- a/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr +++ b/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::insecure::trbfv::{ L, N, VERIFY_SHARES_BIT_SECRET_SK, VERIFY_SHARES_BIT_SHARE, VERIFY_SHARES_CONFIGS_SK, }; diff --git a/circuits/bin/production/dec_bfv_e_sm/src/main.nr b/circuits/bin/production/dec_bfv_e_sm/src/main.nr index 72c6e7489d..8f2b563307 100644 --- a/circuits/bin/production/dec_bfv_e_sm/src/main.nr +++ b/circuits/bin/production/dec_bfv_e_sm/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::bfv::{DEC_BFV_BIT_MSG_E_SM, L_TRBFV, N}; use lib::core::bfv_dec::BfvDecCommitVerify; use lib::math::polynomial::Polynomial; diff --git a/circuits/bin/production/dec_bfv_sk/src/main.nr b/circuits/bin/production/dec_bfv_sk/src/main.nr index 51d7d17b7e..9ef05e49de 100644 --- a/circuits/bin/production/dec_bfv_sk/src/main.nr +++ b/circuits/bin/production/dec_bfv_sk/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::bfv::{DEC_BFV_BIT_MSG_SK, L_TRBFV, N}; use lib::core::bfv_dec::BfvDecCommitVerify; use lib::math::polynomial::Polynomial; diff --git a/circuits/bin/production/dec_share_agg_trbfv/src/main.nr b/circuits/bin/production/dec_share_agg_trbfv/src/main.nr index c58005a813..acf5246dee 100644 --- a/circuits/bin/production/dec_share_agg_trbfv/src/main.nr +++ b/circuits/bin/production/dec_share_agg_trbfv/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::trbfv::{DEC_SHARES_AGG_BIT_NOISE, DEC_SHARES_AGG_CONFIGS, L}; use lib::core::trbfv_dec_shares_agg::DecryptionSharesAggregation; use lib::math::polynomial::Polynomial; diff --git a/circuits/bin/production/dec_share_trbfv/src/main.nr b/circuits/bin/production/dec_share_trbfv/src/main.nr index f4d0f4efb0..97b256e14d 100644 --- a/circuits/bin/production/dec_share_trbfv/src/main.nr +++ b/circuits/bin/production/dec_share_trbfv/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::trbfv::{ DEC_SHARES_BIT_CT, DEC_SHARES_BIT_D, DEC_SHARES_BIT_E, DEC_SHARES_BIT_R1, DEC_SHARES_BIT_R2, DEC_SHARES_BIT_S, DEC_SHARES_CONFIGS, L, N, diff --git a/circuits/bin/production/enc_bfv_e_sm/src/main.nr b/circuits/bin/production/enc_bfv_e_sm/src/main.nr index 949e17f579..4d6ee3ab0b 100644 --- a/circuits/bin/production/enc_bfv_e_sm/src/main.nr +++ b/circuits/bin/production/enc_bfv_e_sm/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::bfv::{ ENC_BFV_BIT_CT, ENC_BFV_BIT_E0, ENC_BFV_BIT_E1, ENC_BFV_BIT_MSG, ENC_BFV_BIT_P1, ENC_BFV_BIT_P2, ENC_BFV_BIT_PK, ENC_BFV_BIT_R1, ENC_BFV_BIT_R2, ENC_BFV_BIT_U, ENC_BFV_CONFIGS_E_SM, L, N, diff --git a/circuits/bin/production/enc_bfv_sk/src/main.nr b/circuits/bin/production/enc_bfv_sk/src/main.nr index d43181331a..1bb949a627 100644 --- a/circuits/bin/production/enc_bfv_sk/src/main.nr +++ b/circuits/bin/production/enc_bfv_sk/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::bfv::{ ENC_BFV_BIT_CT, ENC_BFV_BIT_E0, ENC_BFV_BIT_E1, ENC_BFV_BIT_MSG, ENC_BFV_BIT_P1, ENC_BFV_BIT_P2, ENC_BFV_BIT_PK, ENC_BFV_BIT_R1, ENC_BFV_BIT_R2, ENC_BFV_BIT_U, ENC_BFV_CONFIGS_SK, L, N, diff --git a/circuits/bin/production/greco/src/main.nr b/circuits/bin/production/greco/src/main.nr index 1972c14c5d..d561098c0f 100644 --- a/circuits/bin/production/greco/src/main.nr +++ b/circuits/bin/production/greco/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::trbfv::{ GRECO_BIT_CT, GRECO_BIT_E0, GRECO_BIT_E1, GRECO_BIT_K, GRECO_BIT_P1, GRECO_BIT_P2, GRECO_BIT_PK, GRECO_BIT_R1, GRECO_BIT_R2, GRECO_BIT_U, GRECO_CONFIGS, L, N, diff --git a/circuits/bin/production/pk_agg_trbfv/src/main.nr b/circuits/bin/production/pk_agg_trbfv/src/main.nr index 943dd3398a..2d3df7732e 100644 --- a/circuits/bin/production/pk_agg_trbfv/src/main.nr +++ b/circuits/bin/production/pk_agg_trbfv/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::trbfv::{L, N, PK_AGG_TRBFV_BIT_PK, PK_AGG_TRBFV_CONFIGS}; use lib::core::trbfv_pk_agg::TrbfvPublicKeyAggregation; use lib::math::polynomial::Polynomial; diff --git a/circuits/bin/production/pk_bfv/src/main.nr b/circuits/bin/production/pk_bfv/src/main.nr index f43ae128df..d85c49ae58 100644 --- a/circuits/bin/production/pk_bfv/src/main.nr +++ b/circuits/bin/production/pk_bfv/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::bfv::{L, N, PK_BFV_BIT_PK}; use lib::core::bfv_pk::BfvPkCommit; use lib::math::polynomial::Polynomial; diff --git a/circuits/bin/production/pk_trbfv/src/main.nr b/circuits/bin/production/pk_trbfv/src/main.nr index 94b609cfaf..f42727ae16 100644 --- a/circuits/bin/production/pk_trbfv/src/main.nr +++ b/circuits/bin/production/pk_trbfv/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::trbfv::{ L, N, PK_TRBFV_BIT_E_SM, PK_TRBFV_BIT_EEK, PK_TRBFV_BIT_PK, PK_TRBFV_BIT_R1, PK_TRBFV_BIT_R2, PK_TRBFV_BIT_SK, PK_TRBFV_CONFIGS, diff --git a/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr b/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr index 3856fd82a9..38ba6ac5a7 100644 --- a/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr +++ b/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::trbfv::{ L, N, VERIFY_SHARES_BIT_SECRET_E_SM, VERIFY_SHARES_BIT_SHARE, VERIFY_SHARES_CONFIGS_E_SM, }; diff --git a/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr b/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr index fe48b206df..38bb86713e 100644 --- a/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr +++ b/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use lib::configs::production::trbfv::{ L, N, VERIFY_SHARES_BIT_SECRET_SK, VERIFY_SHARES_BIT_SHARE, VERIFY_SHARES_CONFIGS_SK, }; diff --git a/circuits/lib/src/configs/insecure/bfv.nr b/circuits/lib/src/configs/insecure/bfv.nr index 2cf123d718..782e54b246 100644 --- a/circuits/lib/src/configs/insecure/bfv.nr +++ b/circuits/lib/src/configs/insecure/bfv.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::core::bfv_enc::Configs as BfvEncConfigs; // Global configs for BFV Decryption circuit diff --git a/circuits/lib/src/configs/insecure/mod.nr b/circuits/lib/src/configs/insecure/mod.nr index 0b3b884634..2d2beb97b1 100644 --- a/circuits/lib/src/configs/insecure/mod.nr +++ b/circuits/lib/src/configs/insecure/mod.nr @@ -1,2 +1,8 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + pub mod bfv; pub mod trbfv; diff --git a/circuits/lib/src/configs/insecure/trbfv.nr b/circuits/lib/src/configs/insecure/trbfv.nr index 77fc02e3b9..57fd01ed67 100644 --- a/circuits/lib/src/configs/insecure/trbfv.nr +++ b/circuits/lib/src/configs/insecure/trbfv.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::core::greco::Configs as GrecoConfigs; use crate::core::trbfv_dec_share::Configs as DecShareTrBfvConfigs; use crate::core::trbfv_dec_shares_agg::Configs as DecShareAggTrBfvConfigs; diff --git a/circuits/lib/src/configs/mod.nr b/circuits/lib/src/configs/mod.nr index 7c39344de7..186fa2a8ac 100644 --- a/circuits/lib/src/configs/mod.nr +++ b/circuits/lib/src/configs/mod.nr @@ -1,2 +1,8 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + pub mod insecure; pub mod production; diff --git a/circuits/lib/src/configs/production/bfv.nr b/circuits/lib/src/configs/production/bfv.nr index b0524b292a..031444d633 100644 --- a/circuits/lib/src/configs/production/bfv.nr +++ b/circuits/lib/src/configs/production/bfv.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::core::bfv_enc::Configs as BfvEncConfigs; // Global configs for BFV parameter set diff --git a/circuits/lib/src/configs/production/mod.nr b/circuits/lib/src/configs/production/mod.nr index 0b3b884634..2d2beb97b1 100644 --- a/circuits/lib/src/configs/production/mod.nr +++ b/circuits/lib/src/configs/production/mod.nr @@ -1,2 +1,8 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + pub mod bfv; pub mod trbfv; diff --git a/circuits/lib/src/configs/production/trbfv.nr b/circuits/lib/src/configs/production/trbfv.nr index 9a8312a1c5..0df1636f99 100644 --- a/circuits/lib/src/configs/production/trbfv.nr +++ b/circuits/lib/src/configs/production/trbfv.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::core::greco::Configs as GrecoConfigs; use crate::core::trbfv_dec_share::Configs as DecShareTrBfvConfigs; use crate::core::trbfv_dec_shares_agg::Configs as DecShareAggTrBfvConfigs; diff --git a/circuits/lib/src/core/bfv_dec.nr b/circuits/lib/src/core/bfv_dec.nr index 79d18f2fbe..8960813efb 100644 --- a/circuits/lib/src/core/bfv_dec.nr +++ b/circuits/lib/src/core/bfv_dec.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::math::commitments::{ compute_aggregated_shares_commitment, compute_shares_party_modulus_commitment, prepare_aggregated_shares_commitment_payload, prepare_single_polynomial_commitment_payload, diff --git a/circuits/lib/src/core/bfv_enc.nr b/circuits/lib/src/core/bfv_enc.nr index a7016293b4..27fb2bfae1 100644 --- a/circuits/lib/src/core/bfv_enc.nr +++ b/circuits/lib/src/core/bfv_enc.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::math::commitments::{ compute_bfv_enc_challenge_commitment, compute_pk_bfv_commitment, compute_shares_party_modulus_commitment, prepare_message_commitment_payload, diff --git a/circuits/lib/src/core/bfv_pk.nr b/circuits/lib/src/core/bfv_pk.nr index 1946b99217..8ff85013f3 100644 --- a/circuits/lib/src/core/bfv_pk.nr +++ b/circuits/lib/src/core/bfv_pk.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::math::commitments::{compute_pk_bfv_commitment, prepare_pk_commitment_payload}; use crate::math::polynomial::Polynomial; diff --git a/circuits/lib/src/core/mod.nr b/circuits/lib/src/core/mod.nr index 6703be1f34..d61708018d 100644 --- a/circuits/lib/src/core/mod.nr +++ b/circuits/lib/src/core/mod.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + pub mod bfv_pk; pub mod trbfv_pk; pub mod bfv_dec; diff --git a/circuits/lib/src/core/trbfv_dec_share.nr b/circuits/lib/src/core/trbfv_dec_share.nr index 668c9074b1..c4151f3ab9 100644 --- a/circuits/lib/src/core/trbfv_dec_share.nr +++ b/circuits/lib/src/core/trbfv_dec_share.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::math::commitments::{ compute_aggregated_shares_commitment, compute_dec_share_challenge_commitment, prepare_aggregated_shares_from_values_commitment_payload, diff --git a/circuits/lib/src/core/trbfv_dec_shares_agg.nr b/circuits/lib/src/core/trbfv_dec_shares_agg.nr index bc05136c36..fd638f69d5 100644 --- a/circuits/lib/src/core/trbfv_dec_shares_agg.nr +++ b/circuits/lib/src/core/trbfv_dec_shares_agg.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::math::modulo::U128::ModU128; use crate::math::polynomial::Polynomial; use dep::bignum::BigNum; diff --git a/circuits/lib/src/core/trbfv_pk.nr b/circuits/lib/src/core/trbfv_pk.nr index 0f6c9cca53..283130e3ad 100644 --- a/circuits/lib/src/core/trbfv_pk.nr +++ b/circuits/lib/src/core/trbfv_pk.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::math::commitments::{ compute_pk_trbfv_commitment, compute_secret_commitment, compute_trbfv_pk_challenge_commitment, prepare_pk_commitment_payload, prepare_single_polynomial_commitment_payload, diff --git a/circuits/lib/src/core/trbfv_pk_agg.nr b/circuits/lib/src/core/trbfv_pk_agg.nr index 24fabec909..61c441df0f 100644 --- a/circuits/lib/src/core/trbfv_pk_agg.nr +++ b/circuits/lib/src/core/trbfv_pk_agg.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::math::commitments::compute_greco_pk_agg_commitment; use crate::math::commitments::{compute_pk_trbfv_commitment, prepare_pk_commitment_payload}; use crate::math::modulo::U128::ModU128; diff --git a/circuits/lib/src/core/trbfv_verify_shares.nr b/circuits/lib/src/core/trbfv_verify_shares.nr index d8d27d546e..eb35bbb77d 100644 --- a/circuits/lib/src/core/trbfv_verify_shares.nr +++ b/circuits/lib/src/core/trbfv_verify_shares.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::math::commitments::{ compute_secret_commitment, compute_shares_party_modulus_commitment, prepare_shares_party_modulus_commitment_payload, prepare_single_polynomial_commitment_payload, diff --git a/circuits/lib/src/lib.nr b/circuits/lib/src/lib.nr index ec1ad02156..e6338c0881 100644 --- a/circuits/lib/src/lib.nr +++ b/circuits/lib/src/lib.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + //! # lib - Enclave Zero-Knowledge Cryptographic Library //! - **`core`**: Core functions and structs for Public Verifiable //! Secret Sharing (PVSS) circuits implementations. diff --git a/circuits/lib/src/math/commitments.nr b/circuits/lib/src/math/commitments.nr index 3230adb7b1..b8bfa06e7d 100644 --- a/circuits/lib/src/math/commitments.nr +++ b/circuits/lib/src/math/commitments.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use crate::math::helpers::{compute_safe, flatten}; use crate::math::polynomial::Polynomial; diff --git a/circuits/lib/src/math/helpers.nr b/circuits/lib/src/math/helpers.nr index 79165bdae2..ae94afe4e2 100644 --- a/circuits/lib/src/math/helpers.nr +++ b/circuits/lib/src/math/helpers.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + //! Helper functions for circuit construction and cryptographic operations. use crate::math::polynomial::Polynomial; use crate::math::safe::SafeSponge; diff --git a/circuits/lib/src/math/mod.nr b/circuits/lib/src/math/mod.nr index 2cd07d265d..b03c54f7ff 100644 --- a/circuits/lib/src/math/mod.nr +++ b/circuits/lib/src/math/mod.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + pub mod polynomial; pub mod safe; pub mod helpers; diff --git a/circuits/lib/src/math/modulo/U128.nr b/circuits/lib/src/math/modulo/U128.nr index 858b9acc86..bc2db8a2bc 100644 --- a/circuits/lib/src/math/modulo/U128.nr +++ b/circuits/lib/src/math/modulo/U128.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + //! Constrained modular arithmetic operations for u128 values. //! //! This module provides a `ModU128` struct that implements modular arithmetic operations diff --git a/circuits/lib/src/math/modulo/mod.nr b/circuits/lib/src/math/modulo/mod.nr index d6a40f4211..b0bcfcb012 100644 --- a/circuits/lib/src/math/modulo/mod.nr +++ b/circuits/lib/src/math/modulo/mod.nr @@ -1,2 +1,8 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + pub mod unconstrained_U128; pub mod U128; diff --git a/circuits/lib/src/math/modulo/unconstrained_U128.nr b/circuits/lib/src/math/modulo/unconstrained_U128.nr index b721da8c35..e8944e8162 100644 --- a/circuits/lib/src/math/modulo/unconstrained_U128.nr +++ b/circuits/lib/src/math/modulo/unconstrained_U128.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + //! Unconstrained functions for modular u128 arithmetic. //! //! This module provides unconstrained functions that perform modular arithmetic diff --git a/circuits/lib/src/math/polynomial.nr b/circuits/lib/src/math/polynomial.nr index f034f8786f..9419410447 100644 --- a/circuits/lib/src/math/polynomial.nr +++ b/circuits/lib/src/math/polynomial.nr @@ -1,3 +1,9 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + use super::modulo::U128::ModU128; /// Polynomial structure representing a polynomial of degree N-1. From 3bf41e22b42609dbc47a937919398654e43ea324 Mon Sep 17 00:00:00 2001 From: Cedoor Date: Fri, 16 Jan 2026 16:44:42 +0100 Subject: [PATCH 05/30] ci: update ci workflow to check formatting all circuits --- .github/workflows/ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0c792bb36..5db7289b41 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -588,16 +588,16 @@ jobs: toolchain: ${{ env.NOIR_TOOLCHAIN }} - name: Check formatting - working-directory: ./circuits - run: nargo fmt --check - - - name: Compile Noir circuits - working-directory: ./circuits run: | - nargo compile --workspace + for dir in circuits/lib circuits/bin/aggregation circuits/bin/production circuits/bin/insecure; do + if [ -d "$dir" ]; then + echo "Checking formatting in $dir..." + (cd "$dir" && nargo fmt --check) + fi + done - name: Test Noir circuits - working-directory: ./circuits + working-directory: ./circuits/lib run: | nargo test --workspace From 882ae9eb79af7e114b6536a552352152657d05cb Mon Sep 17 00:00:00 2001 From: Cedoor Date: Fri, 16 Jan 2026 16:45:56 +0100 Subject: [PATCH 06/30] ci: use scripts to check formatting all circuits --- .github/workflows/ci.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5db7289b41..c843ba4e7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -588,18 +588,10 @@ jobs: toolchain: ${{ env.NOIR_TOOLCHAIN }} - name: Check formatting - run: | - for dir in circuits/lib circuits/bin/aggregation circuits/bin/production circuits/bin/insecure; do - if [ -d "$dir" ]; then - echo "Checking formatting in $dir..." - (cd "$dir" && nargo fmt --check) - fi - done + run: ./scripts/lint-circuits.sh - name: Test Noir circuits - working-directory: ./circuits/lib - run: | - nargo test --workspace + run: ./scripts/test-circuits.sh - name: Upload circuit artifacts uses: actions/upload-artifact@v4 From c5dacc452c686ef67dfd15b3f7a1d7452aecc35f Mon Sep 17 00:00:00 2001 From: Cedoor Date: Mon, 19 Jan 2026 12:46:52 +0100 Subject: [PATCH 07/30] chore: align versions in nargo dependencies to bb version --- circuits/bin/aggregation/fold/Nargo.toml | 2 +- circuits/bin/aggregation/fold/src/main.nr | 6 +++--- .../insecure/verify_shares_trbfv_wrapper/Nargo.toml | 2 +- .../insecure/verify_shares_trbfv_wrapper/src/main.nr | 4 ++-- circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml | 2 +- circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr | 4 ++-- .../production/verify_shares_trbfv_wrapper/Nargo.toml | 2 +- .../production/verify_shares_trbfv_wrapper/src/main.nr | 4 ++-- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/circuits/bin/aggregation/fold/Nargo.toml b/circuits/bin/aggregation/fold/Nargo.toml index a0ca121abc..4df67f2446 100644 --- a/circuits/bin/aggregation/fold/Nargo.toml +++ b/circuits/bin/aggregation/fold/Nargo.toml @@ -6,4 +6,4 @@ version = "1.0.0-beta.15" [dependencies] lib = { path = "../../../lib" } -bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20260102", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/fold/src/main.nr b/circuits/bin/aggregation/fold/src/main.nr index 6f1d298d59..944792b7b4 100644 --- a/circuits/bin/aggregation/fold/src/main.nr +++ b/circuits/bin/aggregation/fold/src/main.nr @@ -4,7 +4,7 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; use lib::math::commitments::compute_aggregation_commitment; fn main( @@ -13,8 +13,8 @@ fn main( commitments: pub [Field; 2], key_hash: Field, ) -> pub Field { - verify_honk_proof_non_zk(verification_key, proofs[0], [commitments[0]], key_hash); - verify_honk_proof_non_zk(verification_key, proofs[1], [commitments[1]], key_hash); + verify_ultrahonk_proof(verification_key, proofs[0], [commitments[0]], key_hash); + verify_ultrahonk_proof(verification_key, proofs[1], [commitments[1]], key_hash); let mut commitments_vec = Vec::new(); diff --git a/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/Nargo.toml index 5dd27583c5..988e16adad 100644 --- a/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/Nargo.toml +++ b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/Nargo.toml @@ -6,4 +6,4 @@ version = "1.0.0-beta.15" [dependencies] lib = { path = "../../../../lib" } -bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20260102", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr index 76cecde836..73c8d34e91 100644 --- a/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr +++ b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr @@ -4,7 +4,7 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; use lib::math::commitments::compute_aggregation_commitment; // Number of proofs. @@ -19,7 +19,7 @@ fn main( key_hash: Field, ) -> pub Field { for i in 0..N_PROOFS { - verify_honk_proof_non_zk(verification_key, proofs[i], commitments[i], key_hash); + verify_ultrahonk_proof(verification_key, proofs[i], commitments[i], key_hash); } let mut aggregated_commitments = Vec::new(); diff --git a/circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml index 05ad684ea8..8e20cf697f 100644 --- a/circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml +++ b/circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml @@ -6,4 +6,4 @@ version = "1.0.0-beta.15" [dependencies] lib = { path = "../../../lib" } -bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20260102", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr index 3d464e7464..3feb9806de 100644 --- a/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr +++ b/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr @@ -4,7 +4,7 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; use lib::math::commitments::compute_aggregation_commitment; // Number of proofs. @@ -19,7 +19,7 @@ fn main( key_hash: Field, ) -> pub Field { for i in 0..N_PROOFS { - verify_honk_proof_non_zk(verification_key, proofs[i], commitments[i], key_hash); + verify_ultrahonk_proof(verification_key, proofs[i], commitments[i], key_hash); } let mut aggregated_commitments = Vec::new(); diff --git a/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/Nargo.toml index 5dd27583c5..988e16adad 100644 --- a/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/Nargo.toml +++ b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/Nargo.toml @@ -6,4 +6,4 @@ version = "1.0.0-beta.15" [dependencies] lib = { path = "../../../../lib" } -bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20260102", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr index 7dcf4333b9..1d40914eeb 100644 --- a/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr +++ b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr @@ -4,7 +4,7 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_honk_proof_non_zk}; +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; use lib::math::commitments::compute_aggregation_commitment; // Number of proofs. @@ -19,7 +19,7 @@ fn main( key_hash: Field, ) -> pub Field { for i in 0..N_PROOFS { - verify_honk_proof_non_zk(verification_key, proofs[i], commitments[i], key_hash); + verify_ultrahonk_proof(verification_key, proofs[i], commitments[i], key_hash); } let mut aggregated_commitments = Vec::new(); From a39ae48b8c490a8153c237fa3946739cb2d350a3 Mon Sep 17 00:00:00 2001 From: Cedoor Date: Mon, 19 Jan 2026 12:51:46 +0100 Subject: [PATCH 08/30] chore: update script to use nargo test without workspace flag --- scripts/test-circuits.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/test-circuits.sh b/scripts/test-circuits.sh index d77eacd839..09cc9b073a 100755 --- a/scripts/test-circuits.sh +++ b/scripts/test-circuits.sh @@ -2,6 +2,6 @@ set -euo pipefail cd circuits/lib -nargo test --workspace +nargo test echo "Noir circuits tested successfully" \ No newline at end of file From ee2c677f2ffbb7444ad13d39cf5c7d2d3b908603 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 14:37:48 +0100 Subject: [PATCH 09/30] make commitments pub --- circuits/bin/insecure/dec_bfv_e_sm/src/main.nr | 2 +- circuits/bin/insecure/dec_bfv_sk/src/main.nr | 2 +- circuits/bin/insecure/enc_bfv_e_sm/src/main.nr | 4 ++-- circuits/bin/insecure/enc_bfv_sk/src/main.nr | 4 ++-- circuits/bin/insecure/pk_agg_trbfv/src/main.nr | 2 +- circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr | 2 +- circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr | 2 +- circuits/bin/production/dec_bfv_e_sm/src/main.nr | 2 +- circuits/bin/production/dec_bfv_sk/src/main.nr | 2 +- circuits/bin/production/enc_bfv_e_sm/src/main.nr | 4 ++-- circuits/bin/production/enc_bfv_sk/src/main.nr | 4 ++-- circuits/bin/production/pk_agg_trbfv/src/main.nr | 2 +- circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr | 2 +- circuits/bin/production/verify_shares_trbfv_sk/src/main.nr | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr b/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr index fe956181e3..0354c61c13 100644 --- a/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr +++ b/circuits/bin/insecure/dec_bfv_e_sm/src/main.nr @@ -12,7 +12,7 @@ use lib::math::polynomial::Polynomial; pub global H: u32 = 5; fn main( - expected_commitments: [[Field; L_TRBFV]; H], + expected_commitments: pub [[Field; L_TRBFV]; H], decrypted_shares: [[Polynomial; L_TRBFV]; H], ) -> pub Field { let circuit: BfvDecCommitVerify = diff --git a/circuits/bin/insecure/dec_bfv_sk/src/main.nr b/circuits/bin/insecure/dec_bfv_sk/src/main.nr index 02d3b66008..b9b50e8a8a 100644 --- a/circuits/bin/insecure/dec_bfv_sk/src/main.nr +++ b/circuits/bin/insecure/dec_bfv_sk/src/main.nr @@ -12,7 +12,7 @@ use lib::math::polynomial::Polynomial; pub global H: u32 = 5; fn main( - expected_commitments: [[Field; L_TRBFV]; H], + expected_commitments: pub [[Field; L_TRBFV]; H], decrypted_shares: [[Polynomial; L_TRBFV]; H], ) -> pub Field { let circuit: BfvDecCommitVerify = diff --git a/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr b/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr index 9be56e0e3c..8f64f210c0 100644 --- a/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr +++ b/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr @@ -12,8 +12,8 @@ use lib::core::bfv_enc::EncryptionBfv; use lib::math::polynomial::Polynomial; fn main( - expected_pk_commitment: Field, - expected_message_commitment: Field, + expected_pk_commitment: pub Field, + expected_message_commitment: pub Field, pk0is: [Polynomial; L], pk1is: [Polynomial; L], ct0is: [Polynomial; L], diff --git a/circuits/bin/insecure/enc_bfv_sk/src/main.nr b/circuits/bin/insecure/enc_bfv_sk/src/main.nr index 9dd2244b17..ae2865e020 100644 --- a/circuits/bin/insecure/enc_bfv_sk/src/main.nr +++ b/circuits/bin/insecure/enc_bfv_sk/src/main.nr @@ -12,8 +12,8 @@ use lib::core::bfv_enc::EncryptionBfv; use lib::math::polynomial::Polynomial; fn main( - expected_pk_commitment: Field, - expected_message_commitment: Field, + expected_pk_commitment: pub Field, + expected_message_commitment: pub Field, pk0is: [Polynomial; L], pk1is: [Polynomial; L], ct0is: [Polynomial; L], diff --git a/circuits/bin/insecure/pk_agg_trbfv/src/main.nr b/circuits/bin/insecure/pk_agg_trbfv/src/main.nr index 187926e96c..98e57a0801 100644 --- a/circuits/bin/insecure/pk_agg_trbfv/src/main.nr +++ b/circuits/bin/insecure/pk_agg_trbfv/src/main.nr @@ -12,7 +12,7 @@ use lib::math::polynomial::Polynomial; pub global H: u32 = 5; fn main( - expected_pk_trbfv_commitments: [Field; H], + expected_pk_trbfv_commitments: pub [Field; H], pk0: [[Polynomial; L]; H], pk1: [[Polynomial; L]; H], pk0_agg: [Polynomial; L], diff --git a/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr b/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr index a65373768f..98358897f5 100644 --- a/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr +++ b/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr @@ -16,7 +16,7 @@ pub global N_PARTIES: u32 = 5; pub global T: u32 = 2; fn main( - expected_secret_commitment: Field, + expected_secret_commitment: pub Field, secret_e_sm: [Polynomial; L], y: [[[Field; N_PARTIES + 1]; L]; N], h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], diff --git a/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr b/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr index b18cf4660d..a9705c685a 100644 --- a/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr +++ b/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr @@ -16,7 +16,7 @@ pub global N_PARTIES: u32 = 5; pub global T: u32 = 2; fn main( - expected_secret_commitment: Field, + expected_secret_commitment: pub Field, secret_sk: Polynomial, y: [[[Field; N_PARTIES + 1]; L]; N], h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], diff --git a/circuits/bin/production/dec_bfv_e_sm/src/main.nr b/circuits/bin/production/dec_bfv_e_sm/src/main.nr index 8f2b563307..892015caf7 100644 --- a/circuits/bin/production/dec_bfv_e_sm/src/main.nr +++ b/circuits/bin/production/dec_bfv_e_sm/src/main.nr @@ -12,7 +12,7 @@ use lib::math::polynomial::Polynomial; pub global H: u32 = 5; fn main( - expected_commitments: [[Field; L_TRBFV]; H], + expected_commitments: pub [[Field; L_TRBFV]; H], decrypted_shares: [[Polynomial; L_TRBFV]; H], ) -> pub Field { let circuit: BfvDecCommitVerify = diff --git a/circuits/bin/production/dec_bfv_sk/src/main.nr b/circuits/bin/production/dec_bfv_sk/src/main.nr index 9ef05e49de..448f92b044 100644 --- a/circuits/bin/production/dec_bfv_sk/src/main.nr +++ b/circuits/bin/production/dec_bfv_sk/src/main.nr @@ -12,7 +12,7 @@ use lib::math::polynomial::Polynomial; pub global H: u32 = 5; fn main( - expected_commitments: [[Field; L_TRBFV]; H], + expected_commitments: pub [[Field; L_TRBFV]; H], decrypted_shares: [[Polynomial; L_TRBFV]; H], ) -> pub Field { let circuit: BfvDecCommitVerify = diff --git a/circuits/bin/production/enc_bfv_e_sm/src/main.nr b/circuits/bin/production/enc_bfv_e_sm/src/main.nr index 4d6ee3ab0b..8196c9b296 100644 --- a/circuits/bin/production/enc_bfv_e_sm/src/main.nr +++ b/circuits/bin/production/enc_bfv_e_sm/src/main.nr @@ -12,8 +12,8 @@ use lib::core::bfv_enc::EncryptionBfv; use lib::math::polynomial::Polynomial; fn main( - expected_pk_commitment: Field, - expected_message_commitment: Field, + expected_pk_commitment: pub Field, + expected_message_commitment: pub Field, pk0is: [Polynomial; L], pk1is: [Polynomial; L], ct0is: [Polynomial; L], diff --git a/circuits/bin/production/enc_bfv_sk/src/main.nr b/circuits/bin/production/enc_bfv_sk/src/main.nr index 1bb949a627..2be42ef1b7 100644 --- a/circuits/bin/production/enc_bfv_sk/src/main.nr +++ b/circuits/bin/production/enc_bfv_sk/src/main.nr @@ -12,8 +12,8 @@ use lib::core::bfv_enc::EncryptionBfv; use lib::math::polynomial::Polynomial; fn main( - expected_pk_commitment: Field, - expected_message_commitment: Field, + expected_pk_commitment: pub Field, + expected_message_commitment: pub Field, pk0is: [Polynomial; L], pk1is: [Polynomial; L], ct0is: [Polynomial; L], diff --git a/circuits/bin/production/pk_agg_trbfv/src/main.nr b/circuits/bin/production/pk_agg_trbfv/src/main.nr index 2d3df7732e..d8cc020d34 100644 --- a/circuits/bin/production/pk_agg_trbfv/src/main.nr +++ b/circuits/bin/production/pk_agg_trbfv/src/main.nr @@ -12,7 +12,7 @@ use lib::math::polynomial::Polynomial; pub global H: u32 = 5; fn main( - expected_pk_trbfv_commitments: [Field; H], + expected_pk_trbfv_commitments: pub [Field; H], pk0: [[Polynomial; L]; H], pk1: [[Polynomial; L]; H], pk0_agg: [Polynomial; L], diff --git a/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr b/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr index 38ba6ac5a7..0b5cf2c269 100644 --- a/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr +++ b/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr @@ -16,7 +16,7 @@ pub global N_PARTIES: u32 = 5; pub global T: u32 = 2; fn main( - expected_secret_commitment: Field, + expected_secret_commitment: pub Field, secret_e_sm: [Polynomial; L], y: [[[Field; N_PARTIES + 1]; L]; N], h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], diff --git a/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr b/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr index 38bb86713e..2025f3272c 100644 --- a/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr +++ b/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr @@ -16,7 +16,7 @@ pub global N_PARTIES: u32 = 5; pub global T: u32 = 2; fn main( - expected_secret_commitment: Field, + expected_secret_commitment: pub Field, secret_sk: Polynomial, y: [[[Field; N_PARTIES + 1]; L]; N], h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], From 3531475befcc9e7e16bd3b2092fd042efc404c10 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 14:41:28 +0100 Subject: [PATCH 10/30] rename c7 folder --- .../{dec_share_agg_trbfv => dec_shares_agg_trbfv}/Nargo.toml | 0 .../{dec_share_agg_trbfv => dec_shares_agg_trbfv}/README.md | 0 .../{dec_share_agg_trbfv => dec_shares_agg_trbfv}/src/main.nr | 0 .../{dec_share_agg_trbfv => dec_shares_agg_trbfv}/Nargo.toml | 0 .../{dec_share_agg_trbfv => dec_shares_agg_trbfv}/README.md | 0 .../{dec_share_agg_trbfv => dec_shares_agg_trbfv}/src/main.nr | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename circuits/bin/insecure/{dec_share_agg_trbfv => dec_shares_agg_trbfv}/Nargo.toml (100%) rename circuits/bin/insecure/{dec_share_agg_trbfv => dec_shares_agg_trbfv}/README.md (100%) rename circuits/bin/insecure/{dec_share_agg_trbfv => dec_shares_agg_trbfv}/src/main.nr (100%) rename circuits/bin/production/{dec_share_agg_trbfv => dec_shares_agg_trbfv}/Nargo.toml (100%) rename circuits/bin/production/{dec_share_agg_trbfv => dec_shares_agg_trbfv}/README.md (100%) rename circuits/bin/production/{dec_share_agg_trbfv => dec_shares_agg_trbfv}/src/main.nr (100%) diff --git a/circuits/bin/insecure/dec_share_agg_trbfv/Nargo.toml b/circuits/bin/insecure/dec_shares_agg_trbfv/Nargo.toml similarity index 100% rename from circuits/bin/insecure/dec_share_agg_trbfv/Nargo.toml rename to circuits/bin/insecure/dec_shares_agg_trbfv/Nargo.toml diff --git a/circuits/bin/insecure/dec_share_agg_trbfv/README.md b/circuits/bin/insecure/dec_shares_agg_trbfv/README.md similarity index 100% rename from circuits/bin/insecure/dec_share_agg_trbfv/README.md rename to circuits/bin/insecure/dec_shares_agg_trbfv/README.md diff --git a/circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr b/circuits/bin/insecure/dec_shares_agg_trbfv/src/main.nr similarity index 100% rename from circuits/bin/insecure/dec_share_agg_trbfv/src/main.nr rename to circuits/bin/insecure/dec_shares_agg_trbfv/src/main.nr diff --git a/circuits/bin/production/dec_share_agg_trbfv/Nargo.toml b/circuits/bin/production/dec_shares_agg_trbfv/Nargo.toml similarity index 100% rename from circuits/bin/production/dec_share_agg_trbfv/Nargo.toml rename to circuits/bin/production/dec_shares_agg_trbfv/Nargo.toml diff --git a/circuits/bin/production/dec_share_agg_trbfv/README.md b/circuits/bin/production/dec_shares_agg_trbfv/README.md similarity index 100% rename from circuits/bin/production/dec_share_agg_trbfv/README.md rename to circuits/bin/production/dec_shares_agg_trbfv/README.md diff --git a/circuits/bin/production/dec_share_agg_trbfv/src/main.nr b/circuits/bin/production/dec_shares_agg_trbfv/src/main.nr similarity index 100% rename from circuits/bin/production/dec_share_agg_trbfv/src/main.nr rename to circuits/bin/production/dec_shares_agg_trbfv/src/main.nr From fd5ff596141a5a3ec0b4287ec2a909a7e1a1de7c Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 14:47:33 +0100 Subject: [PATCH 11/30] remove unused decryption_share_bound from C6 --- circuits/bin/insecure/Nargo.toml | 2 +- circuits/bin/production/Nargo.toml | 2 +- circuits/lib/src/configs/insecure/trbfv.nr | 9 ++------- circuits/lib/src/configs/production/trbfv.nr | 9 ++------- circuits/lib/src/core/trbfv_dec_share.nr | 11 ++--------- 5 files changed, 8 insertions(+), 25 deletions(-) diff --git a/circuits/bin/insecure/Nargo.toml b/circuits/bin/insecure/Nargo.toml index c5a20cc008..999368739a 100644 --- a/circuits/bin/insecure/Nargo.toml +++ b/circuits/bin/insecure/Nargo.toml @@ -11,5 +11,5 @@ members = [ "pk_agg_trbfv", "greco", "dec_share_trbfv", - "dec_share_agg_trbfv" + "dec_shares_agg_trbfv" ] \ No newline at end of file diff --git a/circuits/bin/production/Nargo.toml b/circuits/bin/production/Nargo.toml index 19670a5ae2..becb094990 100644 --- a/circuits/bin/production/Nargo.toml +++ b/circuits/bin/production/Nargo.toml @@ -11,5 +11,5 @@ members = [ "pk_agg_trbfv", "greco", "dec_share_trbfv", - "dec_share_agg_trbfv" + "dec_shares_agg_trbfv" ] \ No newline at end of file diff --git a/circuits/lib/src/configs/insecure/trbfv.nr b/circuits/lib/src/configs/insecure/trbfv.nr index 57fd01ed67..1efc95cbf1 100644 --- a/circuits/lib/src/configs/insecure/trbfv.nr +++ b/circuits/lib/src/configs/insecure/trbfv.nr @@ -155,17 +155,12 @@ pub global DEC_SHARES_BIT_R2: u32 = 36; pub global DEC_SHARES_BIT_D: u32 = 36; // dec_share_trbfv - bounds -pub global DEC_SHARES_DECRYPTION_SHARE_BOUND: Field = 34359701504; pub global DEC_SHARES_R1_BOUNDS: [Field; L] = [8796083584897, 8796061564801]; pub global DEC_SHARES_R2_BOUNDS: [Field; L] = [34359701504, 34359615488]; // dec_share_trbfv - configs -pub global DEC_SHARES_CONFIGS: DecShareTrBfvConfigs = DecShareTrBfvConfigs::new( - QIS, - DEC_SHARES_DECRYPTION_SHARE_BOUND, - DEC_SHARES_R1_BOUNDS, - DEC_SHARES_R2_BOUNDS, -); +pub global DEC_SHARES_CONFIGS: DecShareTrBfvConfigs = + DecShareTrBfvConfigs::new(QIS, DEC_SHARES_R1_BOUNDS, DEC_SHARES_R2_BOUNDS); /************************************ ------------------------------------- diff --git a/circuits/lib/src/configs/production/trbfv.nr b/circuits/lib/src/configs/production/trbfv.nr index 0df1636f99..351ee29516 100644 --- a/circuits/lib/src/configs/production/trbfv.nr +++ b/circuits/lib/src/configs/production/trbfv.nr @@ -163,19 +163,14 @@ pub global DEC_SHARES_BIT_R2: u32 = 53; pub global DEC_SHARES_BIT_D: u32 = 53; // dec_share_trbfv - bounds -pub global DEC_SHARES_DECRYPTION_SHARE_BOUND: Field = 2251799817289728; pub global DEC_SHARES_R1_BOUNDS: [Field; L] = [4611686035875690497, 9223372037660080129, 9223372045176272897, 9223372051618723841]; pub global DEC_SHARES_R2_BOUNDS: [Field; L] = [1125899911102464, 2251799813881856, 2251799815716864, 2251799817289728]; // dec_share_trbfv - configs -pub global DEC_SHARES_CONFIGS: DecShareTrBfvConfigs = DecShareTrBfvConfigs::new( - QIS, - DEC_SHARES_DECRYPTION_SHARE_BOUND, - DEC_SHARES_R1_BOUNDS, - DEC_SHARES_R2_BOUNDS, -); +pub global DEC_SHARES_CONFIGS: DecShareTrBfvConfigs = + DecShareTrBfvConfigs::new(QIS, DEC_SHARES_R1_BOUNDS, DEC_SHARES_R2_BOUNDS); /************************************ ------------------------------------- diff --git a/circuits/lib/src/core/trbfv_dec_share.nr b/circuits/lib/src/core/trbfv_dec_share.nr index c4151f3ab9..c98d37a594 100644 --- a/circuits/lib/src/core/trbfv_dec_share.nr +++ b/circuits/lib/src/core/trbfv_dec_share.nr @@ -15,8 +15,6 @@ use crate::math::polynomial::Polynomial; pub struct Configs { /// CRT moduli: [q_0, q_1, ..., q_{L-1}] pub qis: [Field; L], - /// Bound for decryption share coefficients - pub decryption_share_bound: Field, /// Bounds for r1 polynomials (modulus switching quotients) for each CRT basis pub r1_bounds: [Field; L], /// Bounds for r2 polynomials (cyclotomic reduction quotients) for each CRT basis @@ -24,13 +22,8 @@ pub struct Configs { } impl Configs { - pub fn new( - qis: [Field; L], - decryption_share_bound: Field, - r1_bounds: [Field; L], - r2_bounds: [Field; L], - ) -> Self { - Configs { qis, decryption_share_bound, r1_bounds, r2_bounds } + pub fn new(qis: [Field; L], r1_bounds: [Field; L], r2_bounds: [Field; L]) -> Self { + Configs { qis, r1_bounds, r2_bounds } } } From 6e1172be0d7b1f8d3115663ae97e98f6f2c94684 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 14:55:28 +0100 Subject: [PATCH 12/30] improve comment on ascending order of party_ids for C7 --- circuits/lib/src/core/trbfv_dec_shares_agg.nr | 1 + 1 file changed, 1 insertion(+) diff --git a/circuits/lib/src/core/trbfv_dec_shares_agg.nr b/circuits/lib/src/core/trbfv_dec_shares_agg.nr index fd638f69d5..4a4171257d 100644 --- a/circuits/lib/src/core/trbfv_dec_shares_agg.nr +++ b/circuits/lib/src/core/trbfv_dec_shares_agg.nr @@ -40,6 +40,7 @@ pub struct DecryptionSharesAggregation; L]; T + 1], /// Party IDs (x-coordinates) for interpolation (public inputs) + /// Note: Must be in strictly increasing order for correct Lagrange sign computation party_ids: [Field; T + 1], /// Message polynomial m(x) (public output) From ebcc3fd1571be67d5df6a4a2698755449cd2ce96 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 15:07:47 +0100 Subject: [PATCH 13/30] fix wrong formula for C7 --- circuits/lib/src/core/trbfv_dec_shares_agg.nr | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/circuits/lib/src/core/trbfv_dec_shares_agg.nr b/circuits/lib/src/core/trbfv_dec_shares_agg.nr index 4a4171257d..33378f95e3 100644 --- a/circuits/lib/src/core/trbfv_dec_shares_agg.nr +++ b/circuits/lib/src/core/trbfv_dec_shares_agg.nr @@ -241,9 +241,12 @@ impl Date: Mon, 19 Jan 2026 15:52:54 +0100 Subject: [PATCH 14/30] add missing assertion for determinism --- circuits/lib/src/math/helpers.nr | 1 + 1 file changed, 1 insertion(+) diff --git a/circuits/lib/src/math/helpers.nr b/circuits/lib/src/math/helpers.nr index ae94afe4e2..cd4392324c 100644 --- a/circuits/lib/src/math/helpers.nr +++ b/circuits/lib/src/math/helpers.nr @@ -299,6 +299,7 @@ fn test_safe_hashing_with_safe_helper() { assert(digests2.len() == 1); assert(digests2.get(0) != 0); + assert(digests2.get(0) == digests1.get(0)); } #[test] From 2574f61e769f48285aeb827a03d5a3ec5651586b Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 16:28:16 +0100 Subject: [PATCH 15/30] fix wrong flatten bit for a in C1 --- circuits/lib/src/core/trbfv_pk.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circuits/lib/src/core/trbfv_pk.nr b/circuits/lib/src/core/trbfv_pk.nr index 283130e3ad..ead069ea12 100644 --- a/circuits/lib/src/core/trbfv_pk.nr +++ b/circuits/lib/src/core/trbfv_pk.nr @@ -109,7 +109,7 @@ impl(inputs, self.a); + inputs = flatten::<_, _, BIT_PK>(inputs, self.a); // Flatten error polynomial eek (1 polynomial of degree N) inputs = flatten::<_, _, BIT_EEK>(inputs, [self.eek]); From 211bea26ebe8b5cc2797c44bf6d724b8e54d6a8c Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 16:32:47 +0100 Subject: [PATCH 16/30] small nits on docs, safety and script --- circuits/lib/src/configs/insecure/trbfv.nr | 6 +++--- circuits/lib/src/configs/production/trbfv.nr | 6 +++--- circuits/lib/src/core/trbfv_pk_agg.nr | 4 ++-- circuits/lib/src/math/modulo/U128.nr | 2 +- .../lib/src/math/modulo/unconstrained_U128.nr | 19 ++++++++++++++----- circuits/lib/src/math/polynomial.nr | 6 +++--- scripts/lint-circuits.sh | 5 +++-- 7 files changed, 29 insertions(+), 19 deletions(-) diff --git a/circuits/lib/src/configs/insecure/trbfv.nr b/circuits/lib/src/configs/insecure/trbfv.nr index 1efc95cbf1..f7d86c37d0 100644 --- a/circuits/lib/src/configs/insecure/trbfv.nr +++ b/circuits/lib/src/configs/insecure/trbfv.nr @@ -164,13 +164,13 @@ pub global DEC_SHARES_CONFIGS: DecShareTrBfvConfigs = /************************************ ------------------------------------- -dec_share_agg_trbfv (CIRCUIT 7 - DECRYPTION SHARE AGGREGATION TRBFV) +dec_shares_agg_trbfv (CIRCUIT 7 - DECRYPTION SHARE AGGREGATION TRBFV) ------------------------------------- ************************************/ -// dec_share_agg_trbfv - bit parameters +// dec_shares_agg_trbfv - bit parameters pub global DEC_SHARES_AGG_BIT_NOISE: u32 = 69; -// dec_share_agg_trbfv - configs +// dec_shares_agg_trbfv - configs pub global DEC_SHARES_AGG_CONFIGS: DecShareAggTrBfvConfigs = DecShareAggTrBfvConfigs::new(QIS, PLAINTEXT_MODULUS, Q_INVERSE_MOD_T); diff --git a/circuits/lib/src/configs/production/trbfv.nr b/circuits/lib/src/configs/production/trbfv.nr index 351ee29516..4899a9caea 100644 --- a/circuits/lib/src/configs/production/trbfv.nr +++ b/circuits/lib/src/configs/production/trbfv.nr @@ -174,13 +174,13 @@ pub global DEC_SHARES_CONFIGS: DecShareTrBfvConfigs = /************************************ ------------------------------------- -dec_share_agg_trbfv (CIRCUIT 7 - DECRYPTION SHARE AGGREGATION TRBFV) +dec_shares_agg_trbfv (CIRCUIT 7 - DECRYPTION SHARE AGGREGATION TRBFV) ------------------------------------- ************************************/ -// dec_share_agg_trbfv - bit parameters +// dec_shares_agg_trbfv - bit parameters pub global DEC_SHARES_AGG_BIT_NOISE: u32 = 201; -// dec_share_agg_trbfv - configs +// dec_shares_agg_trbfv - configs pub global DEC_SHARES_AGG_CONFIGS: DecShareAggTrBfvConfigs = DecShareAggTrBfvConfigs::new(QIS, PLAINTEXT_MODULUS, Q_INVERSE_MOD_T); diff --git a/circuits/lib/src/core/trbfv_pk_agg.nr b/circuits/lib/src/core/trbfv_pk_agg.nr index 61c441df0f..3cc4da7e5d 100644 --- a/circuits/lib/src/core/trbfv_pk_agg.nr +++ b/circuits/lib/src/core/trbfv_pk_agg.nr @@ -31,7 +31,7 @@ pub struct TrbfvPublicKeyAggregation, /// Expected commitments to public key TRBFV (from C1) - /// We need one comment from each honest party (H). + /// We need one commitment from each honest party (H). expected_pk_trbfv_commitments: [Field; H], /// Individual public keys from H honest parties (public inputs) @@ -111,7 +111,7 @@ impl TrbfvPublicKeyAggregat // 0. Verify pk commitments self.verify_pk_commitments(); - // 1. Verify pk & pk1 aggregations for each basis + // 1. Verify pk0 & pk1 aggregations for each basis for basis_idx in 0..L { self.verify_pk_for_basis(self.pk0, self.pk0_agg, basis_idx); self.verify_pk_for_basis(self.pk1, self.pk1_agg, basis_idx); diff --git a/circuits/lib/src/math/modulo/U128.nr b/circuits/lib/src/math/modulo/U128.nr index bc2db8a2bc..5c8c4e21a7 100644 --- a/circuits/lib/src/math/modulo/U128.nr +++ b/circuits/lib/src/math/modulo/U128.nr @@ -64,7 +64,7 @@ impl ModU128 { // Safety: __compute_mod_reduction is safe to call here because we assert the properties of the output let (q, r) = unsafe { __compute_mod_reduction(n, self.m) }; - // Ensure remainder is in [0, q) + // Ensure remainder is in [0, m) assert(r as u128 < self.m as u128); // Verify the reduction is correct assert(n == q * self.m + r); diff --git a/circuits/lib/src/math/modulo/unconstrained_U128.nr b/circuits/lib/src/math/modulo/unconstrained_U128.nr index e8944e8162..9d9bb4e242 100644 --- a/circuits/lib/src/math/modulo/unconstrained_U128.nr +++ b/circuits/lib/src/math/modulo/unconstrained_U128.nr @@ -101,15 +101,24 @@ pub unconstrained fn __sub_with_underflow(lhs: Field, rhs: Field, m: Field) -> ( /// # Returns /// A tuple `(quotient, remainder)` where `lhs * rhs = m * quotient + remainder` /// -/// # Note -/// For u128 values, the product can overflow Field, but for typical use cases -/// (e.g., party IDs <= 100), this is safe. +/// # Overflow Warning +/// Field multiplication wraps modulo the field prime (~254 bits). For two u128 values +/// near 2^128, their product (up to 2^256) exceeds the Field modulus, causing silent +/// wraparound before the mod reduction. This can produce incorrect results. +/// +/// # Safe Input Range +/// To avoid overflow, ensure `lhs * rhs < Field::MODULUS`. For typical use cases: +/// - Party IDs, polynomial coefficients, and small cryptographic values (< 2^64) are safe +/// - Arbitrary u128 values may overflow and should be validated by callers /// /// # Safety /// This is an unconstrained function. The result must be verified in constrained code. +/// Callers must ensure inputs are within the safe range to prevent silent overflow. pub unconstrained fn __mul_with_quotient(lhs: Field, rhs: Field, m: Field) -> (Field, Field) { - // For u128 values, product can overflow Field - // But since our values are small (party IDs <= 100), this is safe + // WARNING: Field multiplication can overflow for large inputs. + // For u128 values near 2^128, the product (up to 2^256) exceeds Field modulus (~2^254), + // causing wraparound. This is safe for typical use cases (party IDs, small coefficients), + // but callers must validate input ranges for arbitrary u128 values. let product = lhs * rhs; __compute_mod_reduction(product, m) } diff --git a/circuits/lib/src/math/polynomial.nr b/circuits/lib/src/math/polynomial.nr index 9419410447..7e38e488e4 100644 --- a/circuits/lib/src/math/polynomial.nr +++ b/circuits/lib/src/math/polynomial.nr @@ -128,13 +128,13 @@ impl Polynomial { for i in 1..len { acc = acc * x + self.coefficients[i]; // Only reduce if accumulator exceeds q - if acc as u64 >= m as u64 { + if acc as u128 >= m as u128 { acc = q.reduce_mod(acc); } } // Final reduction to ensure result is in [0, q) - if acc as u64 >= m as u64 { + if acc as u128 >= m as u128 { q.reduce_mod(acc) } else { acc @@ -394,7 +394,7 @@ fn test_eval_mod() { let poly4 = Polynomial::new([5, 3, 7]); let q = ModU128::new(17); let result4 = poly4.eval_mod(4, q); - assert(result4 as u64 < q.get_mod_field() as u64); + assert(result4 as u128 < q.get_mod_field() as u128); // Test 5: Compare with regular eval for small values let poly5 = Polynomial::new([1, 2, 1]); diff --git a/scripts/lint-circuits.sh b/scripts/lint-circuits.sh index 709891b74e..cd5cf2e558 100755 --- a/scripts/lint-circuits.sh +++ b/scripts/lint-circuits.sh @@ -24,13 +24,14 @@ for dir in "${DIRS[@]}"; do # Find all package directories and create empty Prover.toml to prevent nargo from creating them created_files=() - while IFS= read -r -d '' pkg_dir; do + while IFS= read -r -d '' nargo_file; do + pkg_dir=$(dirname "$nargo_file") prover_file="${pkg_dir}/Prover.toml" if [ ! -f "$prover_file" ]; then touch "$prover_file" created_files+=("$prover_file") fi - done < <(find . -name "Nargo.toml" -type f -print0 2>/dev/null | xargs -0 dirname 2>/dev/null || true) + done < <(find . -name "Nargo.toml" -type f -print0 2>/dev/null || true) # Checking circuit format. if ! (nargo fmt --check); then From a86254ee20d854c74720d5d0011809e7706437a4 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 16:42:20 +0100 Subject: [PATCH 17/30] fix potential overflow in unsafe sub --- .../lib/src/math/modulo/unconstrained_U128.nr | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/circuits/lib/src/math/modulo/unconstrained_U128.nr b/circuits/lib/src/math/modulo/unconstrained_U128.nr index 9d9bb4e242..9dbd3b4ead 100644 --- a/circuits/lib/src/math/modulo/unconstrained_U128.nr +++ b/circuits/lib/src/math/modulo/unconstrained_U128.nr @@ -73,6 +73,15 @@ pub unconstrained fn __neg(val: Field, m: Field) -> Field { /// - `result = (lhs - rhs) mod m` /// - `underflow = true` if `lhs < rhs`, `false` otherwise /// +/// # Overflow Warning +/// The computation `lhs_u128 + m_u128 - rhs_u128` can overflow u128 if +/// `lhs_u128 + m_u128 > 2^128 - 1`. To avoid overflow, ensure that for the +/// underflow case, `lhs_u128 + m_u128` does not exceed u128::MAX. +/// +/// # Safe Input Range +/// For typical use cases with moduli < 2^64, this is safe. For larger moduli +/// approaching 2^128, ensure `lhs < 2^128 - m` to prevent intermediate overflow. +/// /// # Safety /// This is an unconstrained function. The result must be verified in constrained code. pub unconstrained fn __sub_with_underflow(lhs: Field, rhs: Field, m: Field) -> (Field, bool) { @@ -82,7 +91,11 @@ pub unconstrained fn __sub_with_underflow(lhs: Field, rhs: Field, m: Field) -> ( let underflow = lhs_u128 < rhs_u128; let result = if underflow { - (lhs_u128 + m_u128 - rhs_u128) as Field + // Compute (lhs - rhs + m) mod m safely to avoid u128 overflow + // Since lhs < rhs, we compute: m - (rhs - lhs) + // This avoids the potential overflow in lhs + m + let diff = rhs_u128 - lhs_u128; // This is safe since rhs > lhs + (m_u128 - diff) as Field } else { (lhs_u128 - rhs_u128) as Field }; From 83ea3e0e34416cc892d0ca5b1608e1e47948673e Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 16:50:20 +0100 Subject: [PATCH 18/30] improve comment for range_check_2bounds --- circuits/lib/src/math/polynomial.nr | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/circuits/lib/src/math/polynomial.nr b/circuits/lib/src/math/polynomial.nr index 7e38e488e4..607da027b6 100644 --- a/circuits/lib/src/math/polynomial.nr +++ b/circuits/lib/src/math/polynomial.nr @@ -143,11 +143,12 @@ impl Polynomial { /// Performs range checking on polynomial coefficients using asymmetric bounds. /// - /// This function constrains all polynomial coefficients to be in the range [lower_bound, upper_bound]. + /// This function constrains all polynomial coefficients to be in the range [-lower_bound, upper_bound], + /// where `lower_bound` is a non-negative magnitude. /// It uses a shifting technique to handle negative numbers efficiently: /// 1. Shifts each coefficient by adding `lower_bound`: c' = c + lower_bound /// 2. Checks that shifted coefficients are in [0, upper_bound + lower_bound] using bit-size assertions - /// 3. This ensures original coefficients are in [lower_bound, upper_bound] + /// 3. This ensures original coefficients are in [-lower_bound, upper_bound] /// /// The function uses two bit-size checks per coefficient to ensure the value is within bounds: /// - `shifted_coefficient.assert_max_bit_size::()` ensures c' >= 0 @@ -155,12 +156,12 @@ impl Polynomial { /// /// # Arguments /// * `upper_bound` - The upper bound for coefficient range checking - /// * `lower_bound` - The lower bound for coefficient range checking - /// Coefficients must satisfy: lower_bound <= c <= upper_bound + /// * `lower_bound` - Non-negative magnitude of the negative bound + /// Coefficients must satisfy: -lower_bound <= c <= upper_bound /// /// # Generic Parameters - /// * `BIT` - The bit-length of the total range `upper_bound - lower_bound` - /// (choose `BIT` so `upper_bound - lower_bound < 2^BIT`). Since all checked + /// * `BIT` - The bit-length of the total range `upper_bound + lower_bound` + /// (choose `BIT` so `upper_bound + lower_bound < 2^BIT`). Since all checked /// values lie in `[0, upper_bound + lower_bound]`, they cannot exceed `BIT + 1` bits. /// /// # Panics From a08c50b4aa126ae441ab466ecc91543c0bc92d7b Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 16:55:38 +0100 Subject: [PATCH 19/30] make c7 pub inputs --- circuits/bin/insecure/dec_shares_agg_trbfv/src/main.nr | 6 +++--- circuits/bin/production/dec_shares_agg_trbfv/src/main.nr | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/circuits/bin/insecure/dec_shares_agg_trbfv/src/main.nr b/circuits/bin/insecure/dec_shares_agg_trbfv/src/main.nr index ec32da92e4..98b2124ce4 100644 --- a/circuits/bin/insecure/dec_shares_agg_trbfv/src/main.nr +++ b/circuits/bin/insecure/dec_shares_agg_trbfv/src/main.nr @@ -14,9 +14,9 @@ pub global MAX_MSG_NON_ZERO_COEFFS: u32 = 80; pub global T: u32 = 2; fn main( - decryption_shares: [[Polynomial; L]; T + 1], - party_ids: [Field; T + 1], - message: Polynomial, + decryption_shares: pub [[Polynomial; L]; T + 1], + party_ids: pub [Field; T + 1], + message: pub Polynomial, u_global: Polynomial, crt_quotients: [Polynomial; L], ) { diff --git a/circuits/bin/production/dec_shares_agg_trbfv/src/main.nr b/circuits/bin/production/dec_shares_agg_trbfv/src/main.nr index acf5246dee..1204a9ca3f 100644 --- a/circuits/bin/production/dec_shares_agg_trbfv/src/main.nr +++ b/circuits/bin/production/dec_shares_agg_trbfv/src/main.nr @@ -14,9 +14,9 @@ pub global MAX_MSG_NON_ZERO_COEFFS: u32 = 80; pub global T: u32 = 2; fn main( - decryption_shares: [[Polynomial; L]; T + 1], - party_ids: [Field; T + 1], - message: Polynomial, + decryption_shares: pub [[Polynomial; L]; T + 1], + party_ids: pub [Field; T + 1], + message: pub Polynomial, u_global: Polynomial, crt_quotients: [Polynomial; L], ) { From 84aec03a7af9a69826270fbdca2c7c20bde08be4 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 19 Jan 2026 17:13:41 +0100 Subject: [PATCH 20/30] rename t_bn --- circuits/lib/src/core/trbfv_dec_shares_agg.nr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/circuits/lib/src/core/trbfv_dec_shares_agg.nr b/circuits/lib/src/core/trbfv_dec_shares_agg.nr index 33378f95e3..8ff506131d 100644 --- a/circuits/lib/src/core/trbfv_dec_shares_agg.nr +++ b/circuits/lib/src/core/trbfv_dec_shares_agg.nr @@ -242,9 +242,9 @@ impl Date: Mon, 19 Jan 2026 18:18:17 +0100 Subject: [PATCH 21/30] fix: small fixes in CRISP after pvss migration --- crates/bfv-helpers/src/lib.rs | 21 +++++++++++++++++++ examples/CRISP/circuits/src/main.nr | 4 ++-- examples/CRISP/circuits/src/utils.nr | 2 +- .../crates/zk-inputs/src/serialization.rs | 15 +++---------- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/crates/bfv-helpers/src/lib.rs b/crates/bfv-helpers/src/lib.rs index 9549e68341..92c0fbcb1d 100644 --- a/crates/bfv-helpers/src/lib.rs +++ b/crates/bfv-helpers/src/lib.rs @@ -68,6 +68,14 @@ pub enum BfvParamSets { #[strum(serialize = "SET_8192_1000_4")] Set8192_1000_4, + /// 128bits security BFV parameters set (PRODUCTION READY). + /// - Degree: 8192 + /// - Plaintext modulus: 100 + /// - Moduli: [0x0008000000820001, 0x0010000000060001, 0x00100000003e0001, 0x00100000006e0001] + /// - Error2 Variance: 1004336277661868922213726307713258317841382576849282939643494400 + #[strum(serialize = "SET_8192_100_4")] + Set8192_100_4, + /// 128bits security BFV parameters set (PRODUCTION READY). /// - Degree: 8192 /// - Plaintext modulus: 144115188075855872 @@ -132,6 +140,19 @@ impl From for BfvParamSet { "52309181128222339698631578526730685514457152477762943514050560000", ), }, + B::Set8192_100_4 => BfvParamSet { + degree: 8192, + plaintext_modulus: 100, + moduli: &[ + 0x0008000000820001, + 0x0010000000060001, + 0x00100000003e0001, + 0x00100000006e0001, + ], + error1_variance: Some( + "1004336277661868922213726307713258317841382576849282939643494400", + ), + }, B::Set8192_144115188075855872_2 => BfvParamSet { degree: 8192, plaintext_modulus: 144115188075855872, diff --git a/examples/CRISP/circuits/src/main.nr b/examples/CRISP/circuits/src/main.nr index 422fc318ad..05c40689e0 100644 --- a/examples/CRISP/circuits/src/main.nr +++ b/examples/CRISP/circuits/src/main.nr @@ -6,7 +6,7 @@ use lib::configs::insecure::trbfv::{ GRECO_BIT_CT, GRECO_BIT_E0, GRECO_BIT_E1, GRECO_BIT_K, GRECO_BIT_P1, GRECO_BIT_P2, GRECO_BIT_PK, - GRECO_BIT_R1, GRECO_BIT_R2, GRECO_BIT_U, GRECO_CONFIGS, L, N, Q_MOD_T, + GRECO_BIT_R1, GRECO_BIT_R2, GRECO_BIT_U, GRECO_CONFIGS, L, N, Q_MOD_T_MOD_P, }; use lib::core::greco::Greco; use lib::math::polynomial::Polynomial; @@ -217,7 +217,7 @@ fn main( // - If first vote in slot: return zero ciphertext (ct0is, ct1is) // - If updating slot: verify addition and return sum of previous votes if (is_signature_valid == true) & (slot_address == address) { - check_coefficient_values_with_balance(k1, Q_MOD_T, balance); + check_coefficient_values_with_balance(k1, Q_MOD_T_MOD_P, balance); ct_commitment } else { diff --git a/examples/CRISP/circuits/src/utils.nr b/examples/CRISP/circuits/src/utils.nr index f4426e94a3..10b17c4ce3 100644 --- a/examples/CRISP/circuits/src/utils.nr +++ b/examples/CRISP/circuits/src/utils.nr @@ -17,7 +17,7 @@ use crate::constants::HALF_LARGEST_MINIMUM_DEGREE; /// /// # Arguments /// * `k1` - The plaintext polynomial encoding the vote -/// * `q_mod_t` - The plaintext modulus (typically 1 for binary encoding) +/// * `q_mod_t` - The field representation of 1 (Q_MOD_T_MOD_P for binary encoding) /// * `balance` - The voter's balance/voting power pub fn check_coefficient_values_with_balance( k1: Polynomial, diff --git a/examples/CRISP/crates/zk-inputs/src/serialization.rs b/examples/CRISP/crates/zk-inputs/src/serialization.rs index 2940ee8d9e..8a3c53017d 100644 --- a/examples/CRISP/crates/zk-inputs/src/serialization.rs +++ b/examples/CRISP/crates/zk-inputs/src/serialization.rs @@ -237,20 +237,11 @@ pub fn construct_inputs( "coefficients": to_string_1d_vec(&vectors_standard.e0) }), e0_quotients: vectors_standard - .e0is + .e0_quotients .iter() - .enumerate() - .map(|(i, e0i)| { - // Compute quotients: e0_quotient[i][j] = (e0[j] - e0is[i][j]) / qis[i] - let qi = &crypto_params.moduli[i]; - let quotients: Vec = vectors_standard - .e0 - .iter() - .zip(e0i.iter()) - .map(|(e0_coeff, e0i_coeff)| (e0_coeff - e0i_coeff) / qi) - .collect(); + .map(|v| { serde_json::json!({ - "coefficients": to_string_1d_vec("ients) + "coefficients": to_string_1d_vec(v) }) }) .collect(), From 8f5bb5723a5e4baf6b8495dc13f7af3ec2fa1d90 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 20 Jan 2026 10:19:34 +0100 Subject: [PATCH 22/30] avoid intermediate overflow in eval_mod --- circuits/lib/src/math/polynomial.nr | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/circuits/lib/src/math/polynomial.nr b/circuits/lib/src/math/polynomial.nr index 607da027b6..292d6d41c4 100644 --- a/circuits/lib/src/math/polynomial.nr +++ b/circuits/lib/src/math/polynomial.nr @@ -110,9 +110,9 @@ impl Polynomial { /// modular reductions to prevent overflow. The result is guaranteed to be in /// the range `[0, q)`. /// - /// The function performs lazy reduction: it only reduces the accumulator modulo - /// `q` when it exceeds the modulus, which is more efficient than reducing after - /// every operation while still preventing overflow. + /// The function performs modular reduction after each multiplication and addition + /// to ensure the accumulator always remains in the range `[0, q)`, preventing + /// any potential overflow issues. /// /// # Arguments /// * `x` - The point at which to evaluate the polynomial @@ -121,24 +121,15 @@ impl Polynomial { /// # Returns /// The value `P(x) mod q` in the range `[0, q)` pub fn eval_mod(self, x: Field, q: ModU128) -> Field { - let m = q.get_mod_field(); let mut acc = self.coefficients[0]; let len = self.coefficients.len(); for i in 1..len { - acc = acc * x + self.coefficients[i]; - // Only reduce if accumulator exceeds q - if acc as u128 >= m as u128 { - acc = q.reduce_mod(acc); - } + acc = q.mul_mod(acc, x); + acc = q.add(acc, self.coefficients[i]); } - // Final reduction to ensure result is in [0, q) - if acc as u128 >= m as u128 { - q.reduce_mod(acc) - } else { - acc - } + acc } /// Performs range checking on polynomial coefficients using asymmetric bounds. From 648cb8c1c939a49a714649a75131bbb2a8c04d6e Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 20 Jan 2026 10:36:46 +0100 Subject: [PATCH 23/30] update stale overflow warning in sub_with_underflow method --- .../lib/src/math/modulo/unconstrained_U128.nr | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/circuits/lib/src/math/modulo/unconstrained_U128.nr b/circuits/lib/src/math/modulo/unconstrained_U128.nr index 9dbd3b4ead..52a812cb85 100644 --- a/circuits/lib/src/math/modulo/unconstrained_U128.nr +++ b/circuits/lib/src/math/modulo/unconstrained_U128.nr @@ -63,27 +63,26 @@ pub unconstrained fn __neg(val: Field, m: Field) -> Field { /// Computes `(lhs - rhs) mod m`, handling the case where `lhs < rhs` by adding /// the modulus. Returns both the result and a flag indicating if underflow occurred. /// +/// # Preconditions +/// Inputs must be reduced modulo `m` such that `lhs, rhs in [0, m)`. This ensures +/// that the computed difference is bounded and cannot overflow `u128`. +/// /// # Arguments -/// * `lhs` - Left-hand side value (minuend) -/// * `rhs` - Right-hand side value (subtrahend) -/// * `m` - The modulus +/// * `lhs` - Left-hand side value (minuend), must be in `[0, m)` +/// * `rhs` - Right-hand side value (subtrahend), must be in `[0, m)` +/// * `m` - The modulus, must satisfy `m <= u128::MAX` /// /// # Returns /// A tuple `(result, underflow)` where: /// - `result = (lhs - rhs) mod m` /// - `underflow = true` if `lhs < rhs`, `false` otherwise /// -/// # Overflow Warning -/// The computation `lhs_u128 + m_u128 - rhs_u128` can overflow u128 if -/// `lhs_u128 + m_u128 > 2^128 - 1`. To avoid overflow, ensure that for the -/// underflow case, `lhs_u128 + m_u128` does not exceed u128::MAX. -/// -/// # Safe Input Range -/// For typical use cases with moduli < 2^64, this is safe. For larger moduli -/// approaching 2^128, ensure `lhs < 2^128 - m` to prevent intermediate overflow. -/// /// # Safety /// This is an unconstrained function. The result must be verified in constrained code. +/// As long as inputs are reduced modulo `m` (and `m <= u128::MAX`), the subtraction-with-underflow +/// logic is safe and will not overflow `u128`. This function is used by the constrained `sub` method +/// in `modulo::U128`, which ensures inputs are properly reduced before calling `__sub_with_underflow`. +/// See the surrounding `modulo/unconstrained_U128` module documentation for details. pub unconstrained fn __sub_with_underflow(lhs: Field, rhs: Field, m: Field) -> (Field, bool) { let lhs_u128 = lhs as u128; let rhs_u128 = rhs as u128; From a51e215a3cfe97cae53073da8cbd3cb721fbe205 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 20 Jan 2026 15:35:39 +0100 Subject: [PATCH 24/30] update public inputs --- .../bin/insecure/dec_share_trbfv/src/main.nr | 6 +++--- circuits/bin/insecure/enc_bfv_e_sm/src/main.nr | 8 ++++---- circuits/bin/insecure/enc_bfv_sk/src/main.nr | 8 ++++---- circuits/bin/insecure/pk_trbfv/src/main.nr | 2 +- .../bin/production/dec_share_trbfv/src/main.nr | 6 +++--- circuits/bin/production/enc_bfv_e_sm/src/main.nr | 8 ++++---- circuits/bin/production/enc_bfv_sk/src/main.nr | 8 ++++---- circuits/bin/production/pk_trbfv/src/main.nr | 2 +- circuits/lib/src/core/bfv_dec.nr | 2 ++ circuits/lib/src/core/bfv_enc.nr | 16 +++++++++------- circuits/lib/src/core/trbfv_dec_share.nr | 7 +++++-- circuits/lib/src/core/trbfv_dec_shares_agg.nr | 6 +++--- circuits/lib/src/core/trbfv_pk.nr | 6 +++--- circuits/lib/src/core/trbfv_pk_agg.nr | 9 +++++++-- circuits/lib/src/core/trbfv_verify_shares.nr | 4 ++++ 15 files changed, 57 insertions(+), 41 deletions(-) diff --git a/circuits/bin/insecure/dec_share_trbfv/src/main.nr b/circuits/bin/insecure/dec_share_trbfv/src/main.nr index 2ee4c57ab0..637db1eb7a 100644 --- a/circuits/bin/insecure/dec_share_trbfv/src/main.nr +++ b/circuits/bin/insecure/dec_share_trbfv/src/main.nr @@ -19,13 +19,13 @@ pub global T: u32 = 2; fn main( expected_s_commitment: pub Field, expected_e_commitment: pub Field, - c_0: [Polynomial; L], - c_1: [Polynomial; L], + c_0: pub [Polynomial; L], + c_1: pub [Polynomial; L], s: [Polynomial; L], e: [Polynomial; L], r_1: [Polynomial<(2 * N) - 1>; L], r_2: [Polynomial; L], - d: [Polynomial; L], + d: pub [Polynomial; L], ) { let dec_share: DecryptionShare = DecryptionShare::new( DEC_SHARES_CONFIGS, diff --git a/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr b/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr index 8f64f210c0..43ca54689a 100644 --- a/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr +++ b/circuits/bin/insecure/enc_bfv_e_sm/src/main.nr @@ -16,8 +16,8 @@ fn main( expected_message_commitment: pub Field, pk0is: [Polynomial; L], pk1is: [Polynomial; L], - ct0is: [Polynomial; L], - ct1is: [Polynomial; L], + ct0is: pub [Polynomial; L], + ct1is: pub [Polynomial; L], u: Polynomial, e0: Polynomial, e0is: [Polynomial; L], @@ -28,7 +28,7 @@ fn main( r2is: [Polynomial; L], p1is: [Polynomial<(2 * N) - 1>; L], p2is: [Polynomial; L], -) -> pub bool { +) { let enc_bfv: EncryptionBfv = EncryptionBfv::new( ENC_BFV_CONFIGS_E_SM, expected_pk_commitment, @@ -48,5 +48,5 @@ fn main( p1is, p2is, ); - enc_bfv.verify() + enc_bfv.verify(); } diff --git a/circuits/bin/insecure/enc_bfv_sk/src/main.nr b/circuits/bin/insecure/enc_bfv_sk/src/main.nr index ae2865e020..11d4ed60e7 100644 --- a/circuits/bin/insecure/enc_bfv_sk/src/main.nr +++ b/circuits/bin/insecure/enc_bfv_sk/src/main.nr @@ -16,8 +16,8 @@ fn main( expected_message_commitment: pub Field, pk0is: [Polynomial; L], pk1is: [Polynomial; L], - ct0is: [Polynomial; L], - ct1is: [Polynomial; L], + ct0is: pub [Polynomial; L], + ct1is: pub [Polynomial; L], u: Polynomial, e0: Polynomial, e0is: [Polynomial; L], @@ -28,7 +28,7 @@ fn main( r2is: [Polynomial; L], p1is: [Polynomial<(2 * N) - 1>; L], p2is: [Polynomial; L], -) -> pub bool { +) { let enc_bfv: EncryptionBfv = EncryptionBfv::new( ENC_BFV_CONFIGS_SK, expected_pk_commitment, @@ -48,5 +48,5 @@ fn main( p1is, p2is, ); - enc_bfv.verify() + enc_bfv.verify(); } diff --git a/circuits/bin/insecure/pk_trbfv/src/main.nr b/circuits/bin/insecure/pk_trbfv/src/main.nr index fa2699c1c5..b79b9fc5c1 100644 --- a/circuits/bin/insecure/pk_trbfv/src/main.nr +++ b/circuits/bin/insecure/pk_trbfv/src/main.nr @@ -12,7 +12,7 @@ use lib::core::trbfv_pk::TrbfvPublicKey; use lib::math::polynomial::Polynomial; fn main( - a: [Polynomial; L], + a: pub [Polynomial; L], eek: Polynomial, sk: Polynomial, e_sm: Polynomial, diff --git a/circuits/bin/production/dec_share_trbfv/src/main.nr b/circuits/bin/production/dec_share_trbfv/src/main.nr index 97b256e14d..98e7e9d8d5 100644 --- a/circuits/bin/production/dec_share_trbfv/src/main.nr +++ b/circuits/bin/production/dec_share_trbfv/src/main.nr @@ -19,13 +19,13 @@ pub global T: u32 = 2; fn main( expected_s_commitment: pub Field, expected_e_commitment: pub Field, - c_0: [Polynomial; L], - c_1: [Polynomial; L], + c_0: pub [Polynomial; L], + c_1: pub [Polynomial; L], s: [Polynomial; L], e: [Polynomial; L], r_1: [Polynomial<(2 * N) - 1>; L], r_2: [Polynomial; L], - d: [Polynomial; L], + d: pub [Polynomial; L], ) { let dec_share: DecryptionShare = DecryptionShare::new( DEC_SHARES_CONFIGS, diff --git a/circuits/bin/production/enc_bfv_e_sm/src/main.nr b/circuits/bin/production/enc_bfv_e_sm/src/main.nr index 8196c9b296..dd2b492cb7 100644 --- a/circuits/bin/production/enc_bfv_e_sm/src/main.nr +++ b/circuits/bin/production/enc_bfv_e_sm/src/main.nr @@ -16,8 +16,8 @@ fn main( expected_message_commitment: pub Field, pk0is: [Polynomial; L], pk1is: [Polynomial; L], - ct0is: [Polynomial; L], - ct1is: [Polynomial; L], + ct0is: pub [Polynomial; L], + ct1is: pub [Polynomial; L], u: Polynomial, e0: Polynomial, e0is: [Polynomial; L], @@ -28,7 +28,7 @@ fn main( r2is: [Polynomial; L], p1is: [Polynomial<(2 * N) - 1>; L], p2is: [Polynomial; L], -) -> pub bool { +) { let enc_bfv: EncryptionBfv = EncryptionBfv::new( ENC_BFV_CONFIGS_E_SM, expected_pk_commitment, @@ -48,5 +48,5 @@ fn main( p1is, p2is, ); - enc_bfv.verify() + enc_bfv.verify(); } diff --git a/circuits/bin/production/enc_bfv_sk/src/main.nr b/circuits/bin/production/enc_bfv_sk/src/main.nr index 2be42ef1b7..c290b8b2a1 100644 --- a/circuits/bin/production/enc_bfv_sk/src/main.nr +++ b/circuits/bin/production/enc_bfv_sk/src/main.nr @@ -16,8 +16,8 @@ fn main( expected_message_commitment: pub Field, pk0is: [Polynomial; L], pk1is: [Polynomial; L], - ct0is: [Polynomial; L], - ct1is: [Polynomial; L], + ct0is: pub [Polynomial; L], + ct1is: pub [Polynomial; L], u: Polynomial, e0: Polynomial, e0is: [Polynomial; L], @@ -28,7 +28,7 @@ fn main( r2is: [Polynomial; L], p1is: [Polynomial<(2 * N) - 1>; L], p2is: [Polynomial; L], -) -> pub bool { +) { let enc_bfv: EncryptionBfv = EncryptionBfv::new( ENC_BFV_CONFIGS_SK, expected_pk_commitment, @@ -48,5 +48,5 @@ fn main( p1is, p2is, ); - enc_bfv.verify() + enc_bfv.verify(); } diff --git a/circuits/bin/production/pk_trbfv/src/main.nr b/circuits/bin/production/pk_trbfv/src/main.nr index f42727ae16..314e0a66b8 100644 --- a/circuits/bin/production/pk_trbfv/src/main.nr +++ b/circuits/bin/production/pk_trbfv/src/main.nr @@ -12,7 +12,7 @@ use lib::core::trbfv_pk::TrbfvPublicKey; use lib::math::polynomial::Polynomial; fn main( - a: [Polynomial; L], + a: pub [Polynomial; L], eek: Polynomial, sk: Polynomial, e_sm: Polynomial, diff --git a/circuits/lib/src/core/bfv_dec.nr b/circuits/lib/src/core/bfv_dec.nr index 8960813efb..20ee81bcca 100644 --- a/circuits/lib/src/core/bfv_dec.nr +++ b/circuits/lib/src/core/bfv_dec.nr @@ -18,9 +18,11 @@ use crate::math::polynomial::Polynomial; /// 3. Returns commitment to aggregated shares pub struct BfvDecCommitVerify { /// Expected commitments from Circuit 3 for H honest parties: [party_idx][mod_idx] + /// (public witness) expected_commitments: [[Field; L]; H], /// Decrypted shares from H honest parties: [party_idx][mod_idx] + /// (secret witnesses) decrypted_shares: [[Polynomial; L]; H], } diff --git a/circuits/lib/src/core/bfv_enc.nr b/circuits/lib/src/core/bfv_enc.nr index 27fb2bfae1..763e01ceb8 100644 --- a/circuits/lib/src/core/bfv_enc.nr +++ b/circuits/lib/src/core/bfv_enc.nr @@ -92,16 +92,18 @@ pub struct EncryptionBfv, /// Expected commitment to public key (from Circuit 0) + /// (public witness) expected_pk_commitment: Field, /// Expected commitment to message (from SK shares verification circuit) + /// (public witness) expected_message_commitment: Field, - /// Public key component 0 for each CRT basis (public inputs) + /// Public key component 0 for each CRT basis (committed witnesses) pk0is: [Polynomial; L], - /// Public key component 1 for each CRT basis (public inputs) + /// Public key component 1 for each CRT basis (committed witnesses) pk1is: [Polynomial; L], - /// Ciphertext component 0 for each CRT basis (public inputs) + /// Ciphertext component 0 for each CRT basis (public witnesses) ct0is: [Polynomial; L], - /// Ciphertext component 1 for each CRT basis (public inputs) + /// Ciphertext component 1 for each CRT basis (public witnesses) ct1is: [Polynomial; L], /// Random ternary polynomial u (secret witness) u: Polynomial, @@ -262,7 +264,7 @@ impl bool { + pub fn verify(self) { // Step 1: Verify public key commitment matches expected self.verify_pk_commitment(); @@ -332,7 +334,7 @@ impl, k1: Polynomial) -> bool { + fn verify_evaluations(self, gammas: Vec, k1: Polynomial) { let gamma = gammas.get(0); let cyclo_at_gamma = gamma.pow_32(N as Field) + 1; let u_at_gamma = self.u.eval(gamma); @@ -370,6 +372,6 @@ impl, /// Expected commitment to aggregated shares s (from BFV decryption circuit) + /// (public witness) expected_s_commitment: Field, /// Expected commitment to aggregated noise e (from BFV decryption circuit) + /// (public witness) expected_e_commitment: Field, - /// Ciphertext components (public inputs) + /// Ciphertext components (public witnesses) /// c_0 components for each CRT basis (degree N-1 polynomials with N coefficients) c_0: [Polynomial; L], /// c_1 components for each CRT basis (degree N-1 polynomials with N coefficients) @@ -60,7 +62,8 @@ pub struct DecryptionShare; L], r_2: [Polynomial; L], - /// Party's computed decryption share (public output) + /// Party's computed decryption share + /// (public witnesses) d: [Polynomial; L], } diff --git a/circuits/lib/src/core/trbfv_dec_shares_agg.nr b/circuits/lib/src/core/trbfv_dec_shares_agg.nr index 8ff506131d..c5416964a8 100644 --- a/circuits/lib/src/core/trbfv_dec_shares_agg.nr +++ b/circuits/lib/src/core/trbfv_dec_shares_agg.nr @@ -36,14 +36,14 @@ pub struct DecryptionSharesAggregation, - /// Decryption shares from t+1 parties (public inputs) + /// Decryption shares from t+1 parties (public witnesses) decryption_shares: [[Polynomial; L]; T + 1], - /// Party IDs (x-coordinates) for interpolation (public inputs) + /// Party IDs (x-coordinates) for interpolation (public witnesses) /// Note: Must be in strictly increasing order for correct Lagrange sign computation party_ids: [Field; T + 1], - /// Message polynomial m(x) (public output) + /// Message polynomial m(x) (public witness) message: Polynomial, /// Global u polynomial (secret witness) diff --git a/circuits/lib/src/core/trbfv_pk.nr b/circuits/lib/src/core/trbfv_pk.nr index ead069ea12..c910523283 100644 --- a/circuits/lib/src/core/trbfv_pk.nr +++ b/circuits/lib/src/core/trbfv_pk.nr @@ -55,7 +55,7 @@ pub struct TrbfvPublicKey, - /// Common Reference String polynomials (public) + /// Common Reference String polynomials (public witnesses) /// One polynomial per modulus i a: [Polynomial; L], @@ -71,13 +71,13 @@ pub struct TrbfvPublicKey, - /// Quotients from polynomial operations (secret witness) + /// Quotients from polynomial operations (secret witnesses) /// r1[i] are quotients from modulus switching for modulus i (can be negative, degree 2*N-1) r1: [Polynomial<2 * N - 1>; L], /// r2[i] are quotients from cyclotomic reduction for modulus i (typically positive, degree N-1) r2: [Polynomial; L], - /// TRBFV public key components (public output) + /// TRBFV public key components (committed witnesses) /// pk0[i] is the first component of the public key for modulus i pk0: [Polynomial; L], /// pk1[i] is the second component of the public key for modulus i (should equal a[i]) diff --git a/circuits/lib/src/core/trbfv_pk_agg.nr b/circuits/lib/src/core/trbfv_pk_agg.nr index 3cc4da7e5d..a94a7c3c58 100644 --- a/circuits/lib/src/core/trbfv_pk_agg.nr +++ b/circuits/lib/src/core/trbfv_pk_agg.nr @@ -32,18 +32,23 @@ pub struct TrbfvPublicKeyAggregation; L]; H], /// pk1[party_idx][basis_idx] - second component of public key for each party and CRT basis + /// (committed witnesses) pk1: [[Polynomial; L]; H], - /// Claimed aggregated public key (public inputs) + /// Claimed aggregated public key /// pk0_agg[basis_idx] - first component of aggregated public key for each CRT basis + /// (committed witnesses) pk0_agg: [Polynomial; L], /// pk1_agg[basis_idx] - second component of aggregated public key for each CRT basis + /// (committed witnesses) pk1_agg: [Polynomial; L], } diff --git a/circuits/lib/src/core/trbfv_verify_shares.nr b/circuits/lib/src/core/trbfv_verify_shares.nr index eb35bbb77d..29c0552414 100644 --- a/circuits/lib/src/core/trbfv_verify_shares.nr +++ b/circuits/lib/src/core/trbfv_verify_shares.nr @@ -35,16 +35,20 @@ impl Configs { pub struct VerifySharesSk { configs: Configs, /// Expected commitment to secret (from C1) + /// (public witness) expected_secret_commitment: Field, /// Secret key polynomial: Polynomial /// trinary coefficients + /// (secret witness) secret_sk: Polynomial, /// Shares: y[coeff_idx][mod_idx][0..N_PARTIES+1] /// y[i][j][0] = secret_sk[i] = f(0), y[i][j][k] = f(k) for k = 1..N_PARTIES + /// (secret witnesses) y: [[[Field; N_PARTIES + 1]; L]; N], /// Parity check matrices: H[mod_idx][row][col] /// Size per modulus: (N_PARTIES - T) * (N_PARTIES + 1) /// H * y^T = 0 mod q_j + /// (public constants) h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], } From 659a4b5f177daf3b07983f636ffe298fec115cbf Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 20 Jan 2026 16:10:13 +0100 Subject: [PATCH 25/30] add wrappers --- .../insecure/dec_bfv_wrapper/Nargo.toml | 9 +++++ .../insecure/dec_bfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../dec_share_trbfv_wrapper/Nargo.toml | 9 +++++ .../dec_share_trbfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../dec_shares_agg_trbfv_wrapper/Nargo.toml | 9 +++++ .../dec_shares_agg_trbfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../insecure/enc_bfv_wrapper/Nargo.toml | 9 +++++ .../insecure/enc_bfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../insecure/pk_agg_trbfv_wrapper/Nargo.toml | 9 +++++ .../pk_agg_trbfv_wrapper}/src/main.nr | 16 ++++----- .../pk_trbfv_wrapper/Nargo.toml | 0 .../insecure/pk_trbfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../verify_shares_trbfv_wrapper/src/main.nr | 16 ++++----- .../production/dec_bfv_wrapper/Nargo.toml | 9 +++++ .../production/dec_bfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../dec_share_trbfv_wrapper/Nargo.toml | 9 +++++ .../dec_share_trbfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../dec_shares_agg_trbfv_wrapper/Nargo.toml | 9 +++++ .../dec_shares_agg_trbfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../production/enc_bfv_wrapper/Nargo.toml | 9 +++++ .../production/enc_bfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../pk_agg_trbfv_wrapper/Nargo.toml | 9 +++++ .../pk_agg_trbfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../production/pk_trbfv_wrapper/Nargo.toml | 9 +++++ .../production/pk_trbfv_wrapper/src/main.nr | 34 +++++++++++++++++++ .../verify_shares_trbfv_wrapper/src/main.nr | 16 ++++----- 26 files changed, 497 insertions(+), 24 deletions(-) create mode 100644 circuits/bin/aggregation/insecure/dec_bfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/insecure/dec_bfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/insecure/dec_share_trbfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/insecure/dec_share_trbfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/insecure/dec_shares_agg_trbfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/insecure/dec_shares_agg_trbfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/insecure/enc_bfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/insecure/enc_bfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/insecure/pk_agg_trbfv_wrapper/Nargo.toml rename circuits/bin/aggregation/{pk_trbfv_wrapper => insecure/pk_agg_trbfv_wrapper}/src/main.nr (57%) rename circuits/bin/aggregation/{ => insecure}/pk_trbfv_wrapper/Nargo.toml (100%) create mode 100644 circuits/bin/aggregation/insecure/pk_trbfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/production/dec_bfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/production/dec_bfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/production/dec_share_trbfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/production/dec_share_trbfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/production/dec_shares_agg_trbfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/production/dec_shares_agg_trbfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/production/enc_bfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/production/enc_bfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/production/pk_agg_trbfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/production/pk_agg_trbfv_wrapper/src/main.nr create mode 100644 circuits/bin/aggregation/production/pk_trbfv_wrapper/Nargo.toml create mode 100644 circuits/bin/aggregation/production/pk_trbfv_wrapper/src/main.nr diff --git a/circuits/bin/aggregation/insecure/dec_bfv_wrapper/Nargo.toml b/circuits/bin/aggregation/insecure/dec_bfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..dce69a5e29 --- /dev/null +++ b/circuits/bin/aggregation/insecure/dec_bfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_bfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/insecure/dec_bfv_wrapper/src/main.nr b/circuits/bin/aggregation/insecure/dec_bfv_wrapper/src/main.nr new file mode 100644 index 0000000000..1135d82692 --- /dev/null +++ b/circuits/bin/aggregation/insecure/dec_bfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 2; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 11; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/insecure/dec_share_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/insecure/dec_share_trbfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..71d46d5a18 --- /dev/null +++ b/circuits/bin/aggregation/insecure/dec_share_trbfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_share_trbfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/insecure/dec_share_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/insecure/dec_share_trbfv_wrapper/src/main.nr new file mode 100644 index 0000000000..a6ef2a7033 --- /dev/null +++ b/circuits/bin/aggregation/insecure/dec_share_trbfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 1; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 3074; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/insecure/dec_shares_agg_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/insecure/dec_shares_agg_trbfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..2a78a4a42a --- /dev/null +++ b/circuits/bin/aggregation/insecure/dec_shares_agg_trbfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_shares_agg_trbfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/insecure/dec_shares_agg_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/insecure/dec_shares_agg_trbfv_wrapper/src/main.nr new file mode 100644 index 0000000000..28b73825a7 --- /dev/null +++ b/circuits/bin/aggregation/insecure/dec_shares_agg_trbfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 1; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 563; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/insecure/enc_bfv_wrapper/Nargo.toml b/circuits/bin/aggregation/insecure/enc_bfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..40ab5f97e6 --- /dev/null +++ b/circuits/bin/aggregation/insecure/enc_bfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "enc_bfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/insecure/enc_bfv_wrapper/src/main.nr b/circuits/bin/aggregation/insecure/enc_bfv_wrapper/src/main.nr new file mode 100644 index 0000000000..e313a80056 --- /dev/null +++ b/circuits/bin/aggregation/insecure/enc_bfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 2; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 1026; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/insecure/pk_agg_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/insecure/pk_agg_trbfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..0b985dd2cc --- /dev/null +++ b/circuits/bin/aggregation/insecure/pk_agg_trbfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "pk_agg_trbfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/insecure/pk_agg_trbfv_wrapper/src/main.nr similarity index 57% rename from circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr rename to circuits/bin/aggregation/insecure/pk_agg_trbfv_wrapper/src/main.nr index 3feb9806de..f56ef89641 100644 --- a/circuits/bin/aggregation/pk_trbfv_wrapper/src/main.nr +++ b/circuits/bin/aggregation/insecure/pk_agg_trbfv_wrapper/src/main.nr @@ -9,26 +9,26 @@ use lib::math::commitments::compute_aggregation_commitment; // Number of proofs. pub global N_PROOFS: u32 = 1; -/// Number of commitments per proof. -pub global N_COMMITMENTS: u32 = 3; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 6; fn main( verification_key: UltraHonkVerificationKey, proofs: [UltraHonkProof; N_PROOFS], - commitments: pub [[Field; N_COMMITMENTS]; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], key_hash: Field, ) -> pub Field { for i in 0..N_PROOFS { - verify_ultrahonk_proof(verification_key, proofs[i], commitments[i], key_hash); + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); } - let mut aggregated_commitments = Vec::new(); + let mut aggregated_public_inputs = Vec::new(); for i in 0..N_PROOFS { - for j in 0..N_COMMITMENTS { - aggregated_commitments.push(commitments[i][j]); + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); } } - compute_aggregation_commitment(aggregated_commitments) + compute_aggregation_commitment(aggregated_public_inputs) } diff --git a/circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/insecure/pk_trbfv_wrapper/Nargo.toml similarity index 100% rename from circuits/bin/aggregation/pk_trbfv_wrapper/Nargo.toml rename to circuits/bin/aggregation/insecure/pk_trbfv_wrapper/Nargo.toml diff --git a/circuits/bin/aggregation/insecure/pk_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/insecure/pk_trbfv_wrapper/src/main.nr new file mode 100644 index 0000000000..0be092170e --- /dev/null +++ b/circuits/bin/aggregation/insecure/pk_trbfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 1; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 1027; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr index 73c8d34e91..1135d82692 100644 --- a/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr +++ b/circuits/bin/aggregation/insecure/verify_shares_trbfv_wrapper/src/main.nr @@ -9,26 +9,26 @@ use lib::math::commitments::compute_aggregation_commitment; // Number of proofs. pub global N_PROOFS: u32 = 2; -/// Number of commitments per proof. -pub global N_COMMITMENTS: u32 = 10; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 11; fn main( verification_key: UltraHonkVerificationKey, proofs: [UltraHonkProof; N_PROOFS], - commitments: pub [[Field; N_COMMITMENTS]; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], key_hash: Field, ) -> pub Field { for i in 0..N_PROOFS { - verify_ultrahonk_proof(verification_key, proofs[i], commitments[i], key_hash); + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); } - let mut aggregated_commitments = Vec::new(); + let mut aggregated_public_inputs = Vec::new(); for i in 0..N_PROOFS { - for j in 0..N_COMMITMENTS { - aggregated_commitments.push(commitments[i][j]); + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); } } - compute_aggregation_commitment(aggregated_commitments) + compute_aggregation_commitment(aggregated_public_inputs) } diff --git a/circuits/bin/aggregation/production/dec_bfv_wrapper/Nargo.toml b/circuits/bin/aggregation/production/dec_bfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..dce69a5e29 --- /dev/null +++ b/circuits/bin/aggregation/production/dec_bfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_bfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/production/dec_bfv_wrapper/src/main.nr b/circuits/bin/aggregation/production/dec_bfv_wrapper/src/main.nr new file mode 100644 index 0000000000..b3a6225c3a --- /dev/null +++ b/circuits/bin/aggregation/production/dec_bfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 2; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 21; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/production/dec_share_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/production/dec_share_trbfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..71d46d5a18 --- /dev/null +++ b/circuits/bin/aggregation/production/dec_share_trbfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_share_trbfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/production/dec_share_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/production/dec_share_trbfv_wrapper/src/main.nr new file mode 100644 index 0000000000..2107ef3c8d --- /dev/null +++ b/circuits/bin/aggregation/production/dec_share_trbfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 1; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 98306; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/production/dec_shares_agg_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/production/dec_shares_agg_trbfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..2a78a4a42a --- /dev/null +++ b/circuits/bin/aggregation/production/dec_shares_agg_trbfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "dec_shares_agg_trbfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/production/dec_shares_agg_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/production/dec_shares_agg_trbfv_wrapper/src/main.nr new file mode 100644 index 0000000000..eeda74714c --- /dev/null +++ b/circuits/bin/aggregation/production/dec_shares_agg_trbfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 1; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 1043; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/production/enc_bfv_wrapper/Nargo.toml b/circuits/bin/aggregation/production/enc_bfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..40ab5f97e6 --- /dev/null +++ b/circuits/bin/aggregation/production/enc_bfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "enc_bfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/production/enc_bfv_wrapper/src/main.nr b/circuits/bin/aggregation/production/enc_bfv_wrapper/src/main.nr new file mode 100644 index 0000000000..02773b001d --- /dev/null +++ b/circuits/bin/aggregation/production/enc_bfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 2; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 32770; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/production/pk_agg_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/production/pk_agg_trbfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..0b985dd2cc --- /dev/null +++ b/circuits/bin/aggregation/production/pk_agg_trbfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "pk_agg_trbfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/production/pk_agg_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/production/pk_agg_trbfv_wrapper/src/main.nr new file mode 100644 index 0000000000..f56ef89641 --- /dev/null +++ b/circuits/bin/aggregation/production/pk_agg_trbfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 1; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 6; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/production/pk_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/production/pk_trbfv_wrapper/Nargo.toml new file mode 100644 index 0000000000..8e20cf697f --- /dev/null +++ b/circuits/bin/aggregation/production/pk_trbfv_wrapper/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "pk_trbfv_wrapper" +type = "bin" +authors = ["Gnosis Guild / Enclave"] +version = "1.0.0-beta.15" + +[dependencies] +lib = { path = "../../../lib" } +bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/production/pk_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/production/pk_trbfv_wrapper/src/main.nr new file mode 100644 index 0000000000..58a2d2a85b --- /dev/null +++ b/circuits/bin/aggregation/production/pk_trbfv_wrapper/src/main.nr @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. + +use bb_proof_verification::{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}; +use lib::math::commitments::compute_aggregation_commitment; + +// Number of proofs. +pub global N_PROOFS: u32 = 1; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 32771; + +fn main( + verification_key: UltraHonkVerificationKey, + proofs: [UltraHonkProof; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], + key_hash: Field, +) -> pub Field { + for i in 0..N_PROOFS { + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); + } + + let mut aggregated_public_inputs = Vec::new(); + + for i in 0..N_PROOFS { + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); + } + } + + compute_aggregation_commitment(aggregated_public_inputs) +} diff --git a/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr index 1d40914eeb..b3a6225c3a 100644 --- a/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr +++ b/circuits/bin/aggregation/production/verify_shares_trbfv_wrapper/src/main.nr @@ -9,26 +9,26 @@ use lib::math::commitments::compute_aggregation_commitment; // Number of proofs. pub global N_PROOFS: u32 = 2; -/// Number of commitments per proof. -pub global N_COMMITMENTS: u32 = 20; +/// Number of public inputs/outputs per proof. +pub global N_PUBLIC_INPUTS: u32 = 21; fn main( verification_key: UltraHonkVerificationKey, proofs: [UltraHonkProof; N_PROOFS], - commitments: pub [[Field; N_COMMITMENTS]; N_PROOFS], + public_inputs: pub [[Field; N_PUBLIC_INPUTS]; N_PROOFS], key_hash: Field, ) -> pub Field { for i in 0..N_PROOFS { - verify_ultrahonk_proof(verification_key, proofs[i], commitments[i], key_hash); + verify_ultrahonk_proof(verification_key, proofs[i], public_inputs[i], key_hash); } - let mut aggregated_commitments = Vec::new(); + let mut aggregated_public_inputs = Vec::new(); for i in 0..N_PROOFS { - for j in 0..N_COMMITMENTS { - aggregated_commitments.push(commitments[i][j]); + for j in 0..N_PUBLIC_INPUTS { + aggregated_public_inputs.push(public_inputs[i][j]); } } - compute_aggregation_commitment(aggregated_commitments) + compute_aggregation_commitment(aggregated_public_inputs) } From b873721a4fc0c87fde37ce5a56183690d7927904 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 20 Jan 2026 16:15:26 +0100 Subject: [PATCH 26/30] update C2a and C2b templates with parity matrix as constant --- .../verify_shares_trbfv_e_sm/src/main.nr | 17 ++++++++++-- .../verify_shares_trbfv_sk/src/main.nr | 17 ++++++++++-- .../verify_shares_trbfv_e_sm/src/main.nr | 27 +++++++++++++++++-- .../verify_shares_trbfv_sk/src/main.nr | 27 +++++++++++++++++-- 4 files changed, 80 insertions(+), 8 deletions(-) diff --git a/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr b/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr index 98358897f5..7256d11a23 100644 --- a/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr +++ b/circuits/bin/insecure/verify_shares_trbfv_e_sm/src/main.nr @@ -14,19 +14,32 @@ use lib::math::polynomial::Polynomial; pub global N_PARTIES: u32 = 5; /// Threshold. pub global T: u32 = 2; +/// Parity check matrix for each modulus. +/// H[modulus_idx][row][col] where size is [L][N_PARTIES-T][N_PARTIES+1] +pub global H: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L] = [ + [ + [68719403008, 3, 68719403006, 1, 0, 0], + [68719403006, 8, 68719403003, 0, 1, 0], + [68719403003, 15, 68719402999, 0, 0, 1], + ], + [ + [68719230976, 3, 68719230974, 1, 0, 0], + [68719230974, 8, 68719230971, 0, 1, 0], + [68719230971, 15, 68719230967, 0, 0, 1], + ], +]; fn main( expected_secret_commitment: pub Field, secret_e_sm: [Polynomial; L], y: [[[Field; N_PARTIES + 1]; L]; N], - h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], ) -> pub [[Field; L]; N_PARTIES] { let verify_shares: VerifySharesEsm = VerifySharesEsm::new( VERIFY_SHARES_CONFIGS_E_SM, expected_secret_commitment, secret_e_sm, y, - h, + H, ); verify_shares.verify() diff --git a/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr b/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr index a9705c685a..6aa657d5a4 100644 --- a/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr +++ b/circuits/bin/insecure/verify_shares_trbfv_sk/src/main.nr @@ -14,19 +14,32 @@ use lib::math::polynomial::Polynomial; pub global N_PARTIES: u32 = 5; /// Threshold. pub global T: u32 = 2; +/// Parity check matrix for each modulus. +/// H[modulus_idx][row][col] where size is [L][N_PARTIES-T][N_PARTIES+1] +pub global H: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L] = [ + [ + [68719403008, 3, 68719403006, 1, 0, 0], + [68719403006, 8, 68719403003, 0, 1, 0], + [68719403003, 15, 68719402999, 0, 0, 1], + ], + [ + [68719230976, 3, 68719230974, 1, 0, 0], + [68719230974, 8, 68719230971, 0, 1, 0], + [68719230971, 15, 68719230967, 0, 0, 1], + ], +]; fn main( expected_secret_commitment: pub Field, secret_sk: Polynomial, y: [[[Field; N_PARTIES + 1]; L]; N], - h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], ) -> pub [[Field; L]; N_PARTIES] { let verify_shares: VerifySharesSk = VerifySharesSk::new( VERIFY_SHARES_CONFIGS_SK, expected_secret_commitment, secret_sk, y, - h, + H, ); verify_shares.verify() diff --git a/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr b/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr index 0b5cf2c269..df839f625c 100644 --- a/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr +++ b/circuits/bin/production/verify_shares_trbfv_e_sm/src/main.nr @@ -14,19 +14,42 @@ use lib::math::polynomial::Polynomial; pub global N_PARTIES: u32 = 5; /// Threshold. pub global T: u32 = 2; +/// Parity check matrix for each modulus. +/// H[modulus_idx][row][col] where size is [L][N_PARTIES-T][N_PARTIES+1] +pub global H: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L] = [ + [ + [2251799822204928, 3, 2251799822204926, 1, 0, 0], + [2251799822204926, 8, 2251799822204923, 0, 1, 0], + [2251799822204923, 15, 2251799822204919, 0, 0, 1], + ], + [ + [4503599627763712, 3, 4503599627763710, 1, 0, 0], + [4503599627763710, 8, 4503599627763707, 0, 1, 0], + [4503599627763707, 15, 4503599627763703, 0, 0, 1], + ], + [ + [4503599631433728, 3, 4503599631433726, 1, 0, 0], + [4503599631433726, 8, 4503599631433723, 0, 1, 0], + [4503599631433723, 15, 4503599631433719, 0, 0, 1], + ], + [ + [4503599634579456, 3, 4503599634579454, 1, 0, 0], + [4503599634579454, 8, 4503599634579451, 0, 1, 0], + [4503599634579451, 15, 4503599634579447, 0, 0, 1], + ], +]; fn main( expected_secret_commitment: pub Field, secret_e_sm: [Polynomial; L], y: [[[Field; N_PARTIES + 1]; L]; N], - h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], ) -> pub [[Field; L]; N_PARTIES] { let verify_shares: VerifySharesEsm = VerifySharesEsm::new( VERIFY_SHARES_CONFIGS_E_SM, expected_secret_commitment, secret_e_sm, y, - h, + H, ); verify_shares.verify() diff --git a/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr b/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr index 2025f3272c..e30a11ad7a 100644 --- a/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr +++ b/circuits/bin/production/verify_shares_trbfv_sk/src/main.nr @@ -14,19 +14,42 @@ use lib::math::polynomial::Polynomial; pub global N_PARTIES: u32 = 5; /// Threshold. pub global T: u32 = 2; +/// Parity check matrix for each modulus. +/// H[modulus_idx][row][col] where size is [L][N_PARTIES-T][N_PARTIES+1] +pub global H: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L] = [ + [ + [2251799822204928, 3, 2251799822204926, 1, 0, 0], + [2251799822204926, 8, 2251799822204923, 0, 1, 0], + [2251799822204923, 15, 2251799822204919, 0, 0, 1], + ], + [ + [4503599627763712, 3, 4503599627763710, 1, 0, 0], + [4503599627763710, 8, 4503599627763707, 0, 1, 0], + [4503599627763707, 15, 4503599627763703, 0, 0, 1], + ], + [ + [4503599631433728, 3, 4503599631433726, 1, 0, 0], + [4503599631433726, 8, 4503599631433723, 0, 1, 0], + [4503599631433723, 15, 4503599631433719, 0, 0, 1], + ], + [ + [4503599634579456, 3, 4503599634579454, 1, 0, 0], + [4503599634579454, 8, 4503599634579451, 0, 1, 0], + [4503599634579451, 15, 4503599634579447, 0, 0, 1], + ], +]; fn main( expected_secret_commitment: pub Field, secret_sk: Polynomial, y: [[[Field; N_PARTIES + 1]; L]; N], - h: [[[Field; N_PARTIES + 1]; N_PARTIES - T]; L], ) -> pub [[Field; L]; N_PARTIES] { let verify_shares: VerifySharesSk = VerifySharesSk::new( VERIFY_SHARES_CONFIGS_SK, expected_secret_commitment, secret_sk, y, - h, + H, ); verify_shares.verify() From 3bc99a54022abd43a2f6516c7ecf51f035758300 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 20 Jan 2026 16:25:55 +0100 Subject: [PATCH 27/30] update nargo --- circuits/bin/aggregation/Nargo.toml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/circuits/bin/aggregation/Nargo.toml b/circuits/bin/aggregation/Nargo.toml index d07c2b2748..32ae1c4fbe 100644 --- a/circuits/bin/aggregation/Nargo.toml +++ b/circuits/bin/aggregation/Nargo.toml @@ -1,7 +1,18 @@ [workspace] members = [ "fold", - "pk_trbfv_wrapper", + "insecure/pk_trbfv_wrapper", "insecure/verify_shares_trbfv_wrapper", - "production/verify_shares_trbfv_wrapper" + "insecure/enc_bfv_wrapper", + "insecure/dec_bfv_wrapper", + "insecure/pk_agg_trbfv_wrapper", + "insecure/dec_share_trbfv_wrapper", + "insecure/dec_shares_agg_trbfv_wrapper", + "insecure/pk_trbfv_wrapper", + "production/verify_shares_trbfv_wrapper", + "production/enc_bfv_wrapper", + "production/dec_bfv_wrapper", + "production/pk_agg_trbfv_wrapper", + "production/dec_share_trbfv_wrapper", + "production/dec_shares_agg_trbfv_wrapper" ] \ No newline at end of file From bff1dd69bd5cc4ede5d4be97d3004de603783291 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 20 Jan 2026 16:26:23 +0100 Subject: [PATCH 28/30] remove unused constants from c6 --- circuits/bin/insecure/dec_share_trbfv/src/main.nr | 5 ----- circuits/bin/production/dec_share_trbfv/src/main.nr | 5 ----- 2 files changed, 10 deletions(-) diff --git a/circuits/bin/insecure/dec_share_trbfv/src/main.nr b/circuits/bin/insecure/dec_share_trbfv/src/main.nr index 637db1eb7a..4863282066 100644 --- a/circuits/bin/insecure/dec_share_trbfv/src/main.nr +++ b/circuits/bin/insecure/dec_share_trbfv/src/main.nr @@ -11,11 +11,6 @@ use lib::configs::insecure::trbfv::{ use lib::core::trbfv_dec_share::DecryptionShare; use lib::math::polynomial::Polynomial; -/// Number of parties. -pub global N_PARTIES: u32 = 5; -/// Threshold. -pub global T: u32 = 2; - fn main( expected_s_commitment: pub Field, expected_e_commitment: pub Field, diff --git a/circuits/bin/production/dec_share_trbfv/src/main.nr b/circuits/bin/production/dec_share_trbfv/src/main.nr index 98e7e9d8d5..f5a47a5429 100644 --- a/circuits/bin/production/dec_share_trbfv/src/main.nr +++ b/circuits/bin/production/dec_share_trbfv/src/main.nr @@ -11,11 +11,6 @@ use lib::configs::production::trbfv::{ use lib::core::trbfv_dec_share::DecryptionShare; use lib::math::polynomial::Polynomial; -/// Number of parties. -pub global N_PARTIES: u32 = 5; -/// Threshold. -pub global T: u32 = 2; - fn main( expected_s_commitment: pub Field, expected_e_commitment: pub Field, From 10ec0044e802bfc9e7e142e7eded0806c4fe4a88 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 20 Jan 2026 16:28:35 +0100 Subject: [PATCH 29/30] update c6 docs --- circuits/lib/src/core/trbfv_dec_share.nr | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/circuits/lib/src/core/trbfv_dec_share.nr b/circuits/lib/src/core/trbfv_dec_share.nr index b419cce536..fa6800d9b5 100644 --- a/circuits/lib/src/core/trbfv_dec_share.nr +++ b/circuits/lib/src/core/trbfv_dec_share.nr @@ -115,17 +115,21 @@ impl Vec { let mut inputs = Vec::new(); @@ -213,7 +217,7 @@ impl Date: Tue, 20 Jan 2026 16:41:55 +0100 Subject: [PATCH 30/30] update script and nargo subfolders for workspace --- circuits/bin/aggregation/Nargo.toml | 18 ------------------ circuits/bin/aggregation/insecure/Nargo.toml | 10 ++++++++++ .../insecure/pk_trbfv_wrapper/Nargo.toml | 2 +- circuits/bin/aggregation/production/Nargo.toml | 10 ++++++++++ .../production/pk_trbfv_wrapper/Nargo.toml | 2 +- scripts/lint-circuits.sh | 2 +- 6 files changed, 23 insertions(+), 21 deletions(-) delete mode 100644 circuits/bin/aggregation/Nargo.toml create mode 100644 circuits/bin/aggregation/insecure/Nargo.toml create mode 100644 circuits/bin/aggregation/production/Nargo.toml diff --git a/circuits/bin/aggregation/Nargo.toml b/circuits/bin/aggregation/Nargo.toml deleted file mode 100644 index 32ae1c4fbe..0000000000 --- a/circuits/bin/aggregation/Nargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[workspace] -members = [ - "fold", - "insecure/pk_trbfv_wrapper", - "insecure/verify_shares_trbfv_wrapper", - "insecure/enc_bfv_wrapper", - "insecure/dec_bfv_wrapper", - "insecure/pk_agg_trbfv_wrapper", - "insecure/dec_share_trbfv_wrapper", - "insecure/dec_shares_agg_trbfv_wrapper", - "insecure/pk_trbfv_wrapper", - "production/verify_shares_trbfv_wrapper", - "production/enc_bfv_wrapper", - "production/dec_bfv_wrapper", - "production/pk_agg_trbfv_wrapper", - "production/dec_share_trbfv_wrapper", - "production/dec_shares_agg_trbfv_wrapper" -] \ No newline at end of file diff --git a/circuits/bin/aggregation/insecure/Nargo.toml b/circuits/bin/aggregation/insecure/Nargo.toml new file mode 100644 index 0000000000..635384631e --- /dev/null +++ b/circuits/bin/aggregation/insecure/Nargo.toml @@ -0,0 +1,10 @@ +[workspace] +members = [ + "pk_trbfv_wrapper", + "verify_shares_trbfv_wrapper", + "enc_bfv_wrapper", + "dec_bfv_wrapper", + "pk_agg_trbfv_wrapper", + "dec_share_trbfv_wrapper", + "dec_shares_agg_trbfv_wrapper", +] \ No newline at end of file diff --git a/circuits/bin/aggregation/insecure/pk_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/insecure/pk_trbfv_wrapper/Nargo.toml index 8e20cf697f..42756d468c 100644 --- a/circuits/bin/aggregation/insecure/pk_trbfv_wrapper/Nargo.toml +++ b/circuits/bin/aggregation/insecure/pk_trbfv_wrapper/Nargo.toml @@ -5,5 +5,5 @@ authors = ["Gnosis Guild / Enclave"] version = "1.0.0-beta.15" [dependencies] -lib = { path = "../../../lib" } +lib = { path = "../../../../lib" } bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/circuits/bin/aggregation/production/Nargo.toml b/circuits/bin/aggregation/production/Nargo.toml new file mode 100644 index 0000000000..cd25cb537a --- /dev/null +++ b/circuits/bin/aggregation/production/Nargo.toml @@ -0,0 +1,10 @@ +[workspace] +members = [ + "pk_trbfv_wrapper", + "verify_shares_trbfv_wrapper", + "enc_bfv_wrapper", + "dec_bfv_wrapper", + "pk_agg_trbfv_wrapper", + "dec_share_trbfv_wrapper", + "dec_shares_agg_trbfv_wrapper" +] \ No newline at end of file diff --git a/circuits/bin/aggregation/production/pk_trbfv_wrapper/Nargo.toml b/circuits/bin/aggregation/production/pk_trbfv_wrapper/Nargo.toml index 8e20cf697f..42756d468c 100644 --- a/circuits/bin/aggregation/production/pk_trbfv_wrapper/Nargo.toml +++ b/circuits/bin/aggregation/production/pk_trbfv_wrapper/Nargo.toml @@ -5,5 +5,5 @@ authors = ["Gnosis Guild / Enclave"] version = "1.0.0-beta.15" [dependencies] -lib = { path = "../../../lib" } +lib = { path = "../../../../lib" } bb_proof_verification = { git = "https://github.com/AztecProtocol/aztec-packages/", tag = "v3.0.0-nightly.20251104", directory = "barretenberg/noir/bb_proof_verification" } \ No newline at end of file diff --git a/scripts/lint-circuits.sh b/scripts/lint-circuits.sh index cd5cf2e558..80c72e7840 100755 --- a/scripts/lint-circuits.sh +++ b/scripts/lint-circuits.sh @@ -11,7 +11,7 @@ fi cd circuits # Directories to check -DIRS=("lib" "bin/aggregation" "bin/insecure" "bin/production") +DIRS=("lib" "bin/aggregation/fold" "bin/aggregation/insecure" "bin/aggregation/production" "bin/insecure" "bin/production") for dir in "${DIRS[@]}"; do if [ ! -d "$dir" ]; then