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
2 changes: 1 addition & 1 deletion circuits/lib/src/configs/committee/small.nr
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ pub global N_PARTIES: u32 = 5;
/// Threshold.
pub global T: u32 = 2;
/// Number of honest parties.
pub global H: u32 = 5;
pub global H: u32 = 3;
4 changes: 1 addition & 3 deletions circuits/lib/src/configs/insecure/threshold.nr
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,8 @@ pk_aggregation (CIRCUIT 5)
-------------------------------------
************************************/

// pk_aggregation - bit parameters
pub global PK_AGGREGATION_BIT_PK: u32 = 36;
pub global PK_AGGREGATION_BIT_PK: u32 = 35;

// pk_aggregation - configs
pub global PK_AGGREGATION_CONFIGS: PkAggregationConfigs<L> = PkAggregationConfigs::new(QIS);

/************************************
Expand Down
4 changes: 1 addition & 3 deletions circuits/lib/src/configs/secure/threshold.nr
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,8 @@ pk_aggregation (CIRCUIT 5)
-------------------------------------
************************************/

// pk_aggregation - bit parameters
pub global PK_AGGREGATION_BIT_PK: u32 = 53;
pub global PK_AGGREGATION_BIT_PK: u32 = 52;

// pk_aggregation - configs
pub global PK_AGGREGATION_CONFIGS: PkAggregationConfigs<L> = PkAggregationConfigs::new(QIS);

/************************************
Expand Down
11 changes: 11 additions & 0 deletions crates/polynomial/src/crt_polynomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,17 @@ impl CrtPolynomial {
}
}

/// Multiplies each limb's coefficients by a scalar.
///
/// # Arguments
///
/// * `scalar` - The scalar to multiply each coefficient by.
pub fn scalar_mul(&mut self, scalar: &BigInt) {
for limb in &mut self.limbs {
*limb = limb.scalar_mul(scalar);
}
}

/// Adds a limb to the CRT polynomial.
///
/// # Arguments
Expand Down
11 changes: 11 additions & 0 deletions crates/zk-helpers/src/bin/zk_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ use e3_zk_helpers::dkg::share_encryption::{
ShareEncryptionCircuit, ShareEncryptionCircuitInput, ShareEncryptionSample,
};
use e3_zk_helpers::registry::{Circuit, CircuitRegistry};
use e3_zk_helpers::threshold::pk_aggregation::PkAggregationCircuit;
use e3_zk_helpers::threshold::pk_aggregation::PkAggregationCircuitInput;
use e3_zk_helpers::threshold::pk_generation::{PkGenerationCircuit, PkGenerationCircuitInput};
use e3_zk_helpers::threshold::user_data_encryption::{
UserDataEncryptionCircuit, UserDataEncryptionCircuitInput, UserDataEncryptionSample,
Expand Down Expand Up @@ -159,6 +161,7 @@ fn main() -> Result<()> {
registry.register(Arc::new(UserDataEncryptionCircuit));
registry.register(Arc::new(ShareEncryptionCircuit));
registry.register(Arc::new(PkGenerationCircuit));
registry.register(Arc::new(PkAggregationCircuit));

// Handle list circuits flag.
if args.list_circuits {
Expand Down Expand Up @@ -326,6 +329,14 @@ fn main() -> Result<()> {
let circuit = PkGenerationCircuit;
circuit.codegen(preset, &sample)?
}
name if name == <PkAggregationCircuit as Circuit>::NAME => {
let sample = PkAggregationCircuitInput::generate_sample(
preset,
CiphernodesCommitteeSize::Small.values(),
)?;
let circuit = PkAggregationCircuit;
circuit.codegen(preset, &sample)?
}
name => return Err(anyhow!("circuit {} not yet implemented", name)),
};

Expand Down
1 change: 1 addition & 0 deletions crates/zk-helpers/src/circuits/threshold/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
// without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.

pub mod pk_aggregation;
pub mod pk_generation;
pub mod user_data_encryption;
30 changes: 30 additions & 0 deletions crates/zk-helpers/src/circuits/threshold/pk_aggregation/circuit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 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::computation::DkgInputType;
use crate::registry::Circuit;
use crate::CiphernodesCommittee;
use e3_fhe_params::ParameterType;
use e3_polynomial::CrtPolynomial;
use fhe::bfv::PublicKey;

#[derive(Debug)]
pub struct PkAggregationCircuit;

impl Circuit for PkAggregationCircuit {
const NAME: &'static str = "pk-aggregation";
const PREFIX: &'static str = "PK_AGGREGATION";
const SUPPORTED_PARAMETER: ParameterType = ParameterType::THRESHOLD;
const DKG_INPUT_TYPE: Option<DkgInputType> = None;
}

#[derive(Debug, Clone)]
pub struct PkAggregationCircuitInput {
pub committee: CiphernodesCommittee,
pub public_key: PublicKey,
pub pk0_shares: Vec<CrtPolynomial>,
pub a: CrtPolynomial,
}
139 changes: 139 additions & 0 deletions crates/zk-helpers/src/circuits/threshold/pk_aggregation/codegen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// 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.

//! Code generation for the public-key BFV circuit: Prover.toml and configs.nr.

use e3_fhe_params::BfvPreset;

use crate::circuits::computation::Computation;
use crate::threshold::pk_aggregation::circuit::PkAggregationCircuit;
use crate::threshold::pk_aggregation::computation::{Configs, Witness};
use crate::threshold::pk_aggregation::PkAggregationCircuitInput;
use crate::utils::join_display;
use crate::CircuitCodegen;
use crate::CircuitsErrors;
use crate::{Artifacts, CodegenToml};
use crate::{Circuit, CodegenConfigs};

/// Implementation of [`CircuitCodegen`] for [`PkAggregationCircuit`].
impl CircuitCodegen for PkAggregationCircuit {
type Preset = BfvPreset;
type Input = PkAggregationCircuitInput;
type Error = CircuitsErrors;

fn codegen(&self, preset: Self::Preset, input: &Self::Input) -> Result<Artifacts, Self::Error> {
let witness = Witness::compute(preset, input)?;
let configs = Configs::compute(preset, &())?;

let toml = generate_toml(witness)?;
let configs = generate_configs(preset, &configs);

Ok(Artifacts { toml, configs })
}
}

pub fn generate_toml(witness: Witness) -> Result<CodegenToml, CircuitsErrors> {
let json = witness
.to_json()
.map_err(|e| CircuitsErrors::SerdeJson(e))?;

Ok(toml::to_string(&json)?)
}

pub fn generate_configs(_preset: BfvPreset, configs: &Configs) -> CodegenConfigs {
let prefix = <PkAggregationCircuit as Circuit>::PREFIX;

let qis_str = join_display(&configs.moduli, ", ");

format!(
r#"use crate::core::threshold::pk_aggregation::Configs as PkAggregationConfigs;

// Global configs
pub global N: u32 = {};
pub global L: u32 = {};
pub global QIS: [Field; L] = [{}];

/************************************
-------------------------------------
pk_aggregation (CIRCUIT 5)
-------------------------------------
************************************/

