Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions circuits/bin/threshold/pk_generation/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,8 @@ fn main(
r1is: [Polynomial<(2 * N) - 1>; L],
r2is: [Polynomial<N - 1>; L],
pk0is: [Polynomial<N>; L],
pk1is: [Polynomial<N>; L],
) -> pub (Field, Field, Field) {
let pk_generation: PkGeneration<N, L, PK_GENERATION_BIT_EEK, PK_GENERATION_BIT_SK, PK_GENERATION_BIT_E_SM, PK_GENERATION_BIT_R1, PK_GENERATION_BIT_R2, PK_GENERATION_BIT_PK> = PkGeneration::new(
PK_GENERATION_CONFIGS,
CRP,
eek,
sk,
e_sm,
r1is,
r2is,
pk0is,
pk1is,
);
let pk_generation: PkGeneration<N, L, PK_GENERATION_BIT_EEK, PK_GENERATION_BIT_SK, PK_GENERATION_BIT_E_SM, PK_GENERATION_BIT_R1, PK_GENERATION_BIT_R2, PK_GENERATION_BIT_PK> =
PkGeneration::new(PK_GENERATION_CONFIGS, CRP, eek, sk, e_sm, r1is, r2is, pk0is);
pk_generation.execute()
}
16 changes: 4 additions & 12 deletions circuits/lib/src/core/threshold/pk_generation.nr
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl<let N: u32, let L: u32> Configs<N, L> {
/// 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
/// (pk1 is a_i from the hardcoded CRS `a`, not a separate witness)
///
/// Outputs:
/// - commit(threshold_sk)
Expand Down Expand Up @@ -77,11 +77,8 @@ pub struct PkGeneration<let N: u32, let L: u32, let BIT_EEK: u32, let BIT_SK: u3
/// r2[i] are quotients from cyclotomic reduction for modulus i (typically positive, degree N-1)
r2: [Polynomial<N - 1>; L],

/// Threshold public key components (committed witnesses)
/// pk0[i] is the first component of the public key for modulus i
/// Threshold public key first component per modulus (committed witness). Second component is a[i].
pk0: [Polynomial<N>; L],
/// pk1[i] is the second component of the public key for modulus i (should equal a[i])
pk1: [Polynomial<N>; L],
}

impl<let N: u32, let L: u32, let BIT_EEK: u32, let BIT_SK: u32, let BIT_E_SM: u32, let BIT_R1: u32, let BIT_R2: u32, let BIT_PK: u32> PkGeneration<N, L, BIT_EEK, BIT_SK, BIT_E_SM, BIT_R1, BIT_R2, BIT_PK> {
Expand All @@ -94,9 +91,8 @@ impl<let N: u32, let L: u32, let BIT_EEK: u32, let BIT_SK: u32, let BIT_E_SM: u3
r1: [Polynomial<2 * N - 1>; L],
r2: [Polynomial<N - 1>; L],
pk0: [Polynomial<N>; L],
pk1: [Polynomial<N>; L],
) -> Self {
PkGeneration { configs, a, eek, sk, e_sm, r1, r2, pk0, pk1 }
PkGeneration { configs, a, eek, sk, e_sm, r1, r2, pk0 }
}

/// Flattens all witness data into a single array for Fiat-Shamir challenge generation
Expand Down Expand Up @@ -128,7 +124,7 @@ impl<let N: u32, let L: u32, let BIT_EEK: u32, let BIT_SK: u32, let BIT_E_SM: u3
let sk_commitment = compute_share_computation_sk_commitment::<N, BIT_SK>(self.sk);
let e_sm_commitment =
compute_share_computation_e_sm_commitment::<N, L, BIT_E_SM>(self.e_sm);
let pk_commitment = compute_threshold_pk_commitment::<N, L, BIT_PK>(self.pk0, self.pk1);
let pk_commitment = compute_threshold_pk_commitment::<N, L, BIT_PK>(self.pk0, self.a);

let gamma = self.generate_challenge(sk_commitment, pk_commitment);
self.verify_evaluations(gamma);
Expand Down Expand Up @@ -182,10 +178,6 @@ impl<let N: u32, let L: u32, let BIT_EEK: u32, let BIT_SK: u32, let BIT_E_SM: u3
+ self.r1[i].eval(gamma) * self.configs.qis[i];

