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
19 changes: 8 additions & 11 deletions circuits/lib/src/configs/insecure/threshold.nr
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,19 @@ pk_generation (CIRCUIT 1)
-------------------------------------
************************************/

// pk_generation - bit parameters
pub global PK_GENERATION_BIT_EEK: u32 = 6;
pub global PK_GENERATION_BIT_SK: u32 = 2;
pub global PK_GENERATION_BIT_E_SM: u32 = 18;
pub global PK_GENERATION_BIT_R1: u32 = 14;
pub global PK_GENERATION_BIT_R2: u32 = 36;
pub global PK_GENERATION_BIT_PK: u32 = 36;

// pk_generation - bounds
pub global PK_GENERATION_BIT_EEK: u32 = 5;
pub global PK_GENERATION_BIT_SK: u32 = 1;
pub global PK_GENERATION_BIT_E_SM: u32 = 17;
pub global PK_GENERATION_BIT_R1: u32 = 13;
pub global PK_GENERATION_BIT_R2: u32 = 35;
pub global PK_GENERATION_BIT_PK: u32 = 35;

pub global PK_GENERATION_EEK_BOUND: Field = 20;
pub global PK_GENERATION_SK_BOUND: Field = 1;
pub global PK_GENERATION_E_SM_BOUND: Field = 122892;
pub global PK_GENERATION_E_SM_BOUND: Field = 123072;
pub global PK_GENERATION_R1_BOUNDS: [Field; L] = [5120, 5120];
pub global PK_GENERATION_R2_BOUNDS: [Field; L] = [34359701504, 34359615488];