pub global {}_BIT_PK: u32 = {};

pub global {}_CONFIGS: PkAggregationConfigs<L> = PkAggregationConfigs::new(QIS,);
"#,
configs.n, // N
configs.l, // L
qis_str, // QIS array
prefix, // BIT_PK
configs.bits.pk_bit, // BIT_PK
prefix, // CONFIGS
)
}

#[cfg(test)]
mod tests {
use super::*;

use crate::CiphernodesCommitteeSize;

#[test]
fn test_toml_generation_and_structure() {
let preset = BfvPreset::InsecureThreshold512;
let committee = CiphernodesCommitteeSize::Small.values();
let prefix: &str = <PkAggregationCircuit as Circuit>::PREFIX;

let sample = PkAggregationCircuitInput::generate_sample(preset, committee).unwrap();
let witness = Witness::compute(preset, &sample).unwrap();
let configs = Configs::compute(preset, &()).unwrap();

let qis_str = join_display(&configs.moduli, ", ");

let parsed: serde_json::Value = witness.to_json().unwrap();
let pk0 = parsed
.get("pk0")
.and_then(|value| value.as_array())
.unwrap();
let pk1 = parsed
.get("pk1")
.and_then(|value| value.as_array())
.unwrap();
let pk0_agg = parsed
.get("pk0_agg")
.and_then(|value| value.as_array())
.unwrap();
let pk1_agg = parsed
.get("pk1_agg")
.and_then(|value| value.as_array())
.unwrap();
assert!(!pk0.is_empty());
assert!(!pk1.is_empty());
assert!(!pk0_agg.is_empty());
assert!(!pk1_agg.is_empty());

let codegen_toml = generate_toml(witness).unwrap();
let codegen_configs = generate_configs(preset, &configs);

assert!(codegen_toml.contains("pk0"));
assert!(codegen_toml.contains("pk1"));
assert!(codegen_toml.contains("[[pk0_agg]]"));
assert!(codegen_toml.contains("[[pk1_agg]]"));

assert!(codegen_configs.contains(format!("N: u32 = {}", configs.n).as_str()));
assert!(codegen_configs.contains(format!("L: u32 = {}", configs.l).as_str()));
assert!(codegen_configs
.contains(format!("{}_BIT_PK: u32 = {}", prefix, configs.bits.pk_bit).as_str()));
assert!(codegen_configs.contains(
format!(
"{}_CONFIGS: PkAggregationConfigs<L> = PkAggregationConfigs::new(QIS,);",
prefix
)
.as_str()
));
assert!(codegen_configs.contains(format!("QIS: [Field; L] = [{}];", qis_str).as_str()));
}
}
Loading
Loading