assert(self.pk0[i].eval(gamma) == expected_pk0, "Public key equation 1 failed");
assert(
self.pk1[i].eval(gamma) == self.a[i].eval(gamma),
"Public key equation 2 failed",
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,8 @@ mod tests {
.get("pk0is")
.and_then(|value| value.as_array())
.unwrap();
let pk1is = parsed
.get("pk1is")
.and_then(|value| value.as_array())
.unwrap();
assert!(!pk0is.is_empty());
assert!(!pk1is.is_empty());
assert!(parsed.get("pk1is").is_none());

let temp_dir = TempDir::new().unwrap();
write_artifacts(
Expand All @@ -188,10 +184,8 @@ mod tests {

let content = std::fs::read_to_string(&output_path).unwrap();
assert!(content.contains("pk0is"));
assert!(content.contains("pk1is"));

assert!(artifacts.toml.contains("[[pk0is]]"));
assert!(artifacts.toml.contains("[[pk1is]]"));

let configs_path = temp_dir.path().join("configs.nr");
assert!(configs_path.exists());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ pub struct Inputs {
pub r1is: CrtPolynomial,
pub r2is: CrtPolynomial,
pub pk0is: CrtPolynomial,
pub pk1is: CrtPolynomial,
}

impl Computation for Configs {
Expand Down Expand Up @@ -262,14 +261,7 @@ impl Computation for Inputs {
let cyclo = cyclotomic_polynomial(n);

// Perform the main computation logic
let mut results: Vec<(
usize,
Polynomial,
Polynomial,
Polynomial,
Polynomial,
Polynomial,
)> = izip!(
let mut results: Vec<(usize, Polynomial, Polynomial, Polynomial, Polynomial)> = izip!(
moduli.clone(),
data.pk0_share.limbs.clone(),
a.limbs.clone(),
Expand Down Expand Up @@ -306,16 +298,15 @@ impl Computation for Inputs {

let (r1, r2) = decompose_residue(&pk0_share, &pk0_share_hat, &qi, &cyclo, n);

(i, r2, r1, pk0_share.clone(), a.clone(), e_sm.clone())
(i, r2, r1, pk0_share.clone(), e_sm.clone())
})
.collect();

results.sort_by_key(|(i, _, _, _, _, _)| *i);
results.sort_by_key(|(i, _, _, _, _)| *i);

let mut r2 = CrtPolynomial::new(vec![]);
let mut r1 = CrtPolynomial::new(vec![]);
let mut pk0_share = CrtPolynomial::new(vec![]);
let mut a = CrtPolynomial::new(vec![]);
let mut e_sm = CrtPolynomial::new(vec![]);

let mut sk = data.sk.limbs[0].clone();
Expand All @@ -326,11 +317,10 @@ impl Computation for Inputs {
eek.reverse();
eek.center(&moduli[0]);

for (_i, r2i, r1i, pk0_sharei, ai, e_smi) in results {
for (_i, r2i, r1i, pk0_sharei, e_smi) in results {
r2.add_limb(r2i);
r1.add_limb(r1i);
pk0_share.add_limb(pk0_sharei);
a.add_limb(ai);
e_sm.add_limb(e_smi);
}

Expand All @@ -341,13 +331,11 @@ impl Computation for Inputs {
r1is: r1,
r2is: r2,
pk0is: pk0_share,
pk1is: a,
})
}

fn to_json(&self) -> serde_json::Result<serde_json::Value> {
let pk0is = crt_polynomial_to_toml_json(&self.pk0is);
let pk1is = crt_polynomial_to_toml_json(&self.pk1is);
let e = polynomial_to_toml_json(&self.eek);
let sk = polynomial_to_toml_json(&self.sk);
let e_sm = crt_polynomial_to_toml_json(&self.e_sm);
Expand All @@ -356,7 +344,6 @@ impl Computation for Inputs {

let json = serde_json::json!({
"pk0is": pk0is,
"pk1is": pk1is,
"eek": e,
"sk": sk,
"e_sm": e_sm,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

//! Public key generation circuit.
//!
//! This circuit proves public key generation with a threshold BFV public key (pk0, pk1) and produces
//! This circuit proves public key generation for pk0 (pk1 is the CRS polynomial `a`) and produces
//! Prover.toml and configs.nr for the Noir prover. See [`PkGenerationCircuit`] and
//! [`PkGenerationCircuitInput`].

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ mod tests {
let inputs = Inputs::compute(BfvPreset::InsecureThreshold512, &sample).unwrap();

assert_eq!(inputs.pk0is.limbs.len(), 2);
assert_eq!(inputs.pk1is.limbs.len(), 2);
assert_eq!(inputs.e_sm.limbs.len(), 2);
assert_eq!(inputs.r1is.limbs.len(), 2);
assert_eq!(inputs.r2is.limbs.len(), 2);
Expand Down
7 changes: 5 additions & 2 deletions crates/zk-prover/tests/local_e2e_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ use ark_ff::{PrimeField, Zero};
use common::{
extract_field, extract_field_from_end, find_bb, setup_compiled_circuit, setup_test_prover,
};
use e3_fhe_params::BfvPreset;
use e3_fhe_params::{build_pair_for_preset, BfvPreset};
use e3_zk_helpers::circuits::dkg::pk::circuit::PkCircuit;
use e3_zk_helpers::circuits::dkg::pk::circuit::PkCircuitData;
use e3_zk_helpers::circuits::threshold::pk_generation::utils::deterministic_crp_crt_polynomial;
use e3_zk_helpers::circuits::{commitments::compute_dkg_pk_commitment, CircuitComputation};
use e3_zk_helpers::computation::DkgInputType;
use e3_zk_helpers::dkg::share_computation::{
Expand Down Expand Up @@ -431,9 +432,11 @@ async fn test_pk_generation_commitment_consistency() {
&computation_output.inputs.sk,
computation_output.bits.sk_bit,
);
let (threshold_params, _) = build_pair_for_preset(preset).expect("preset pair");
let a = deterministic_crp_crt_polynomial(&threshold_params).expect("crp polynomial");
let pk_commitment_expected = compute_threshold_pk_commitment(
&computation_output.inputs.pk0is,
&computation_output.inputs.pk1is,
&a,
computation_output.bits.pk_bit,
);

Expand Down
Loading