// pk_generation - configs
pub global PK_GENERATION_CONFIGS: PkGenerationConfigs<N, L> = PkGenerationConfigs::new(
QIS,
PK_GENERATION_EEK_BOUND,
Expand Down
19 changes: 8 additions & 11 deletions circuits/lib/src/configs/secure/threshold.nr
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,21 @@ pk_generation (CIRCUIT 1)
-------------------------------------
************************************/

// pk_generation - bit parameters
pub global PK_GENERATION_BIT_EEK: u32 = 6;
pub global PK_GENERATION_BIT_SK: u32 = 2;
pub global PK_GENERATION_BIT_E_SM: u32 = 187;
pub global PK_GENERATION_BIT_R1: u32 = 18;
pub global PK_GENERATION_BIT_R2: u32 = 53;
pub global PK_GENERATION_BIT_PK: u32 = 53;

// pk_generation - bounds
pub global PK_GENERATION_BIT_EEK: u32 = 5;
pub global PK_GENERATION_BIT_SK: u32 = 1;
pub global PK_GENERATION_BIT_E_SM: u32 = 192;
pub global PK_GENERATION_BIT_R1: u32 = 17;
pub global PK_GENERATION_BIT_R2: u32 = 52;
pub global PK_GENERATION_BIT_PK: u32 = 52;

pub global PK_GENERATION_EEK_BOUND: Field = 20;
pub global PK_GENERATION_SK_BOUND: Field = 1;
pub global PK_GENERATION_E_SM_BOUND: Field =
66359003478811654788063765182202739927396573769378037760;
4789048565205902682369834578696752269343944643454802329600;
pub global PK_GENERATION_R1_BOUNDS: [Field; L] = [81920, 81920, 81920, 81920];
pub global PK_GENERATION_R2_BOUNDS: [Field; L] =
[1125899911102464, 2251799813881856, 2251799815716864, 2251799817289728];

// pk_generation - configs
pub global PK_GENERATION_CONFIGS: PkGenerationConfigs<N, L> = PkGenerationConfigs::new(
QIS,
PK_GENERATION_EEK_BOUND,
Expand Down
2 changes: 1 addition & 1 deletion crates/bfv-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

use anyhow::{anyhow, Result};
use e3_fhe_params::{build_bfv_params_arc, DEFAULT_BFV_PRESET};
use e3_zk_helpers::circuits::threshold::user_data_encryption::circuit::UserDataEncryptionCircuitInput;
use e3_zk_helpers::circuits::threshold::user_data_encryption::Witness as UserDataEncryptionWitness;
use e3_zk_helpers::circuits::Computation;
use e3_zk_helpers::threshold::UserDataEncryptionCircuitInput;
use fhe::bfv::{Ciphertext, Encoding, Plaintext, PublicKey, SecretKey};
use fhe::Error as FheError;
use fhe_traits::{DeserializeParametrized, FheEncoder, FheEncrypter, Serialize};
Expand Down
9 changes: 9 additions & 0 deletions crates/polynomial/src/crt_polynomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@ impl CrtPolynomial {
}
}

/// Adds a limb to the CRT polynomial.
///
/// # Arguments
///
/// * `limb` - The limb to add.
pub fn add_limb(&mut self, limb: Polynomial) {
self.limbs.push(limb);
}

/// Returns a reference to the limb polynomial at the given index.
///
/// # Arguments
Expand Down
7 changes: 6 additions & 1 deletion crates/polynomial/src/polynomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ impl Polynomial {
Polynomial::new(product)
}

/// Remove a coefficient from the polynomial.
pub fn remove(&mut self, index: usize) {
self.coefficients.remove(index);
}
Comment thread
cedoor marked this conversation as resolved.

/// Divides one polynomial by another, returning the quotient and remainder.
///
/// # Arguments
Expand Down Expand Up @@ -396,7 +401,7 @@ impl Polynomial {
///
/// # Returns
///
/// Mutates the polynomial in place.
/// A new polynomial containing the remainder.
///
/// # Errors
///
Expand Down
12 changes: 11 additions & 1 deletion crates/zk-helpers/src/bin/zk_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ use e3_zk_helpers::dkg::share_encryption::{
ShareEncryptionCircuit, ShareEncryptionCircuitInput, ShareEncryptionSample,
};
use e3_zk_helpers::registry::{Circuit, CircuitRegistry};
use e3_zk_helpers::threshold::{
use e3_zk_helpers::threshold::pk_generation::{PkGenerationCircuit, PkGenerationCircuitInput};
use e3_zk_helpers::threshold::user_data_encryption::{
UserDataEncryptionCircuit, UserDataEncryptionCircuitInput, UserDataEncryptionSample,
};
use e3_zk_helpers::{PkSample, ShareComputationSample};
Expand Down Expand Up @@ -157,6 +158,7 @@ fn main() -> Result<()> {
registry.register(Arc::new(ShareComputationCircuit));
registry.register(Arc::new(UserDataEncryptionCircuit));
registry.register(Arc::new(ShareEncryptionCircuit));
registry.register(Arc::new(PkGenerationCircuit));

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

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

pub mod pk_generation;
pub mod user_data_encryption;
pub use user_data_encryption::*;
31 changes: 31 additions & 0 deletions crates/zk-helpers/src/circuits/threshold/pk_generation/circuit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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;

#[derive(Debug)]
pub struct PkGenerationCircuit;

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

#[derive(Debug, Clone)]
pub struct PkGenerationCircuitInput {
pub committee: CiphernodesCommittee,
pub pk_share: CrtPolynomial,
pub a: CrtPolynomial,
pub eek: CrtPolynomial,
pub e_sm: CrtPolynomial,
pub sk: CrtPolynomial,
}
195 changes: 195 additions & 0 deletions crates/zk-helpers/src/circuits/threshold/pk_generation/codegen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
// 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_generation::circuit::PkGenerationCircuit;
use crate::threshold::pk_generation::computation::{Configs, Witness};
use crate::threshold::pk_generation::PkGenerationCircuitInput;
use crate::utils::join_display;
use crate::CircuitCodegen;
use crate::CircuitsErrors;
use crate::{Artifacts, CodegenToml};
use crate::{Circuit, CodegenConfigs};

/// Implementation of [`CircuitCodegen`] for [`PkGenerationCircuit`].
impl CircuitCodegen for PkGenerationCircuit {
type Preset = BfvPreset;
type Input = PkGenerationCircuitInput;
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, &input.committee)?;

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 = <PkGenerationCircuit as Circuit>::PREFIX;

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

let r1_bounds_str = join_display(&configs.bounds.r1_bounds, ", ");
let r2_bounds_str = join_display(&configs.bounds.r2_bounds, ", ");

format!(
r#"use crate::core::threshold::pk_generation::Configs as PkGenerationConfigs;

// Global configs for Threshold Public Key Generation circuit
pub global N: u32 = {};
pub global L: u32 = {};
pub global QIS: [Field; L] = [{}];

/************************************
-------------------------------------
pk_generation (CIRCUIT 1 - PUBLIC KEY THRESHOLD BFV)
-------------------------------------
************************************/

pub global {}_BIT_EEK: u32 = {};
pub global {}_BIT_SK: u32 = {};
pub global {}_BIT_E_SM: u32 = {};
pub global {}_BIT_R1: u32 = {};
pub global {}_BIT_R2: u32 = {};
pub global {}_BIT_PK: u32 = {};

pub global {}_EEK_BOUND: Field = {};
pub global {}_SK_BOUND: Field = {};
pub global {}_E_SM_BOUND: Field = {};
pub global {}_R1_BOUNDS: [Field; L] = [{}];
pub global {}_R2_BOUNDS: [Field; L] = [{}];

pub global {}_CONFIGS: PkGenerationConfigs<N, L> = PkGenerationConfigs::new(
QIS,
{}_EEK_BOUND,
{}_SK_BOUND,
{}_E_SM_BOUND,
{}_R1_BOUNDS,
{}_R2_BOUNDS,
);
"#,
configs.n,
configs.l,
qis_str,
prefix,
configs.bits.eek_bit,
prefix,
configs.bits.sk_bit,
prefix,
configs.bits.e_sm_bit,
prefix,
configs.bits.r1_bit,
prefix,
configs.bits.r2_bit,
prefix,
configs.bits.pk_bit,
prefix,
configs.bounds.eek_bound,
prefix,
configs.bounds.sk_bound,
prefix,
configs.bounds.e_sm_bound,
prefix,
r1_bounds_str,
prefix,
r2_bounds_str,
prefix,
prefix,
prefix,
prefix,
prefix,
prefix,
)
}

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

use crate::codegen::write_artifacts;
use crate::threshold::pk_generation::computation::{Bits, Bounds};
use crate::threshold::pk_generation::PkGenerationCircuitInput;
use crate::CiphernodesCommitteeSize;

use e3_fhe_params::DEFAULT_BFV_PRESET;
use tempfile::TempDir;

#[test]
fn test_toml_generation_and_structure() {
let committee = CiphernodesCommitteeSize::Small.values();
let sample =
PkGenerationCircuitInput::generate_sample(DEFAULT_BFV_PRESET, committee).unwrap();
let artifacts = PkGenerationCircuit
.codegen(DEFAULT_BFV_PRESET, &sample)
.unwrap();

let parsed: toml::Value = artifacts.toml.parse().unwrap();
let pk0is = parsed
.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());

let temp_dir = TempDir::new().unwrap();
write_artifacts(
Some(&artifacts.toml),
&artifacts.configs,
Some(temp_dir.path()),
)
.unwrap();

let output_path = temp_dir.path().join("Prover.toml");
assert!(output_path.exists());

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());

let configs_content = std::fs::read_to_string(&configs_path).unwrap();
let bounds = Bounds::compute(DEFAULT_BFV_PRESET, &sample.committee).unwrap();
let bits = Bits::compute(DEFAULT_BFV_PRESET, &bounds).unwrap();

assert!(configs_content
.contains(format!("N: u32 = {}", DEFAULT_BFV_PRESET.metadata().degree).as_str()));
assert!(configs_content
.contains(format!("L: u32 = {}", DEFAULT_BFV_PRESET.metadata().num_moduli).as_str()));
assert!(configs_content.contains(
format!(
"{}_BIT_PK: u32 = {}",
<PkGenerationCircuit as Circuit>::PREFIX,
bits.pk_bit
)
.as_str()
));
}
}
Loading
Loading