From df69073589b5d4527652faa81ed088b3bbcf0fd4 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Mon, 2 Feb 2026 17:57:58 +0100 Subject: [PATCH 01/10] remove pvss-cli crate --- Cargo.toml | 3 +-- crates/Dockerfile | 1 - crates/pvss-cli/Cargo.toml | 13 ------------- crates/zk-helpers/Cargo.toml | 4 ++++ .../src/main.rs => zk-helpers/src/bin/zk_cli.rs} | 4 ++-- 5 files changed, 7 insertions(+), 18 deletions(-) delete mode 100644 crates/pvss-cli/Cargo.toml rename crates/{pvss-cli/src/main.rs => zk-helpers/src/bin/zk_cli.rs} (97%) diff --git a/Cargo.toml b/Cargo.toml index b2c13fd745..281cf067fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,8 +38,7 @@ members = [ "crates/parity-matrix", "crates/polynomial", "crates/zk-helpers", - "crates/pvss", - "crates/pvss-cli" + "crates/pvss" ] exclude = [ "examples/CRISP", diff --git a/crates/Dockerfile b/crates/Dockerfile index 10a6c49ad5..c103eec2c9 100644 --- a/crates/Dockerfile +++ b/crates/Dockerfile @@ -82,7 +82,6 @@ COPY crates/utils/Cargo.toml ./utils/Cargo.toml COPY crates/wasm/Cargo.toml ./wasm/Cargo.toml COPY crates/zk-helpers/Cargo.toml ./zk-helpers/Cargo.toml COPY crates/pvss/Cargo.toml ./pvss/Cargo.toml -COPY crates/pvss-cli/Cargo.toml ./pvss-cli/Cargo.toml RUN echo 'fn main() { println!("cargo:warning=dependency cache build"); }' > ./entrypoint/build.rs RUN echo 'fn main() { println!("cargo:warning=dependency cache build"); }' > ./cli/build.rs diff --git a/crates/pvss-cli/Cargo.toml b/crates/pvss-cli/Cargo.toml deleted file mode 100644 index 46b892b552..0000000000 --- a/crates/pvss-cli/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "e3-pvss-cli" -version.workspace = true -edition.workspace = true -license.workspace = true -description = "PVSS CLI for artifact generation" -repository = "https://github.com/gnosisguild/enclave/crates/pvss-cli" - -[dependencies] -e3-pvss = { workspace = true } -e3-fhe-params = { workspace = true } -clap = { workspace = true } -anyhow = { workspace = true } diff --git a/crates/zk-helpers/Cargo.toml b/crates/zk-helpers/Cargo.toml index da4bd1a440..e9147a37cc 100644 --- a/crates/zk-helpers/Cargo.toml +++ b/crates/zk-helpers/Cargo.toml @@ -15,3 +15,7 @@ fhe = { workspace = true } num-bigint = { workspace = true } num-traits = { workspace = true } thiserror = { workspace = true } + +[[bin]] +name = "zk_cli" +path = "src/bin/zk_cli.rs" \ No newline at end of file diff --git a/crates/pvss-cli/src/main.rs b/crates/zk-helpers/src/bin/zk_cli.rs similarity index 97% rename from crates/pvss-cli/src/main.rs rename to crates/zk-helpers/src/bin/zk_cli.rs index 6f1204e70d..a466344134 100644 --- a/crates/pvss-cli/src/main.rs +++ b/crates/zk-helpers/src/bin/zk_cli.rs @@ -16,9 +16,9 @@ use e3_pvss::traits::CircuitCodegen; use std::path::PathBuf; use std::sync::Arc; -/// Minimal PVSS CLI for generating circuit artifacts. +/// Minimal ZK CLI for generating circuit artifacts. #[derive(Debug, Parser)] -#[command(name = "pvss-cli")] +#[command(name = "zk-cli")] struct Cli { /// List all available circuits and exit. #[arg(long)] From 60193ab7ea746ea51d0ccada5a92cb7a39af43de Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 3 Feb 2026 11:03:51 +0100 Subject: [PATCH 02/10] remove stale codegen and reorg for porting --- Cargo.lock | 10 -- crates/pvss/src/circuits/pk_bfv/circuit.rs | 14 ++- crates/pvss/src/circuits/pk_bfv/codegen.rs | 91 +++----------- .../pvss/src/circuits/pk_bfv/computation.rs | 16 +-- crates/pvss/src/codegen.rs | 45 +++++++ crates/pvss/src/computation.rs | 44 +++++++ crates/pvss/src/errors.rs | 2 +- crates/pvss/src/lib.rs | 3 +- crates/pvss/src/registry.rs | 100 ++++++++++++++-- crates/pvss/src/sample.rs | 20 ++-- crates/pvss/src/traits.rs | 112 ------------------ crates/pvss/src/types.rs | 45 +------ crates/pvss/src/utils.rs | 70 ----------- 13 files changed, 228 insertions(+), 344 deletions(-) create mode 100644 crates/pvss/src/codegen.rs create mode 100644 crates/pvss/src/computation.rs delete mode 100644 crates/pvss/src/traits.rs diff --git a/Cargo.lock b/Cargo.lock index 186650d78f..71d87cf6bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3367,16 +3367,6 @@ dependencies = [ "toml", ] -[[package]] -name = "e3-pvss-cli" -version = "0.1.8" -dependencies = [ - "anyhow", - "clap", - "e3-fhe-params", - "e3-pvss", -] - [[package]] name = "e3-request" version = "0.1.8" diff --git a/crates/pvss/src/circuits/pk_bfv/circuit.rs b/crates/pvss/src/circuits/pk_bfv/circuit.rs index 8b6d7a4bac..89bb1af770 100644 --- a/crates/pvss/src/circuits/pk_bfv/circuit.rs +++ b/crates/pvss/src/circuits/pk_bfv/circuit.rs @@ -6,9 +6,13 @@ use crate::circuits::pk_bfv::codegen; use crate::circuits::pk_bfv::computation::{Bits, Bounds, Witness}; -use crate::errors::CodegenError; -use crate::traits::{Circuit, CircuitCodegen, CircuitComputation, Computation}; -use crate::types::{Artifacts, DkgInputType}; +use crate::codegen::Artifacts; +use crate::codegen::CircuitCodegen; +use crate::computation::CircuitComputation; +use crate::computation::Computation; +use crate::errors::CircuitsErrors; +use crate::registry::Circuit; +use crate::registry::DkgInputType; use e3_fhe_params::{BfvPreset, ParameterType}; use fhe::bfv::{BfvParameters, PublicKey}; @@ -39,7 +43,7 @@ impl Circuit for PkBfvCircuit { impl CircuitCodegen for PkBfvCircuit { type Input = PkBfvCodegenInput; - type Error = CodegenError; + type Error = CircuitsErrors; fn codegen(&self, input: Self::Input) -> Result { codegen::codegen(input.preset, input.public_key) @@ -50,7 +54,7 @@ impl CircuitComputation for PkBfvCircuit { type Params = BfvParameters; type Input = PublicKey; type Output = PkBfvComputationOutput; - type Error = CodegenError; + type Error = CircuitsErrors; fn compute( &self, diff --git a/crates/pvss/src/circuits/pk_bfv/codegen.rs b/crates/pvss/src/circuits/pk_bfv/codegen.rs index da8d920d0c..6573a9ef86 100644 --- a/crates/pvss/src/circuits/pk_bfv/codegen.rs +++ b/crates/pvss/src/circuits/pk_bfv/codegen.rs @@ -6,26 +6,20 @@ use crate::circuits::pk_bfv::circuit::PkBfvCircuit; use crate::circuits::pk_bfv::computation::{Bits, Bounds, Witness}; -use crate::errors::CodegenError; -use crate::traits::Circuit; -use crate::traits::Computation; -use crate::traits::ReduceToZkpModulus; -use crate::types::Artifacts; -use crate::types::{Configs, Template, Toml, Wrapper}; -use crate::utils::generate_wrapper; -use crate::utils::get_security_level; +use crate::codegen::Artifacts; +use crate::computation::Computation; +use crate::computation::Configs; +use crate::computation::ReduceToZkpModulus; +use crate::computation::Toml; +use crate::errors::CircuitsErrors; +use crate::registry::Circuit; use crate::utils::map_witness_2d_vector_to_json; -use crate::utils::write_configs; -use crate::utils::write_template; -use crate::utils::write_toml; -use crate::utils::write_wrapper; use e3_fhe_params::BfvParamSet; use e3_fhe_params::BfvPreset; use fhe::bfv::BfvParameters; use fhe::bfv::PublicKey; use serde::{Deserialize, Serialize}; use serde_json; -use std::path::Path; use std::sync::Arc; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -34,7 +28,7 @@ pub struct TomlJson { pub pk1is: Vec, } -pub fn generate_toml(witness: Witness) -> Result { +pub fn generate_toml(witness: Witness) -> Result { let pk0is = map_witness_2d_vector_to_json(&witness.pk0is); let pk1is = map_witness_2d_vector_to_json(&witness.pk1is); @@ -42,7 +36,7 @@ pub fn generate_toml(witness: Witness) -> Result { Ok(toml::to_string(&toml_json)?) } -pub fn codegen(preset: BfvPreset, public_key: PublicKey) -> Result { +pub fn codegen(preset: BfvPreset, public_key: PublicKey) -> Result { let params = BfvParamSet::from(preset).build_arc(); // Compute. let bounds = Bounds::compute(¶ms, &())?; @@ -52,35 +46,8 @@ pub fn codegen(preset: BfvPreset, public_key: PublicKey) -> Result::N_PROOFS, - ::N_PUBLIC_INPUTS, - ); - - Ok(Artifacts { - toml, - configs, - template, - wrapper, - }) -} -pub fn generate_template(lambda: usize) -> Template { - format!( - r#"use lib::configs::{}::bfv::{{L, N, {}_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() -}} -"#, - get_security_level(lambda).as_str(), - ::PREFIX, - ::PREFIX, - ) + Ok(Artifacts { toml, configs }) } pub fn generate_configs(params: &Arc, bits: &Bits) -> Configs { @@ -105,24 +72,11 @@ pub global {}_BIT_PK: u32 = {}; ) } -pub fn write_artifacts( - toml: &Toml, - template: &Template, - configs: &Configs, - wrapper: &Wrapper, - path: Option<&Path>, -) -> Result<(), CodegenError> { - write_toml(&toml, path)?; - write_template(&template, path)?; - write_configs(&configs, path)?; - write_wrapper(&wrapper, path)?; - Ok(()) -} - #[cfg(test)] mod tests { use super::*; - use crate::sample; + use crate::codegen::write_artifacts; + use crate::sample::Sample; use e3_fhe_params::BfvParamSet; use e3_fhe_params::DEFAULT_BFV_PRESET; use tempfile::TempDir; @@ -131,7 +85,7 @@ mod tests { fn test_toml_generation_and_structure() { let preset = DEFAULT_BFV_PRESET; let params = BfvParamSet::from(preset).build_arc(); - let sample = sample::generate_sample(¶ms); + let sample = Sample::generate(¶ms); let artifacts = codegen(preset, sample.public_key).unwrap(); let parsed: toml::Value = artifacts.toml.parse().unwrap(); @@ -147,14 +101,7 @@ mod tests { assert!(!pk1is.is_empty()); let temp_dir = TempDir::new().unwrap(); - write_artifacts( - &artifacts.toml, - &artifacts.template, - &artifacts.configs, - &artifacts.wrapper, - Some(temp_dir.path()), - ) - .unwrap(); + write_artifacts(&artifacts.toml, &artifacts.configs, Some(temp_dir.path())).unwrap(); let output_path = temp_dir.path().join("Prover.toml"); assert!(output_path.exists()); @@ -166,16 +113,6 @@ mod tests { assert!(artifacts.toml.contains("[[pk0is]]")); assert!(artifacts.toml.contains("[[pk1is]]")); - let template_path = temp_dir.path().join("main.nr"); - assert!(template_path.exists()); - - let template_content = std::fs::read_to_string(&template_path).unwrap(); - assert!(template_content.contains("pk0is: [Polynomial; L],")); - assert!(template_content.contains("pk1is: [Polynomial; L]")); - - let wrapper_path = temp_dir.path().join("wrapper.nr"); - assert!(wrapper_path.exists()); - let configs_path = temp_dir.path().join("configs.nr"); assert!(configs_path.exists()); diff --git a/crates/pvss/src/circuits/pk_bfv/computation.rs b/crates/pvss/src/circuits/pk_bfv/computation.rs index 93870e5fbd..8c4870d620 100644 --- a/crates/pvss/src/circuits/pk_bfv/computation.rs +++ b/crates/pvss/src/circuits/pk_bfv/computation.rs @@ -4,9 +4,9 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use crate::traits::Computation; -use crate::traits::ConvertToJson; -use crate::traits::ReduceToZkpModulus; +use crate::computation::Computation; +use crate::computation::ConvertToJson; +use crate::computation::ReduceToZkpModulus; use e3_polynomial::center_coefficients_mut; use e3_polynomial::reduce_coefficients_2d; use e3_zk_helpers::utils::calculate_bit_width; @@ -76,7 +76,7 @@ impl Computation for Bits { impl Computation for Bounds { type Params = BfvParameters; type Input = (); - type Error = crate::errors::CodegenError; + type Error = fhe::Error; fn compute(params: &Self::Params, _: &Self::Input) -> Result { let mut pk_bound_max = BigUint::from(0u32); @@ -169,9 +169,9 @@ impl ReduceToZkpModulus for Witness { #[cfg(test)] mod tests { use super::*; - use crate::sample::generate_sample; - use crate::traits::ConvertToJson; - use crate::traits::ReduceToZkpModulus; + use crate::computation::ConvertToJson; + use crate::computation::ReduceToZkpModulus; + use crate::sample::Sample; use e3_fhe_params::BfvParamSet; use e3_fhe_params::DEFAULT_BFV_PRESET; @@ -189,7 +189,7 @@ mod tests { #[test] fn test_witness_reduction_and_json_roundtrip() { let params = BfvParamSet::from(DEFAULT_BFV_PRESET).build_arc(); - let encryption_data = generate_sample(¶ms); + let encryption_data = Sample::generate(¶ms); let witness = Witness::compute(¶ms, &encryption_data.public_key).unwrap(); let zkp_reduced = witness.reduce_to_zkp_modulus(); let json = zkp_reduced.convert_to_json().unwrap(); diff --git a/crates/pvss/src/codegen.rs b/crates/pvss/src/codegen.rs new file mode 100644 index 0000000000..67869b8a93 --- /dev/null +++ b/crates/pvss/src/codegen.rs @@ -0,0 +1,45 @@ +// 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::errors::CircuitsErrors; +use crate::types::{Configs, Toml}; +use std::path::Path; + +#[derive(Debug, Clone)] +pub struct Artifacts { + pub toml: Toml, + pub configs: Configs, +} + +pub trait CircuitCodegen: crate::registry::Circuit { + type Input; + type Error; + + /// Generate artifacts for a circuit. + fn codegen(&self, input: Self::Input) -> Result; +} + +pub fn write_toml(toml: &Toml, path: Option<&Path>) -> Result<(), CircuitsErrors> { + let toml_path = path.unwrap_or_else(|| Path::new(".")); + let toml_path = toml_path.join("Prover.toml"); + Ok(std::fs::write(toml_path, toml)?) +} + +pub fn write_configs(configs: &Configs, path: Option<&Path>) -> Result<(), CircuitsErrors> { + let configs_path = path.unwrap_or_else(|| Path::new(".")); + let configs_path = configs_path.join("configs.nr"); + Ok(std::fs::write(configs_path, configs)?) +} + +pub fn write_artifacts( + toml: &Toml, + configs: &Configs, + path: Option<&Path>, +) -> Result<(), CircuitsErrors> { + write_toml(&toml, path)?; + write_configs(&configs, path)?; + Ok(()) +} diff --git a/crates/pvss/src/computation.rs b/crates/pvss/src/computation.rs new file mode 100644 index 0000000000..54823c2606 --- /dev/null +++ b/crates/pvss/src/computation.rs @@ -0,0 +1,44 @@ +// 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. + +/// TOML file for the circuit. +pub type Toml = String; +/// Configs file for the circuit. +pub type Configs = String; + +/// Trait for computation. +pub trait Computation: Sized { + type Params; + type Input; + type Error; + + fn compute(params: &Self::Params, input: &Self::Input) -> Result; +} + +/// Trait for circuit computation. +pub trait CircuitComputation: crate::registry::Circuit { + type Params; + type Input; + type Output; + type Error; + + /// Compute circuit-specific data. + fn compute( + &self, + params: &Self::Params, + input: &Self::Input, + ) -> Result; +} + +/// Trait for converting to JSON. +pub trait ConvertToJson { + fn convert_to_json(&self) -> serde_json::Result; +} + +/// Trait for reducing to ZKP modulus. +pub trait ReduceToZkpModulus: Sized { + fn reduce_to_zkp_modulus(&self) -> Self; +} diff --git a/crates/pvss/src/errors.rs b/crates/pvss/src/errors.rs index 04ed43423a..4ab0e042c0 100644 --- a/crates/pvss/src/errors.rs +++ b/crates/pvss/src/errors.rs @@ -7,7 +7,7 @@ use thiserror::Error; #[derive(Error, Debug)] -pub enum CodegenError { +pub enum CircuitsErrors { #[error("I/O error: {0}")] Io(#[from] std::io::Error), #[error("TOML serialization error: {0}")] diff --git a/crates/pvss/src/lib.rs b/crates/pvss/src/lib.rs index 9be7fb848e..8de674e946 100644 --- a/crates/pvss/src/lib.rs +++ b/crates/pvss/src/lib.rs @@ -5,9 +5,10 @@ // or FITNESS FOR A PARTICULAR PURPOSE. pub mod circuits; +pub mod codegen; +pub mod computation; pub mod errors; pub mod registry; pub mod sample; -pub mod traits; pub mod types; pub mod utils; diff --git a/crates/pvss/src/registry.rs b/crates/pvss/src/registry.rs index 4229475fd1..41d8af8a37 100644 --- a/crates/pvss/src/registry.rs +++ b/crates/pvss/src/registry.rs @@ -4,8 +4,6 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use crate::traits::CircuitMetadata; -use crate::types::DkgInputType; use e3_fhe_params::ParameterType; use std::collections::HashMap; use std::sync::Arc; @@ -18,6 +16,79 @@ pub enum RegistryError { UnknownCircuit { name: String }, } +/// Variant for input types for DKG. +#[derive(Clone)] +pub enum DkgInputType { + /// The input type that generates shares of a secret key using secret sharing. + SecretKey, + /// The input type that generates shares of smudging noise instead of secret key shares. + SmudgingNoise, +} + +/// Trait for circuit metadata. +pub trait Circuit: Send + Sync { + const NAME: &'static str; + const PREFIX: &'static str; + const SUPPORTED_PARAMETER: ParameterType; + const DKG_INPUT_TYPE: Option; + const N_PROOFS: usize; + const N_PUBLIC_INPUTS: usize; + + fn name(&self) -> &'static str { + Self::NAME + } + + fn prefix(&self) -> &'static str { + Self::PREFIX + } + + fn supported_parameter(&self) -> ParameterType { + Self::SUPPORTED_PARAMETER + } + + fn dkg_input_type(&self) -> Option { + Self::DKG_INPUT_TYPE + } + + fn n_recursive_proofs(&self) -> usize { + Self::N_PROOFS + } + + fn n_public_inputs(&self) -> usize { + Self::N_PUBLIC_INPUTS + } +} + +pub trait CircuitMetadata: Send + Sync { + fn name(&self) -> &'static str; + fn supported_parameter(&self) -> ParameterType; + fn dkg_input_type(&self) -> Option; + fn n_recursive_proofs(&self) -> usize; + fn n_public_inputs(&self) -> usize; +} + +impl CircuitMetadata for T { + fn name(&self) -> &'static str { + T::NAME + } + + fn supported_parameter(&self) -> ParameterType { + T::SUPPORTED_PARAMETER + } + + fn dkg_input_type(&self) -> Option { + T::DKG_INPUT_TYPE + } + + fn n_recursive_proofs(&self) -> usize { + T::N_PROOFS + } + + fn n_public_inputs(&self) -> usize { + T::N_PUBLIC_INPUTS + } +} + /// Registry for PVSS circuits. pub struct CircuitRegistry { circuits: HashMap>, @@ -77,8 +148,17 @@ impl CircuitRegistry { #[cfg(test)] mod tests { use super::*; - use crate::circuits::pk_bfv::circuit::PkBfvCircuit; - use crate::traits::Circuit; + + pub struct TestCircuit; + + impl Circuit for TestCircuit { + const NAME: &'static str = "test"; + const PREFIX: &'static str = "TEST"; + const SUPPORTED_PARAMETER: ParameterType = ParameterType::DKG; + const DKG_INPUT_TYPE: Option = Some(DkgInputType::SecretKey); + const N_PROOFS: usize = 1; + const N_PUBLIC_INPUTS: usize = 1; + } #[test] /// Unknown circuits should return an error. @@ -94,19 +174,19 @@ mod tests { /// Registry should expose metadata for registered circuits. fn registry_reports_expected_metadata() { let mut registry = CircuitRegistry::new(); - registry.register(Arc::new(PkBfvCircuit)); - let circuit = registry.get(::NAME).unwrap(); + registry.register(Arc::new(TestCircuit)); + let circuit = registry.get(::NAME).unwrap(); - assert_eq!(circuit.name(), ::NAME); + assert_eq!(circuit.name(), ::NAME); assert_eq!(circuit.supported_parameter(), ParameterType::DKG); - assert!(circuit.dkg_input_type().is_none()); + assert!(circuit.dkg_input_type().is_some()); assert_eq!( circuit.n_recursive_proofs(), - ::N_PROOFS + ::N_PROOFS ); assert_eq!( circuit.n_public_inputs(), - ::N_PUBLIC_INPUTS + ::N_PUBLIC_INPUTS ); } } diff --git a/crates/pvss/src/sample.rs b/crates/pvss/src/sample.rs index 15a1992f1a..ec3d733e5a 100644 --- a/crates/pvss/src/sample.rs +++ b/crates/pvss/src/sample.rs @@ -4,18 +4,24 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use crate::types::Sample; use fhe::bfv::{BfvParameters, PublicKey, SecretKey}; use rand::thread_rng; use std::sync::Arc; -pub fn generate_sample(params: &Arc) -> Sample { - let mut rng = thread_rng(); +#[derive(Debug, Clone)] +pub struct Sample { + pub public_key: PublicKey, +} + +impl Sample { + pub fn generate(params: &Arc) -> Self { + let mut rng = thread_rng(); - let secret_key = SecretKey::random(¶ms, &mut rng); - let public_key = PublicKey::new(&secret_key, &mut rng); + let secret_key = SecretKey::random(¶ms, &mut rng); + let public_key = PublicKey::new(&secret_key, &mut rng); - Sample { public_key } + Self { public_key } + } } #[cfg(test)] @@ -27,7 +33,7 @@ mod tests { #[test] fn test_generate_sample() { let params = BfvParamSet::from(DEFAULT_BFV_PRESET).build_arc(); - let sample = generate_sample(¶ms); + let sample = Sample::generate(¶ms); assert_eq!(sample.public_key.c.c.len(), 2); } diff --git a/crates/pvss/src/traits.rs b/crates/pvss/src/traits.rs deleted file mode 100644 index 78fa9dfaf1..0000000000 --- a/crates/pvss/src/traits.rs +++ /dev/null @@ -1,112 +0,0 @@ -// 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. - -//! Common computation behavior across circuits. - -use crate::types::DkgInputType; -use e3_fhe_params::ParameterType; -use serde_json::Value; - -pub trait Computation: Sized { - type Params; - type Input; - type Error; - - fn compute(params: &Self::Params, input: &Self::Input) -> Result; -} - -pub trait ConvertToJson { - fn convert_to_json(&self) -> serde_json::Result; -} - -pub trait ReduceToZkpModulus: Sized { - fn reduce_to_zkp_modulus(&self) -> Self; -} - -pub trait Circuit: Send + Sync { - const NAME: &'static str; - const PREFIX: &'static str; - const SUPPORTED_PARAMETER: ParameterType; - const DKG_INPUT_TYPE: Option; - const N_PROOFS: usize; - const N_PUBLIC_INPUTS: usize; - - fn name(&self) -> &'static str { - Self::NAME - } - - fn prefix(&self) -> &'static str { - Self::PREFIX - } - - fn supported_parameter(&self) -> ParameterType { - Self::SUPPORTED_PARAMETER - } - - fn dkg_input_type(&self) -> Option { - Self::DKG_INPUT_TYPE - } - - fn n_recursive_proofs(&self) -> usize { - Self::N_PROOFS - } - - fn n_public_inputs(&self) -> usize { - Self::N_PUBLIC_INPUTS - } -} - -pub trait CircuitMetadata: Send + Sync { - fn name(&self) -> &'static str; - fn supported_parameter(&self) -> ParameterType; - fn dkg_input_type(&self) -> Option; - fn n_recursive_proofs(&self) -> usize; - fn n_public_inputs(&self) -> usize; -} - -impl CircuitMetadata for T { - fn name(&self) -> &'static str { - T::NAME - } - - fn supported_parameter(&self) -> ParameterType { - T::SUPPORTED_PARAMETER - } - - fn dkg_input_type(&self) -> Option { - T::DKG_INPUT_TYPE - } - - fn n_recursive_proofs(&self) -> usize { - T::N_PROOFS - } - - fn n_public_inputs(&self) -> usize { - T::N_PUBLIC_INPUTS - } -} - -pub trait CircuitCodegen: Circuit { - type Input; - type Error; - - /// Generate artifacts for a circuit. - fn codegen(&self, input: Self::Input) -> Result; -} - -pub trait CircuitComputation: Circuit { - type Params; - type Input; - type Output; - type Error; - - /// Compute circuit-specific data. - fn compute( - &self, - params: &Self::Params, - input: &Self::Input, - ) -> Result; -} diff --git a/crates/pvss/src/types.rs b/crates/pvss/src/types.rs index d244d8445a..bc2cce1633 100644 --- a/crates/pvss/src/types.rs +++ b/crates/pvss/src/types.rs @@ -3,24 +3,11 @@ // This file is provided WITHOUT ANY WARRANTY; // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use fhe::bfv::PublicKey; +/// TOML file for the circuit. pub type Toml = String; -pub type Template = String; +/// Configs file for the circuit. pub type Configs = String; -pub type Wrapper = String; - -/// Variant for input types for DKG. -/// -/// This variant is used to determine the type of input that is used for the DKG -/// circuits (C2, C3, C4) -#[derive(Clone)] -pub enum DkgInputType { - /// The input type that generates shares of a secret key using secret sharing. - SecretKey, - /// The input type that generates shares of smudging noise instead of secret key shares. - SmudgingNoise, -} /// @todo this must be integrated inside Ciphernodes & Smart Contract /// instead of being a separate type in here. The pvss crate should import this and @@ -69,31 +56,3 @@ impl CiphernodesCommitteeSize { // }, } } - -#[derive(Debug, Clone, Copy)] -pub enum SecurityLevel { - INSECURE, - PRODUCTION, -} - -impl SecurityLevel { - pub fn as_str(self) -> &'static str { - match self { - SecurityLevel::INSECURE => "insecure", - SecurityLevel::PRODUCTION => "production", - } - } -} - -#[derive(Debug, Clone)] -pub struct Sample { - pub public_key: PublicKey, -} - -#[derive(Debug, Clone)] -pub struct Artifacts { - pub toml: Toml, - pub configs: Configs, - pub template: Template, - pub wrapper: Wrapper, -} diff --git a/crates/pvss/src/utils.rs b/crates/pvss/src/utils.rs index 652855e5d3..d639fdeda8 100644 --- a/crates/pvss/src/utils.rs +++ b/crates/pvss/src/utils.rs @@ -4,12 +4,9 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -use crate::errors::CodegenError; -use crate::types::{Configs, SecurityLevel, Template, Toml, Wrapper}; use e3_zk_helpers::utils::to_string_1d_vec; use num_bigint::BigInt; use serde_json; -use std::path::Path; pub fn map_witness_2d_vector_to_json(values: &Vec>) -> Vec { values @@ -21,70 +18,3 @@ pub fn map_witness_2d_vector_to_json(values: &Vec>) -> Vec SecurityLevel { - if lambda < 80 { - SecurityLevel::INSECURE - } else { - SecurityLevel::PRODUCTION - } -} - -pub fn generate_wrapper(n_recursive_proofs: usize, n_public_inputs: usize) -> Wrapper { - format!( - r#"use bb_proof_verification::{{UltraHonkProof, UltraHonkVerificationKey, verify_ultrahonk_proof}}; -use lib::math::commitments::compute_recursive_aggregation_commitment; - -// Number of proofs. -pub global N_PROOFS: u32 = {}; -/// Number of public inputs/outputs per proof. -pub global N_PUBLIC_INPUTS: u32 = {}; - -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_recursive_aggregation_commitment(aggregated_public_inputs) -}} -"#, - n_recursive_proofs, n_public_inputs - ) -} - -pub fn write_toml(toml: &Toml, path: Option<&Path>) -> Result<(), CodegenError> { - let toml_path = path.unwrap_or_else(|| Path::new(".")); - let toml_path = toml_path.join("Prover.toml"); - Ok(std::fs::write(toml_path, toml)?) -} - -pub fn write_template(template: &Template, path: Option<&Path>) -> Result<(), CodegenError> { - let template_path = path.unwrap_or_else(|| Path::new(".")); - let template_path = template_path.join("main.nr"); - Ok(std::fs::write(template_path, template)?) -} - -pub fn write_configs(configs: &Configs, path: Option<&Path>) -> Result<(), CodegenError> { - let configs_path = path.unwrap_or_else(|| Path::new(".")); - let configs_path = configs_path.join("configs.nr"); - Ok(std::fs::write(configs_path, configs)?) -} - -pub fn write_wrapper(wrapper: &Wrapper, path: Option<&Path>) -> Result<(), CodegenError> { - let wrapper_path = path.unwrap_or_else(|| Path::new(".")); - let wrapper_path = wrapper_path.join("wrapper.nr"); - Ok(std::fs::write(wrapper_path, wrapper)?) -} From d6d1925a2e1a717eadb98301cdf71cf76b2c81ff Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 3 Feb 2026 11:23:50 +0100 Subject: [PATCH 03/10] move to zk-helpers --- Cargo.lock | 33 +++++++------------ Cargo.toml | 2 -- crates/Dockerfile | 1 - crates/pvss/Cargo.toml | 25 -------------- crates/pvss/src/utils.rs | 20 ----------- crates/zk-helpers/Cargo.toml | 11 +++++++ crates/zk-helpers/src/bin/zk_cli.rs | 16 ++++----- .../src/circuits}/codegen.rs | 3 +- .../src/{ => circuits}/commitments.rs | 0 .../src/circuits}/computation.rs | 0 .../src => zk-helpers/src/circuits}/errors.rs | 3 +- .../lib.rs => zk-helpers/src/circuits/mod.rs} | 14 +++++--- .../src/circuits/pk_bfv/circuit.rs | 0 .../src/circuits/pk_bfv/codegen.rs | 0 .../src/circuits/pk_bfv/computation.rs | 6 ++-- .../src/circuits/pk_bfv/mod.rs | 4 +++ .../src => zk-helpers/src/circuits}/sample.rs | 0 crates/zk-helpers/src/lib.rs | 6 ++-- .../src/registry}/mod.rs | 4 ++- .../src/registry}/registry.rs | 0 crates/{pvss => zk-helpers}/src/types.rs | 5 --- crates/zk-helpers/src/utils.rs | 18 ++++++++++ examples/CRISP/Cargo.lock | 17 ++++++++-- templates/default/Cargo.lock | 19 ++++++++--- 24 files changed, 103 insertions(+), 104 deletions(-) delete mode 100644 crates/pvss/Cargo.toml delete mode 100644 crates/pvss/src/utils.rs rename crates/{pvss/src => zk-helpers/src/circuits}/codegen.rs (95%) rename crates/zk-helpers/src/{ => circuits}/commitments.rs (100%) rename crates/{pvss/src => zk-helpers/src/circuits}/computation.rs (100%) rename crates/{pvss/src => zk-helpers/src/circuits}/errors.rs (87%) rename crates/{pvss/src/lib.rs => zk-helpers/src/circuits/mod.rs} (61%) rename crates/{pvss => zk-helpers}/src/circuits/pk_bfv/circuit.rs (100%) rename crates/{pvss => zk-helpers}/src/circuits/pk_bfv/codegen.rs (100%) rename crates/{pvss => zk-helpers}/src/circuits/pk_bfv/computation.rs (97%) rename crates/{pvss => zk-helpers}/src/circuits/pk_bfv/mod.rs (78%) rename crates/{pvss/src => zk-helpers/src/circuits}/sample.rs (100%) rename crates/{pvss/src/circuits => zk-helpers/src/registry}/mod.rs (82%) rename crates/{pvss/src => zk-helpers/src/registry}/registry.rs (100%) rename crates/{pvss => zk-helpers}/src/types.rs (93%) diff --git a/Cargo.lock b/Cargo.lock index 71d87cf6bc..2aa6f62c55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3345,28 +3345,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "e3-pvss" -version = "0.1.8" -dependencies = [ - "anyhow", - "e3-fhe-params", - "e3-polynomial 0.1.8", - "e3-zk-helpers", - "fhe", - "fhe-math", - "itertools 0.14.0", - "num-bigint", - "num-traits", - "rand 0.8.5", - "rayon", - "serde", - "serde_json", - "tempfile", - "thiserror 1.0.69", - "toml", -] - [[package]] name = "e3-request" version = "0.1.8" @@ -3598,14 +3576,25 @@ dependencies = [ name = "e3-zk-helpers" version = "0.1.8" dependencies = [ + "anyhow", "ark-bn254 0.5.0", "ark-ff 0.5.0", + "clap", + "e3-fhe-params", "e3-polynomial 0.1.8", "e3-safe 0.1.8", "fhe", + "fhe-math", + "itertools 0.14.0", "num-bigint", "num-traits", + "rand 0.8.5", + "rayon", + "serde", + "serde_json", + "tempfile", "thiserror 1.0.69", + "toml", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 281cf067fc..b53155d9d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,6 @@ members = [ "crates/parity-matrix", "crates/polynomial", "crates/zk-helpers", - "crates/pvss" ] exclude = [ "examples/CRISP", @@ -107,7 +106,6 @@ e3-trbfv = { version = "0.1.8", path = "./crates/trbfv" } e3-utils = { version = "0.1.8", path = "./crates/utils" } e3-safe = { version = "0.1.8", path = "./crates/safe" } e3-zk-helpers = { version = "0.1.8", path = "./crates/zk-helpers" } -e3-pvss = { version = "0.1.8", path = "./crates/pvss" } actix = "=0.13.5" actix-web = "=4.11.0" diff --git a/crates/Dockerfile b/crates/Dockerfile index c103eec2c9..5904b15eae 100644 --- a/crates/Dockerfile +++ b/crates/Dockerfile @@ -81,7 +81,6 @@ COPY crates/trbfv/Cargo.toml ./trbfv/Cargo.toml COPY crates/utils/Cargo.toml ./utils/Cargo.toml COPY crates/wasm/Cargo.toml ./wasm/Cargo.toml COPY crates/zk-helpers/Cargo.toml ./zk-helpers/Cargo.toml -COPY crates/pvss/Cargo.toml ./pvss/Cargo.toml RUN echo 'fn main() { println!("cargo:warning=dependency cache build"); }' > ./entrypoint/build.rs RUN echo 'fn main() { println!("cargo:warning=dependency cache build"); }' > ./cli/build.rs diff --git a/crates/pvss/Cargo.toml b/crates/pvss/Cargo.toml deleted file mode 100644 index 1246c23752..0000000000 --- a/crates/pvss/Cargo.toml +++ /dev/null @@ -1,25 +0,0 @@ -[package] -name = "e3-pvss" -version.workspace = true -edition.workspace = true -license.workspace = true -description = "PVSS core codegen and computation crate" -repository = "https://github.com/gnosisguild/enclave/crates/pvss" - -[dependencies] -e3-polynomial = { workspace = true } -fhe = { workspace = true } -fhe-math = { workspace = true } -e3-fhe-params = { workspace = true } -e3-zk-helpers = { workspace = true } -num-bigint = { workspace = true } -num-traits = { workspace = true } -rand = { workspace = true } -rayon = { workspace = true } -itertools = "0.14.0" -serde = { workspace = true } -serde_json = { workspace = true } -toml = "0.8.23" -anyhow = { workspace = true } -tempfile = { workspace = true } -thiserror = { workspace = true } diff --git a/crates/pvss/src/utils.rs b/crates/pvss/src/utils.rs deleted file mode 100644 index d639fdeda8..0000000000 --- a/crates/pvss/src/utils.rs +++ /dev/null @@ -1,20 +0,0 @@ -// 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 e3_zk_helpers::utils::to_string_1d_vec; -use num_bigint::BigInt; -use serde_json; - -pub fn map_witness_2d_vector_to_json(values: &Vec>) -> Vec { - values - .iter() - .map(|value| { - serde_json::json!({ - "coefficients": to_string_1d_vec(value) - }) - }) - .collect() -} diff --git a/crates/zk-helpers/Cargo.toml b/crates/zk-helpers/Cargo.toml index e9147a37cc..4e37a71efb 100644 --- a/crates/zk-helpers/Cargo.toml +++ b/crates/zk-helpers/Cargo.toml @@ -7,14 +7,25 @@ description = "ZK circuit helpers" repository = "https://github.com/gnosisguild/enclave/crates/zk-helpers" [dependencies] +anyhow = { workspace = true } ark-bn254 = { workspace = true } +clap = { workspace = true } ark-ff = { workspace = true } e3-polynomial = { workspace = true } e3-safe = { workspace = true } +e3-fhe-params = { workspace = true } fhe = { workspace = true } +fhe-math = { workspace = true } num-bigint = { workspace = true } num-traits = { workspace = true } thiserror = { workspace = true } +rand = { workspace = true } +rayon = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +toml = "0.8.23" +itertools = "0.14.0" +tempfile = { workspace = true } [[bin]] name = "zk_cli" diff --git a/crates/zk-helpers/src/bin/zk_cli.rs b/crates/zk-helpers/src/bin/zk_cli.rs index a466344134..233e7b9560 100644 --- a/crates/zk-helpers/src/bin/zk_cli.rs +++ b/crates/zk-helpers/src/bin/zk_cli.rs @@ -5,14 +5,12 @@ // or FITNESS FOR A PARTICULAR PURPOSE. use anyhow::{anyhow, Context, Result}; -use clap::Parser; +use clap::{arg, command, Parser}; use e3_fhe_params::{BfvParamSet, BfvPreset}; -use e3_pvss::circuits::pk_bfv::circuit::{PkBfvCircuit, PkBfvCodegenInput}; -use e3_pvss::circuits::pk_bfv::codegen::write_artifacts; -use e3_pvss::registry::CircuitRegistry; -use e3_pvss::sample; -use e3_pvss::traits::Circuit; -use e3_pvss::traits::CircuitCodegen; +use e3_zk_helpers::circuits::pk_bfv::circuit::{PkBfvCircuit, PkBfvCodegenInput}; +use e3_zk_helpers::codegen::{write_artifacts, CircuitCodegen}; +use e3_zk_helpers::registry::{Circuit, CircuitRegistry}; +use e3_zk_helpers::sample::Sample; use std::path::PathBuf; use std::sync::Arc; @@ -94,7 +92,7 @@ fn main() -> Result<()> { // Generate artifacts based on circuit name from registry. let params = BfvParamSet::from(preset).build_arc(); - let sample = sample::generate_sample(¶ms); + let sample = Sample::generate(¶ms); let circuit_name = circuit_meta.name(); let artifacts = match circuit_name { name if name == ::NAME => { @@ -109,9 +107,7 @@ fn main() -> Result<()> { write_artifacts( &artifacts.toml, - &artifacts.template, &artifacts.configs, - &artifacts.wrapper, Some(args.output.as_path()), )?; diff --git a/crates/pvss/src/codegen.rs b/crates/zk-helpers/src/circuits/codegen.rs similarity index 95% rename from crates/pvss/src/codegen.rs rename to crates/zk-helpers/src/circuits/codegen.rs index 67869b8a93..c657cc139e 100644 --- a/crates/pvss/src/codegen.rs +++ b/crates/zk-helpers/src/circuits/codegen.rs @@ -4,8 +4,9 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +use crate::computation::Configs; +use crate::computation::Toml; use crate::errors::CircuitsErrors; -use crate::types::{Configs, Toml}; use std::path::Path; #[derive(Debug, Clone)] diff --git a/crates/zk-helpers/src/commitments.rs b/crates/zk-helpers/src/circuits/commitments.rs similarity index 100% rename from crates/zk-helpers/src/commitments.rs rename to crates/zk-helpers/src/circuits/commitments.rs diff --git a/crates/pvss/src/computation.rs b/crates/zk-helpers/src/circuits/computation.rs similarity index 100% rename from crates/pvss/src/computation.rs rename to crates/zk-helpers/src/circuits/computation.rs diff --git a/crates/pvss/src/errors.rs b/crates/zk-helpers/src/circuits/errors.rs similarity index 87% rename from crates/pvss/src/errors.rs rename to crates/zk-helpers/src/circuits/errors.rs index 4ab0e042c0..a56b7f7513 100644 --- a/crates/pvss/src/errors.rs +++ b/crates/zk-helpers/src/circuits/errors.rs @@ -4,6 +4,7 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +use crate::utils::ZkHelpersUtilsError; use thiserror::Error; #[derive(Error, Debug)] @@ -15,7 +16,7 @@ pub enum CircuitsErrors { #[error("BFV error: {0}")] Fhe(#[from] fhe::Error), #[error("ZK helper error: {0}")] - ZkHelpers(#[from] e3_zk_helpers::utils::ZkHelpersUtilsError), + ZkHelpers(#[from] ZkHelpersUtilsError), #[error("Unexpected error: {0}")] Other(String), } diff --git a/crates/pvss/src/lib.rs b/crates/zk-helpers/src/circuits/mod.rs similarity index 61% rename from crates/pvss/src/lib.rs rename to crates/zk-helpers/src/circuits/mod.rs index 8de674e946..3c5e7b5c9c 100644 --- a/crates/pvss/src/lib.rs +++ b/crates/zk-helpers/src/circuits/mod.rs @@ -4,11 +4,17 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -pub mod circuits; pub mod codegen; +pub mod commitments; pub mod computation; pub mod errors; -pub mod registry; pub mod sample; -pub mod types; -pub mod utils; + +pub use codegen::*; +pub use commitments::*; +pub use computation::*; +pub use errors::*; +pub use sample::*; + +pub mod pk_bfv; +pub use pk_bfv::*; diff --git a/crates/pvss/src/circuits/pk_bfv/circuit.rs b/crates/zk-helpers/src/circuits/pk_bfv/circuit.rs similarity index 100% rename from crates/pvss/src/circuits/pk_bfv/circuit.rs rename to crates/zk-helpers/src/circuits/pk_bfv/circuit.rs diff --git a/crates/pvss/src/circuits/pk_bfv/codegen.rs b/crates/zk-helpers/src/circuits/pk_bfv/codegen.rs similarity index 100% rename from crates/pvss/src/circuits/pk_bfv/codegen.rs rename to crates/zk-helpers/src/circuits/pk_bfv/codegen.rs diff --git a/crates/pvss/src/circuits/pk_bfv/computation.rs b/crates/zk-helpers/src/circuits/pk_bfv/computation.rs similarity index 97% rename from crates/pvss/src/circuits/pk_bfv/computation.rs rename to crates/zk-helpers/src/circuits/pk_bfv/computation.rs index 8c4870d620..1a4e834235 100644 --- a/crates/pvss/src/circuits/pk_bfv/computation.rs +++ b/crates/zk-helpers/src/circuits/pk_bfv/computation.rs @@ -7,10 +7,10 @@ use crate::computation::Computation; use crate::computation::ConvertToJson; use crate::computation::ReduceToZkpModulus; +use crate::utils::calculate_bit_width; +use crate::utils::get_zkp_modulus; use e3_polynomial::center_coefficients_mut; use e3_polynomial::reduce_coefficients_2d; -use e3_zk_helpers::utils::calculate_bit_width; -use e3_zk_helpers::utils::get_zkp_modulus; use fhe::bfv::BfvParameters; use fhe::bfv::PublicKey; use fhe_math::rq::Representation; @@ -64,7 +64,7 @@ impl Computation for Constants { impl Computation for Bits { type Params = BfvParameters; type Input = Bounds; - type Error = e3_zk_helpers::utils::ZkHelpersUtilsError; + type Error = crate::utils::ZkHelpersUtilsError; fn compute(_: &Self::Params, input: &Self::Input) -> Result { Ok(Bits { diff --git a/crates/pvss/src/circuits/pk_bfv/mod.rs b/crates/zk-helpers/src/circuits/pk_bfv/mod.rs similarity index 78% rename from crates/pvss/src/circuits/pk_bfv/mod.rs rename to crates/zk-helpers/src/circuits/pk_bfv/mod.rs index 63504b9145..caff0b46d5 100644 --- a/crates/pvss/src/circuits/pk_bfv/mod.rs +++ b/crates/zk-helpers/src/circuits/pk_bfv/mod.rs @@ -7,3 +7,7 @@ pub mod circuit; pub mod codegen; pub mod computation; + +pub use circuit::*; +pub use codegen::*; +pub use computation::*; diff --git a/crates/pvss/src/sample.rs b/crates/zk-helpers/src/circuits/sample.rs similarity index 100% rename from crates/pvss/src/sample.rs rename to crates/zk-helpers/src/circuits/sample.rs diff --git a/crates/zk-helpers/src/lib.rs b/crates/zk-helpers/src/lib.rs index 1d258c43af..18ca81bd7e 100644 --- a/crates/zk-helpers/src/lib.rs +++ b/crates/zk-helpers/src/lib.rs @@ -4,10 +4,12 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -pub mod commitments; +pub mod circuits; pub mod packing; +pub mod registry; pub mod utils; -pub use commitments::*; +pub use circuits::*; pub use packing::*; +pub use registry::*; pub use utils::*; diff --git a/crates/pvss/src/circuits/mod.rs b/crates/zk-helpers/src/registry/mod.rs similarity index 82% rename from crates/pvss/src/circuits/mod.rs rename to crates/zk-helpers/src/registry/mod.rs index 78aa5fbb5d..99b9c9613a 100644 --- a/crates/pvss/src/circuits/mod.rs +++ b/crates/zk-helpers/src/registry/mod.rs @@ -4,4 +4,6 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -pub mod pk_bfv; +pub mod registry; + +pub use registry::*; diff --git a/crates/pvss/src/registry.rs b/crates/zk-helpers/src/registry/registry.rs similarity index 100% rename from crates/pvss/src/registry.rs rename to crates/zk-helpers/src/registry/registry.rs diff --git a/crates/pvss/src/types.rs b/crates/zk-helpers/src/types.rs similarity index 93% rename from crates/pvss/src/types.rs rename to crates/zk-helpers/src/types.rs index bc2cce1633..c397e51721 100644 --- a/crates/pvss/src/types.rs +++ b/crates/zk-helpers/src/types.rs @@ -4,11 +4,6 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -/// TOML file for the circuit. -pub type Toml = String; -/// Configs file for the circuit. -pub type Configs = String; - /// @todo this must be integrated inside Ciphernodes & Smart Contract /// instead of being a separate type in here. The pvss crate should import this and /// the default values that must be used and shared among the whole enclave repository. diff --git a/crates/zk-helpers/src/utils.rs b/crates/zk-helpers/src/utils.rs index 18237880c3..84eca15131 100644 --- a/crates/zk-helpers/src/utils.rs +++ b/crates/zk-helpers/src/utils.rs @@ -150,6 +150,24 @@ pub fn get_zkp_modulus() -> BigInt { .expect("Invalid ZKP modulus") } +/// Map a 2D vector of BigInt to a vector of JSON values. +/// +/// # Arguments +/// * `values` - 2D vector of BigInt values +/// +/// # Returns +/// A vector of JSON values +pub fn map_witness_2d_vector_to_json(values: &Vec>) -> Vec { + values + .iter() + .map(|value| { + serde_json::json!({ + "coefficients": to_string_1d_vec(value) + }) + }) + .collect() +} + #[cfg(test)] mod tests { use super::*; diff --git a/examples/CRISP/Cargo.lock b/examples/CRISP/Cargo.lock index bafa64ef45..799aede9e3 100644 --- a/examples/CRISP/Cargo.lock +++ b/examples/CRISP/Cargo.lock @@ -2568,14 +2568,25 @@ dependencies = [ name = "e3-zk-helpers" version = "0.1.8" dependencies = [ + "anyhow", "ark-bn254 0.5.0", "ark-ff 0.5.0", + "clap", + "e3-fhe-params", "e3-polynomial 0.1.8", "e3-safe 0.1.8", "fhe", + "fhe-math", + "itertools 0.14.0", "num-bigint", "num-traits", + "rand 0.8.5", + "rayon", + "serde", + "serde_json", + "tempfile", "thiserror 1.0.69", + "toml", ] [[package]] @@ -5624,15 +5635,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.24.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] diff --git a/templates/default/Cargo.lock b/templates/default/Cargo.lock index 3b421f369d..cc43dccbf0 100644 --- a/templates/default/Cargo.lock +++ b/templates/default/Cargo.lock @@ -1266,7 +1266,7 @@ dependencies = [ "anyhow", "e3-fhe-params", "e3-greco-helpers", - "e3-polynomial", + "e3-polynomial 0.1.8", "e3-zk-helpers", "fhe", "fhe-traits", @@ -1405,14 +1405,25 @@ dependencies = [ name = "e3-zk-helpers" version = "0.1.8" dependencies = [ + "anyhow", "ark-bn254 0.5.0", "ark-ff 0.5.0", + "clap", + "e3-fhe-params", "e3-polynomial 0.1.8", "e3-safe 0.1.8", "fhe", + "fhe-math", + "itertools 0.14.0", "num-bigint", "num-traits", + "rand 0.8.5", + "rayon", + "serde", + "serde_json", + "tempfile", "thiserror", + "toml", ] [[package]] @@ -3703,15 +3714,15 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.24.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] From ae5d5883ffaae39e9a73794f93e94d3069526a54 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 3 Feb 2026 11:31:52 +0100 Subject: [PATCH 04/10] add tests and docs --- crates/zk-helpers/src/bin/zk_cli.rs | 9 ++- crates/zk-helpers/src/circuits/codegen.rs | 72 ++++++++++++++++++- crates/zk-helpers/src/circuits/computation.rs | 21 ++++-- crates/zk-helpers/src/circuits/errors.rs | 3 + crates/zk-helpers/src/circuits/mod.rs | 7 ++ .../zk-helpers/src/circuits/pk_bfv/circuit.rs | 11 +++ .../zk-helpers/src/circuits/pk_bfv/codegen.rs | 8 +++ .../src/circuits/pk_bfv/computation.rs | 18 ++++- crates/zk-helpers/src/circuits/pk_bfv/mod.rs | 6 ++ crates/zk-helpers/src/circuits/sample.rs | 8 +++ crates/zk-helpers/src/registry/mod.rs | 5 ++ 11 files changed, 155 insertions(+), 13 deletions(-) diff --git a/crates/zk-helpers/src/bin/zk_cli.rs b/crates/zk-helpers/src/bin/zk_cli.rs index 233e7b9560..7da65f45e7 100644 --- a/crates/zk-helpers/src/bin/zk_cli.rs +++ b/crates/zk-helpers/src/bin/zk_cli.rs @@ -4,6 +4,12 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +//! ZK CLI — command-line tool for zero-knowledge circuit artifact generation. +//! +//! This binary lists available circuits and generates Prover.toml and configs.nr +//! for use with the Noir prover. Use `--list_circuits` to see circuits and +//! `--circuit --preset ` to generate artifacts. + use anyhow::{anyhow, Context, Result}; use clap::{arg, command, Parser}; use e3_fhe_params::{BfvParamSet, BfvPreset}; @@ -32,7 +38,8 @@ struct Cli { output: PathBuf, } -/// Parse a preset name into a BFV preset. +/// Parses a preset name (e.g. `"default"`) into a [`BfvPreset`]. +/// Returns an error listing available presets if the name is unknown. fn parse_preset(name: &str) -> Result { BfvPreset::from_name(name).map_err(|_| { let available = BfvPreset::list().join(", "); diff --git a/crates/zk-helpers/src/circuits/codegen.rs b/crates/zk-helpers/src/circuits/codegen.rs index c657cc139e..e22b619d7d 100644 --- a/crates/zk-helpers/src/circuits/codegen.rs +++ b/crates/zk-helpers/src/circuits/codegen.rs @@ -4,43 +4,109 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +//! Circuit artifact types and I/O. +//! +//! [`CircuitCodegen`] is implemented by circuits that can produce [`Artifacts`] +//! (Prover.toml and configs.nr). Use [`write_artifacts`] to write them to disk. + use crate::computation::Configs; use crate::computation::Toml; use crate::errors::CircuitsErrors; use std::path::Path; +/// Generated files for a circuit: Prover TOML and Noir configs. #[derive(Debug, Clone)] pub struct Artifacts { + /// Prover.toml content (witness and circuit inputs). pub toml: Toml, + /// configs.nr content (constants for the Noir prover). pub configs: Configs, } +/// Trait for circuits that can generate Prover.toml and configs.nr from circuit-specific input. pub trait CircuitCodegen: crate::registry::Circuit { + /// Circuit-specific codegen input (e.g. preset + public key). type Input; + /// Error type for codegen failures. type Error; - /// Generate artifacts for a circuit. + /// Produces [`Artifacts`] for this circuit from the given input. fn codegen(&self, input: Self::Input) -> Result; } +/// Writes the Prover TOML string to `path/Prover.toml`, or `./Prover.toml` if `path` is `None`. pub fn write_toml(toml: &Toml, path: Option<&Path>) -> Result<(), CircuitsErrors> { let toml_path = path.unwrap_or_else(|| Path::new(".")); let toml_path = toml_path.join("Prover.toml"); Ok(std::fs::write(toml_path, toml)?) } +/// Writes the Noir configs string to `path/configs.nr`, or `./configs.nr` if `path` is `None`. pub fn write_configs(configs: &Configs, path: Option<&Path>) -> Result<(), CircuitsErrors> { let configs_path = path.unwrap_or_else(|| Path::new(".")); let configs_path = configs_path.join("configs.nr"); Ok(std::fs::write(configs_path, configs)?) } +/// Writes both Prover.toml and configs.nr into the given directory (or current directory if `None`). pub fn write_artifacts( toml: &Toml, configs: &Configs, path: Option<&Path>, ) -> Result<(), CircuitsErrors> { - write_toml(&toml, path)?; - write_configs(&configs, path)?; + write_toml(toml, path)?; + write_configs(configs, path)?; Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + use tempfile::TempDir; + + #[test] + fn write_toml_creates_prover_toml_in_path() { + let toml_content = r#"[section] +key = "value" +"#; + let temp = TempDir::new().unwrap(); + write_toml(&toml_content.to_string(), Some(temp.path())).unwrap(); + let path = temp.path().join("Prover.toml"); + assert!(path.exists()); + let read = std::fs::read_to_string(&path).unwrap(); + assert_eq!(read, toml_content); + } + + #[test] + fn write_configs_creates_configs_nr_in_path() { + let configs_content = "pub global N: u32 = 1024;\n"; + let temp = TempDir::new().unwrap(); + write_configs(&configs_content.to_string(), Some(temp.path())).unwrap(); + let path = temp.path().join("configs.nr"); + assert!(path.exists()); + let read = std::fs::read_to_string(&path).unwrap(); + assert_eq!(read, configs_content); + } + + #[test] + fn write_artifacts_creates_both_files() { + let toml_content = "[section]\nkey = \"value\"\n"; + let configs_content = "pub global N: u32 = 1024;\n"; + let temp = TempDir::new().unwrap(); + write_artifacts( + &toml_content.to_string(), + &configs_content.to_string(), + Some(temp.path()), + ) + .unwrap(); + let toml_path = temp.path().join("Prover.toml"); + let configs_path = temp.path().join("configs.nr"); + assert!(toml_path.exists()); + assert!(configs_path.exists()); + assert_eq!(std::fs::read_to_string(&toml_path).unwrap(), toml_content); + assert_eq!( + std::fs::read_to_string(&configs_path).unwrap(), + configs_content + ); + } +} diff --git a/crates/zk-helpers/src/circuits/computation.rs b/crates/zk-helpers/src/circuits/computation.rs index 54823c2606..93d73dce23 100644 --- a/crates/zk-helpers/src/circuits/computation.rs +++ b/crates/zk-helpers/src/circuits/computation.rs @@ -4,28 +4,35 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -/// TOML file for the circuit. +//! Computation traits and artifact types. +//! +//! [`Computation`] is a generic trait for computing values from parameters and input. +//! [`CircuitComputation`] extends it for circuits that produce witness/bounds/bits. +//! [`Toml`] and [`Configs`] are the string types used for Prover.toml and configs.nr. + +/// Prover TOML file content (witness and circuit inputs). pub type Toml = String; -/// Configs file for the circuit. +/// Noir configs file content (global constants for the prover). pub type Configs = String; -/// Trait for computation. +/// Generic computation from parameters and input to a result. pub trait Computation: Sized { type Params; type Input; type Error; + /// Computes the result from parameters and input. fn compute(params: &Self::Params, input: &Self::Input) -> Result; } -/// Trait for circuit computation. +/// Circuit-specific computation: parameters and input produce bounds, bits, witness, etc. pub trait CircuitComputation: crate::registry::Circuit { type Params; type Input; type Output; type Error; - /// Compute circuit-specific data. + /// Computes circuit-specific data (bounds, bits, witness) from parameters and input. fn compute( &self, params: &Self::Params, @@ -33,12 +40,12 @@ pub trait CircuitComputation: crate::registry::Circuit { ) -> Result; } -/// Trait for converting to JSON. +/// Converts a value to a JSON [`serde_json::Value`] for serialization. pub trait ConvertToJson { fn convert_to_json(&self) -> serde_json::Result; } -/// Trait for reducing to ZKP modulus. +/// Reduces coefficients (or similar) to the ZKP field modulus for use in the prover. pub trait ReduceToZkpModulus: Sized { fn reduce_to_zkp_modulus(&self) -> Self; } diff --git a/crates/zk-helpers/src/circuits/errors.rs b/crates/zk-helpers/src/circuits/errors.rs index a56b7f7513..da45852c57 100644 --- a/crates/zk-helpers/src/circuits/errors.rs +++ b/crates/zk-helpers/src/circuits/errors.rs @@ -4,9 +4,12 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +//! Error types for circuit and codegen operations. + use crate::utils::ZkHelpersUtilsError; use thiserror::Error; +/// Errors that can occur during circuit codegen or artifact I/O. #[derive(Error, Debug)] pub enum CircuitsErrors { #[error("I/O error: {0}")] diff --git a/crates/zk-helpers/src/circuits/mod.rs b/crates/zk-helpers/src/circuits/mod.rs index 3c5e7b5c9c..85de2dd142 100644 --- a/crates/zk-helpers/src/circuits/mod.rs +++ b/crates/zk-helpers/src/circuits/mod.rs @@ -4,6 +4,13 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +//! Zero-knowledge circuit types and code generation. +//! +//! This module provides circuit metadata ([`Circuit`](crate::registry::Circuit)), artifact +//! codegen ([`CircuitCodegen`], [`Artifacts`]), commitment helpers ([`commitments`]), +//! and sample data generation ([`Sample`]). The `pk_bfv` submodule implements the +//! public-key BFV commitment circuit. + pub mod codegen; pub mod commitments; pub mod computation; diff --git a/crates/zk-helpers/src/circuits/pk_bfv/circuit.rs b/crates/zk-helpers/src/circuits/pk_bfv/circuit.rs index 89bb1af770..d2e19af21f 100644 --- a/crates/zk-helpers/src/circuits/pk_bfv/circuit.rs +++ b/crates/zk-helpers/src/circuits/pk_bfv/circuit.rs @@ -4,6 +4,8 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +//! Public-key BFV circuit type and implementations of [`Circuit`], [`CircuitCodegen`], [`CircuitComputation`]. + use crate::circuits::pk_bfv::codegen; use crate::circuits::pk_bfv::computation::{Bits, Bounds, Witness}; use crate::codegen::Artifacts; @@ -16,19 +18,28 @@ use crate::registry::DkgInputType; use e3_fhe_params::{BfvPreset, ParameterType}; use fhe::bfv::{BfvParameters, PublicKey}; +/// Public-key BFV commitment circuit (name: `pk-bfv`). +/// Proves knowledge of a BFV public key; used for DKG parameter type. #[derive(Debug)] pub struct PkBfvCircuit; +/// Output of [`CircuitComputation::compute`] for [`PkBfvCircuit`]: bounds, bit widths, and witness. #[derive(Debug)] pub struct PkBfvComputationOutput { + /// Coefficient bounds for public key polynomials. pub bounds: Bounds, + /// Bit widths for the prover (e.g. pk_bit). pub bits: Bits, + /// Witness data (pk0is, pk1is) for the Noir prover. pub witness: Witness, } +/// Input for [`CircuitCodegen::codegen`] for [`PkBfvCircuit`]: BFV preset and public key. #[derive(Debug, Clone)] pub struct PkBfvCodegenInput { + /// BFV parameter preset (e.g. default). pub preset: BfvPreset, + /// BFV public key to commit to. pub public_key: PublicKey, } diff --git a/crates/zk-helpers/src/circuits/pk_bfv/codegen.rs b/crates/zk-helpers/src/circuits/pk_bfv/codegen.rs index 6573a9ef86..51ffb94640 100644 --- a/crates/zk-helpers/src/circuits/pk_bfv/codegen.rs +++ b/crates/zk-helpers/src/circuits/pk_bfv/codegen.rs @@ -4,6 +4,8 @@ // 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 crate::circuits::pk_bfv::circuit::PkBfvCircuit; use crate::circuits::pk_bfv::computation::{Bits, Bounds, Witness}; use crate::codegen::Artifacts; @@ -22,12 +24,16 @@ use serde::{Deserialize, Serialize}; use serde_json; use std::sync::Arc; +/// JSON-serializable structure for Prover.toml (pk0is, pk1is arrays). #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TomlJson { + /// First component of the public key per modulus (for the prover). pub pk0is: Vec, + /// Second component of the public key per modulus (for the prover). pub pk1is: Vec, } +/// Builds the Prover TOML string from the pk-bfv witness (pk0is, pk1is). pub fn generate_toml(witness: Witness) -> Result { let pk0is = map_witness_2d_vector_to_json(&witness.pk0is); let pk1is = map_witness_2d_vector_to_json(&witness.pk1is); @@ -36,6 +42,7 @@ pub fn generate_toml(witness: Witness) -> Result { Ok(toml::to_string(&toml_json)?) } +/// Generates full artifacts (Prover.toml and configs.nr) for the pk-bfv circuit from a preset and public key. pub fn codegen(preset: BfvPreset, public_key: PublicKey) -> Result { let params = BfvParamSet::from(preset).build_arc(); // Compute. @@ -50,6 +57,7 @@ pub fn codegen(preset: BfvPreset, public_key: PublicKey) -> Result, bits: &Bits) -> Configs { format!( r#"// Global configs for Public Key BFV circuit diff --git a/crates/zk-helpers/src/circuits/pk_bfv/computation.rs b/crates/zk-helpers/src/circuits/pk_bfv/computation.rs index 1a4e834235..f45c6cbbe5 100644 --- a/crates/zk-helpers/src/circuits/pk_bfv/computation.rs +++ b/crates/zk-helpers/src/circuits/pk_bfv/computation.rs @@ -4,6 +4,11 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +//! Computation types for the pk-bfv circuit: constants, bounds, bit widths, and witness. +//! +//! [`Constants`], [`Bounds`], [`Bits`], and [`Witness`] are produced from BFV parameters +//! and (for witness) a public key. They implement [`Computation`] and are used by codegen. + use crate::computation::Computation; use crate::computation::ConvertToJson; use crate::computation::ReduceToZkpModulus; @@ -20,28 +25,37 @@ use num_bigint::BigUint; use rayon::prelude::*; use serde::{Deserialize, Serialize}; +/// BFV parameters extracted for the circuit: degree, number of moduli, and modulus values. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Constants { + /// Polynomial degree (N). pub n: usize, + /// Number of CRT moduli (L). pub l: usize, + /// CRT moduli q_i. pub moduli: Vec, } +/// Bit widths used by the Noir prover (e.g. for packing coefficients). #[derive(Debug, Clone)] pub struct Bits { + /// Bit width for public key coefficients. pub pk_bit: u32, } +/// Coefficient bounds for public key polynomials (used to derive bit widths). #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Bounds { - /// Bound for public key polynomials (pk0, pk1) + /// Bound for public key polynomials (pk0, pk1). pub pk_bound: BigUint, } +/// Witness data for the pk-bfv circuit: public key polynomials in CRT form for the prover. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Witness { - /// Public key polynomials (pk0, pk1) for each CRT basis. + /// First component of the public key per modulus (coefficients as BigInt). pub pk0is: Vec>, + /// Second component of the public key per modulus (coefficients as BigInt). pub pk1is: Vec>, } diff --git a/crates/zk-helpers/src/circuits/pk_bfv/mod.rs b/crates/zk-helpers/src/circuits/pk_bfv/mod.rs index caff0b46d5..607b722b93 100644 --- a/crates/zk-helpers/src/circuits/pk_bfv/mod.rs +++ b/crates/zk-helpers/src/circuits/pk_bfv/mod.rs @@ -4,6 +4,12 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +//! Public-key BFV commitment circuit. +//! +//! This circuit proves knowledge of a BFV public key (pk0, pk1) and produces +//! Prover.toml and configs.nr for the Noir prover. See [`PkBfvCircuit`] and +//! [`PkBfvCodegenInput`]. + pub mod circuit; pub mod codegen; pub mod computation; diff --git a/crates/zk-helpers/src/circuits/sample.rs b/crates/zk-helpers/src/circuits/sample.rs index ec3d733e5a..be3bfc4ff1 100644 --- a/crates/zk-helpers/src/circuits/sample.rs +++ b/crates/zk-helpers/src/circuits/sample.rs @@ -4,16 +4,24 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +//! Sample data generation for circuits. +//! +//! [`Sample`] produces a random BFV key pair; the public key is used as input +//! for codegen and tests (e.g. pk-bfv circuit). + use fhe::bfv::{BfvParameters, PublicKey, SecretKey}; use rand::thread_rng; use std::sync::Arc; +/// A sample BFV public key (and optionally related data) for circuit codegen or tests. #[derive(Debug, Clone)] pub struct Sample { + /// Randomly generated BFV public key. pub public_key: PublicKey, } impl Sample { + /// Generates a random secret key and public key for the given BFV parameters. pub fn generate(params: &Arc) -> Self { let mut rng = thread_rng(); diff --git a/crates/zk-helpers/src/registry/mod.rs b/crates/zk-helpers/src/registry/mod.rs index 99b9c9613a..02e9b54a4c 100644 --- a/crates/zk-helpers/src/registry/mod.rs +++ b/crates/zk-helpers/src/registry/mod.rs @@ -4,6 +4,11 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +//! Circuit registry and metadata. +//! +//! The registry maps circuit names (e.g. `pk-bfv`) to [`CircuitMetadata`]. Use +//! [`CircuitRegistry`] to register and look up circuits by name. + pub mod registry; pub use registry::*; From 0a420b4c7224a1eb191602b1271b939da106b6b3 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 3 Feb 2026 11:35:20 +0100 Subject: [PATCH 05/10] remove unused types and pvss term --- circuits/lib/Nargo.toml | 2 +- crates/zk-helpers/src/types.rs | 53 ---------------------------------- 2 files changed, 1 insertion(+), 54 deletions(-) delete mode 100644 crates/zk-helpers/src/types.rs diff --git a/circuits/lib/Nargo.toml b/circuits/lib/Nargo.toml index 5602a4b52b..aafc1d80ce 100644 --- a/circuits/lib/Nargo.toml +++ b/circuits/lib/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "pvss_lib" +name = "lib" type = "lib" authors = ["Gnosis Guild / Enclave"] version = "1.0.0-beta.15" diff --git a/crates/zk-helpers/src/types.rs b/crates/zk-helpers/src/types.rs deleted file mode 100644 index c397e51721..0000000000 --- a/crates/zk-helpers/src/types.rs +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -/// @todo this must be integrated inside Ciphernodes & Smart Contract -/// instead of being a separate type in here. The pvss crate should import this and -/// the default values that must be used and shared among the whole enclave repository. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum CiphernodesCommitteeSize { - /// Small committee size (fast local/testing). - Small, - /// Medium committee size (default). - Medium, - /// Large committee size (higher assurance). - Large, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct CiphernodesCommittee { - /// Total number of parties (N_PARTIES). - n: usize, - /// Number of honest parties (H). - h: usize, - /// Threshold value (T). - threshold: usize, -} - -impl CiphernodesCommitteeSize { - /// Returns `(num_parties, num_honest_parties, threshold)` for this size. - pub fn values(self) -> CiphernodesCommittee { - match self { - CiphernodesCommitteeSize::Small => CiphernodesCommittee { - n: 5, - h: 3, - threshold: 2, - }, - _ => unreachable!(), - } - // @todo add the other committee sizes - // CiphernodesCommitteeSize::Medium => CiphernodesCommittee { - // n: 5, - // h: 3, - // threshold: 2, - // }, - // CiphernodesCommitteeSize::Large => CiphernodesCommittee { - // n: 5, - // h: 3, - // threshold: 2, - // }, - } -} From 3afc52297c5f94dab3ae69bf38dfce04f0676023 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 3 Feb 2026 12:26:59 +0100 Subject: [PATCH 06/10] complete ref of traits and circuit --- crates/zk-helpers/README.md | 26 ++++++ crates/zk-helpers/src/bin/zk_cli.rs | 30 ++++--- crates/zk-helpers/src/circuits/codegen.rs | 16 ++-- crates/zk-helpers/src/circuits/computation.rs | 9 ++ crates/zk-helpers/src/circuits/mod.rs | 14 +-- .../zk-helpers/src/circuits/pk_bfv/circuit.rs | 72 ++-------------- .../zk-helpers/src/circuits/pk_bfv/codegen.rs | 65 +++++++++----- .../src/circuits/pk_bfv/computation.rs | 86 +++++++++++++++---- crates/zk-helpers/src/circuits/pk_bfv/mod.rs | 1 - crates/zk-helpers/src/registry/registry.rs | 52 +---------- 10 files changed, 191 insertions(+), 180 deletions(-) create mode 100644 crates/zk-helpers/README.md diff --git a/crates/zk-helpers/README.md b/crates/zk-helpers/README.md new file mode 100644 index 0000000000..b34559a6ac --- /dev/null +++ b/crates/zk-helpers/README.md @@ -0,0 +1,26 @@ +# zk-helpers + +ZK circuit artifact generation for the Noir prover. + +## zk-cli + +Generate `Prover.toml` and `configs.nr` for a circuit. + +```bash +# List circuits +cargo run -p e3-zk-helpers --bin zk_cli -- --list_circuits + +# Generate artifacts (default: output/) +cargo run -p e3-zk-helpers --bin zk_cli -- --circuit pk-bfv --preset default + +# Custom output dir; skip Prover.toml (only configs.nr) +cargo run -p e3-zk-helpers --bin zk_cli -- --circuit pk-bfv --preset default --output ./artifacts --toml +``` + +| Flag | Description | +| ------------------ | -------------------------------------------------- | +| `--list_circuits` | List circuits and exit | +| `--circuit ` | Circuit (e.g. `pk-bfv`) | +| `--preset ` | BFV preset (must match circuit) | +| `--output ` | Output dir (default: `output`) | +| `--toml` | Skip writing Prover.toml; always writes configs.nr | diff --git a/crates/zk-helpers/src/bin/zk_cli.rs b/crates/zk-helpers/src/bin/zk_cli.rs index 7da65f45e7..b22e8473a9 100644 --- a/crates/zk-helpers/src/bin/zk_cli.rs +++ b/crates/zk-helpers/src/bin/zk_cli.rs @@ -13,7 +13,7 @@ use anyhow::{anyhow, Context, Result}; use clap::{arg, command, Parser}; use e3_fhe_params::{BfvParamSet, BfvPreset}; -use e3_zk_helpers::circuits::pk_bfv::circuit::{PkBfvCircuit, PkBfvCodegenInput}; +use e3_zk_helpers::circuits::pk_bfv::circuit::{PkBfvCircuit, PkBfvCircuitInput}; use e3_zk_helpers::codegen::{write_artifacts, CircuitCodegen}; use e3_zk_helpers::registry::{Circuit, CircuitRegistry}; use e3_zk_helpers::sample::Sample; @@ -36,6 +36,9 @@ struct Cli { /// Output directory for generated artifacts. #[arg(long, default_value = "output")] output: PathBuf, + /// Skip generating Prover.toml (configs.nr is always generated). + #[arg(long)] + toml: bool, } /// Parses a preset name (e.g. `"default"`) into a [`BfvPreset`]. @@ -61,11 +64,9 @@ fn main() -> Result<()> { for circuit_name in circuits { if let Ok(circuit_meta) = registry.get(&circuit_name) { println!( - " {} - params_type: {:?}, n_recursive_proofs: {}, pub_inputs: {}", + " {} - params_type: {:?}", circuit_name, circuit_meta.supported_parameter(), - circuit_meta.n_recursive_proofs(), - circuit_meta.n_public_inputs() ); } } @@ -104,19 +105,22 @@ fn main() -> Result<()> { let artifacts = match circuit_name { name if name == ::NAME => { let circuit = PkBfvCircuit; - circuit.codegen(PkBfvCodegenInput { - preset, - public_key: sample.public_key, - })? + circuit.codegen( + ¶ms, + &PkBfvCircuitInput { + public_key: sample.public_key, + }, + )? } name => return Err(anyhow!("circuit {} not yet implemented", name)), }; - write_artifacts( - &artifacts.toml, - &artifacts.configs, - Some(args.output.as_path()), - )?; + let toml = if !args.toml { + None + } else { + Some(&artifacts.toml) + }; + write_artifacts(toml, &artifacts.configs, Some(args.output.as_path()))?; println!("Artifacts written to {}", args.output.display()); Ok(()) diff --git a/crates/zk-helpers/src/circuits/codegen.rs b/crates/zk-helpers/src/circuits/codegen.rs index e22b619d7d..fb3844e44d 100644 --- a/crates/zk-helpers/src/circuits/codegen.rs +++ b/crates/zk-helpers/src/circuits/codegen.rs @@ -25,13 +25,16 @@ pub struct Artifacts { /// Trait for circuits that can generate Prover.toml and configs.nr from circuit-specific input. pub trait CircuitCodegen: crate::registry::Circuit { + /// Circuit-specific parameters (e.g. BFV parameters). + type Params; /// Circuit-specific codegen input (e.g. preset + public key). type Input; /// Error type for codegen failures. type Error; /// Produces [`Artifacts`] for this circuit from the given input. - fn codegen(&self, input: Self::Input) -> Result; + fn codegen(&self, params: &Self::Params, input: &Self::Input) + -> Result; } /// Writes the Prover TOML string to `path/Prover.toml`, or `./Prover.toml` if `path` is `None`. @@ -48,13 +51,16 @@ pub fn write_configs(configs: &Configs, path: Option<&Path>) -> Result<(), Circu Ok(std::fs::write(configs_path, configs)?) } -/// Writes both Prover.toml and configs.nr into the given directory (or current directory if `None`). +/// Writes Prover.toml (if `toml` is `Some`) and always configs.nr into the given directory +/// (or current directory if `path` is `None`). pub fn write_artifacts( - toml: &Toml, + toml: Option<&Toml>, configs: &Configs, path: Option<&Path>, ) -> Result<(), CircuitsErrors> { - write_toml(toml, path)?; + if let Some(t) = toml { + write_toml(t, path)?; + } write_configs(configs, path)?; Ok(()) } @@ -94,7 +100,7 @@ key = "value" let configs_content = "pub global N: u32 = 1024;\n"; let temp = TempDir::new().unwrap(); write_artifacts( - &toml_content.to_string(), + Some(&toml_content.to_string()), &configs_content.to_string(), Some(temp.path()), ) diff --git a/crates/zk-helpers/src/circuits/computation.rs b/crates/zk-helpers/src/circuits/computation.rs index 93d73dce23..524892bac8 100644 --- a/crates/zk-helpers/src/circuits/computation.rs +++ b/crates/zk-helpers/src/circuits/computation.rs @@ -10,6 +10,15 @@ //! [`CircuitComputation`] extends it for circuits that produce witness/bounds/bits. //! [`Toml`] and [`Configs`] are the string types used for Prover.toml and configs.nr. +/// Variant for input types for DKG. +#[derive(Clone)] +pub enum DkgInputType { + /// The input type that generates shares of a secret key using secret sharing. + SecretKey, + /// The input type that generates shares of smudging noise instead of secret key shares. + SmudgingNoise, +} + /// Prover TOML file content (witness and circuit inputs). pub type Toml = String; /// Noir configs file content (global constants for the prover). diff --git a/crates/zk-helpers/src/circuits/mod.rs b/crates/zk-helpers/src/circuits/mod.rs index 85de2dd142..1c7e123a1b 100644 --- a/crates/zk-helpers/src/circuits/mod.rs +++ b/crates/zk-helpers/src/circuits/mod.rs @@ -17,11 +17,15 @@ pub mod computation; pub mod errors; pub mod sample; -pub use codegen::*; +pub use codegen::{write_artifacts, Artifacts, CircuitCodegen}; pub use commitments::*; -pub use computation::*; -pub use errors::*; -pub use sample::*; +pub use computation::{ + CircuitComputation, Computation, Configs, ConvertToJson, ReduceToZkpModulus, Toml, +}; +pub use errors::CircuitsErrors; +pub use sample::Sample; pub mod pk_bfv; -pub use pk_bfv::*; +pub use pk_bfv::codegen::{generate_configs, generate_toml, TomlJson}; +pub use pk_bfv::computation::{Bits, Bounds, PkBfvComputationOutput, Witness}; +pub use pk_bfv::PkBfvCircuit; diff --git a/crates/zk-helpers/src/circuits/pk_bfv/circuit.rs b/crates/zk-helpers/src/circuits/pk_bfv/circuit.rs index d2e19af21f..7cd37300fa 100644 --- a/crates/zk-helpers/src/circuits/pk_bfv/circuit.rs +++ b/crates/zk-helpers/src/circuits/pk_bfv/circuit.rs @@ -4,82 +4,22 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. -//! Public-key BFV circuit type and implementations of [`Circuit`], [`CircuitCodegen`], [`CircuitComputation`]. - -use crate::circuits::pk_bfv::codegen; -use crate::circuits::pk_bfv::computation::{Bits, Bounds, Witness}; -use crate::codegen::Artifacts; -use crate::codegen::CircuitCodegen; -use crate::computation::CircuitComputation; -use crate::computation::Computation; -use crate::errors::CircuitsErrors; +use crate::computation::DkgInputType; use crate::registry::Circuit; -use crate::registry::DkgInputType; -use e3_fhe_params::{BfvPreset, ParameterType}; -use fhe::bfv::{BfvParameters, PublicKey}; +use e3_fhe_params::ParameterType; +use fhe::bfv::PublicKey; -/// Public-key BFV commitment circuit (name: `pk-bfv`). -/// Proves knowledge of a BFV public key; used for DKG parameter type. #[derive(Debug)] pub struct PkBfvCircuit; -/// Output of [`CircuitComputation::compute`] for [`PkBfvCircuit`]: bounds, bit widths, and witness. -#[derive(Debug)] -pub struct PkBfvComputationOutput { - /// Coefficient bounds for public key polynomials. - pub bounds: Bounds, - /// Bit widths for the prover (e.g. pk_bit). - pub bits: Bits, - /// Witness data (pk0is, pk1is) for the Noir prover. - pub witness: Witness, -} - -/// Input for [`CircuitCodegen::codegen`] for [`PkBfvCircuit`]: BFV preset and public key. -#[derive(Debug, Clone)] -pub struct PkBfvCodegenInput { - /// BFV parameter preset (e.g. default). - pub preset: BfvPreset, - /// BFV public key to commit to. - pub public_key: PublicKey, -} - impl Circuit for PkBfvCircuit { const NAME: &'static str = "pk-bfv"; const PREFIX: &'static str = "PK_BFV"; const SUPPORTED_PARAMETER: ParameterType = ParameterType::DKG; const DKG_INPUT_TYPE: Option = None; - const N_PROOFS: usize = 1; - const N_PUBLIC_INPUTS: usize = 1; } -impl CircuitCodegen for PkBfvCircuit { - type Input = PkBfvCodegenInput; - type Error = CircuitsErrors; - - fn codegen(&self, input: Self::Input) -> Result { - codegen::codegen(input.preset, input.public_key) - } -} - -impl CircuitComputation for PkBfvCircuit { - type Params = BfvParameters; - type Input = PublicKey; - type Output = PkBfvComputationOutput; - type Error = CircuitsErrors; - - fn compute( - &self, - params: &Self::Params, - input: &Self::Input, - ) -> Result { - let bounds = Bounds::compute(params, &())?; - let bits = Bits::compute(params, &bounds)?; - let witness = Witness::compute(params, input)?; - - Ok(PkBfvComputationOutput { - bounds, - bits, - witness, - }) - } +pub struct PkBfvCircuitInput { + /// BFV public key. + pub public_key: PublicKey, } diff --git a/crates/zk-helpers/src/circuits/pk_bfv/codegen.rs b/crates/zk-helpers/src/circuits/pk_bfv/codegen.rs index 51ffb94640..d6402e3501 100644 --- a/crates/zk-helpers/src/circuits/pk_bfv/codegen.rs +++ b/crates/zk-helpers/src/circuits/pk_bfv/codegen.rs @@ -6,9 +6,11 @@ //! Code generation for the public-key BFV circuit: Prover.toml and configs.nr. -use crate::circuits::pk_bfv::circuit::PkBfvCircuit; +use crate::circuits::pk_bfv::circuit::PkBfvCircuitInput; use crate::circuits::pk_bfv::computation::{Bits, Bounds, Witness}; +use crate::circuits::PkBfvCircuit; use crate::codegen::Artifacts; +use crate::codegen::CircuitCodegen; use crate::computation::Computation; use crate::computation::Configs; use crate::computation::ReduceToZkpModulus; @@ -16,14 +18,35 @@ use crate::computation::Toml; use crate::errors::CircuitsErrors; use crate::registry::Circuit; use crate::utils::map_witness_2d_vector_to_json; -use e3_fhe_params::BfvParamSet; -use e3_fhe_params::BfvPreset; use fhe::bfv::BfvParameters; -use fhe::bfv::PublicKey; use serde::{Deserialize, Serialize}; use serde_json; use std::sync::Arc; +/// Implementation of [`CircuitCodegen`] for [`PkBfvCircuit`]. +impl CircuitCodegen for PkBfvCircuit { + type Params = Arc; + type Input = PkBfvCircuitInput; + type Error = CircuitsErrors; + + fn codegen( + &self, + params: &Self::Params, + input: &Self::Input, + ) -> Result { + // Compute. + let bounds = Bounds::compute(¶ms, &())?; + let bits = Bits::compute(¶ms, &bounds)?; + let witness = Witness::compute(¶ms, input)?; + let zkp_witness = witness.reduce_to_zkp_modulus(); + + let toml = generate_toml(zkp_witness)?; + let configs = generate_configs(¶ms, &bits); + + Ok(Artifacts { toml, configs }) + } +} + /// JSON-serializable structure for Prover.toml (pk0is, pk1is arrays). #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TomlJson { @@ -42,21 +65,6 @@ pub fn generate_toml(witness: Witness) -> Result { Ok(toml::to_string(&toml_json)?) } -/// Generates full artifacts (Prover.toml and configs.nr) for the pk-bfv circuit from a preset and public key. -pub fn codegen(preset: BfvPreset, public_key: PublicKey) -> Result { - let params = BfvParamSet::from(preset).build_arc(); - // Compute. - let bounds = Bounds::compute(¶ms, &())?; - let bits = Bits::compute(¶ms, &bounds)?; - let witness = Witness::compute(¶ms, &public_key)?; - let zkp_witness = witness.reduce_to_zkp_modulus(); - - let toml = generate_toml(zkp_witness)?; - let configs = generate_configs(¶ms, &bits); - - Ok(Artifacts { toml, configs }) -} - /// Builds the configs.nr string (N, L, bit parameters) for the Noir prover. pub fn generate_configs(params: &Arc, bits: &Bits) -> Configs { format!( @@ -91,10 +99,16 @@ mod tests { #[test] fn test_toml_generation_and_structure() { - let preset = DEFAULT_BFV_PRESET; - let params = BfvParamSet::from(preset).build_arc(); + let params = BfvParamSet::from(DEFAULT_BFV_PRESET).build_arc(); let sample = Sample::generate(¶ms); - let artifacts = codegen(preset, sample.public_key).unwrap(); + let artifacts = PkBfvCircuit + .codegen( + ¶ms, + &PkBfvCircuitInput { + public_key: sample.public_key, + }, + ) + .unwrap(); let parsed: toml::Value = artifacts.toml.parse().unwrap(); let pk0is = parsed @@ -109,7 +123,12 @@ mod tests { assert!(!pk1is.is_empty()); let temp_dir = TempDir::new().unwrap(); - write_artifacts(&artifacts.toml, &artifacts.configs, Some(temp_dir.path())).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()); diff --git a/crates/zk-helpers/src/circuits/pk_bfv/computation.rs b/crates/zk-helpers/src/circuits/pk_bfv/computation.rs index f45c6cbbe5..5dffbfec2c 100644 --- a/crates/zk-helpers/src/circuits/pk_bfv/computation.rs +++ b/crates/zk-helpers/src/circuits/pk_bfv/computation.rs @@ -9,15 +9,18 @@ //! [`Constants`], [`Bounds`], [`Bits`], and [`Witness`] are produced from BFV parameters //! and (for witness) a public key. They implement [`Computation`] and are used by codegen. +use crate::circuits::pk_bfv::circuit::PkBfvCircuitInput; +use crate::computation::CircuitComputation; use crate::computation::Computation; use crate::computation::ConvertToJson; use crate::computation::ReduceToZkpModulus; +use crate::errors::CircuitsErrors; use crate::utils::calculate_bit_width; use crate::utils::get_zkp_modulus; +use crate::PkBfvCircuit; use e3_polynomial::center_coefficients_mut; use e3_polynomial::reduce_coefficients_2d; use fhe::bfv::BfvParameters; -use fhe::bfv::PublicKey; use fhe_math::rq::Representation; use itertools::izip; use num_bigint::BigInt; @@ -25,26 +28,65 @@ use num_bigint::BigUint; use rayon::prelude::*; use serde::{Deserialize, Serialize}; +/// Output of [`CircuitComputation::compute`] for [`PkBfvCircuit`]: bounds, bit widths, and witness. +#[derive(Debug)] +pub struct PkBfvComputationOutput { + /// Coefficient bounds for public key polynomials. + pub bounds: Bounds, + /// Bit widths for the prover (e.g. pk_bit). + pub bits: Bits, + /// Witness data (pk0is, pk1is) for the Noir prover. + pub witness: Witness, +} + +/// Implementation of [`CircuitComputation`] for [`PkBfvCircuit`]. +impl CircuitComputation for PkBfvCircuit { + type Params = BfvParameters; + type Input = PkBfvCircuitInput; + type Output = PkBfvComputationOutput; + type Error = CircuitsErrors; + + fn compute( + &self, + params: &Self::Params, + input: &Self::Input, + ) -> Result { + let bounds = Bounds::compute(params, &())?; + let bits = Bits::compute(params, &bounds)?; + let witness = Witness::compute(params, input)?; + + Ok(PkBfvComputationOutput { + bounds, + bits, + witness, + }) + } +} + /// BFV parameters extracted for the circuit: degree, number of moduli, and modulus values. #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Constants { +pub struct Configs { /// Polynomial degree (N). pub n: usize, /// Number of CRT moduli (L). pub l: usize, /// CRT moduli q_i. pub moduli: Vec, + /// Bits. + pub bits: Bits, + /// Bounds. + pub bounds: Bounds, } /// Bit widths used by the Noir prover (e.g. for packing coefficients). -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Bits { /// Bit width for public key coefficients. pub pk_bit: u32, } /// Coefficient bounds for public key polynomials (used to derive bit widths). -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Bounds { /// Bound for public key polynomials (pk0, pk1). pub pk_bound: BigUint, @@ -59,18 +101,22 @@ pub struct Witness { pub pk1is: Vec>, } -impl Computation for Constants { +impl Computation for Configs { type Params = BfvParameters; type Input = (); - type Error = std::convert::Infallible; + type Error = CircuitsErrors; - fn compute(params: &Self::Params, _: &Self::Input) -> Result { + fn compute(params: &Self::Params, _: &Self::Input) -> Result { let moduli = params.moduli().to_vec(); + let bounds = Bounds::compute(¶ms, &())?; + let bits = Bits::compute(¶ms, &bounds)?; - Ok(Constants { + Ok(Configs { n: params.degree(), l: moduli.len(), moduli, + bits, + bounds, }) } } @@ -111,16 +157,16 @@ impl Computation for Bounds { impl Computation for Witness { type Params = BfvParameters; - type Input = PublicKey; + type Input = PkBfvCircuitInput; type Error = fhe::Error; - fn compute(params: &Self::Params, public_key: &Self::Input) -> Result { + fn compute(params: &Self::Params, input: &Self::Input) -> Result { let moduli = params.moduli(); // Extract public key components (pk0, pk1) from the ciphertext structure // and change representation to Power Basis. - let mut pk0 = public_key.c.c[0].clone(); - let mut pk1 = public_key.c.c[1].clone(); + let mut pk0 = input.public_key.c.c[0].clone(); + let mut pk1 = input.public_key.c.c[1].clone(); pk0.change_representation(Representation::PowerBasis); pk1.change_representation(Representation::PowerBasis); @@ -153,7 +199,7 @@ impl Computation for Witness { } } -impl ConvertToJson for Constants { +impl ConvertToJson for Configs { fn convert_to_json(&self) -> serde_json::Result { serde_json::to_value(self) } @@ -204,7 +250,13 @@ mod tests { fn test_witness_reduction_and_json_roundtrip() { let params = BfvParamSet::from(DEFAULT_BFV_PRESET).build_arc(); let encryption_data = Sample::generate(¶ms); - let witness = Witness::compute(¶ms, &encryption_data.public_key).unwrap(); + let witness = Witness::compute( + ¶ms, + &PkBfvCircuitInput { + public_key: encryption_data.public_key, + }, + ) + .unwrap(); let zkp_reduced = witness.reduce_to_zkp_modulus(); let json = zkp_reduced.convert_to_json().unwrap(); let decoded: Witness = serde_json::from_value(json.clone()).unwrap(); @@ -216,13 +268,15 @@ mod tests { #[test] fn test_constants_json_roundtrip() { let params = BfvParamSet::from(DEFAULT_BFV_PRESET).build_arc(); - let constants = Constants::compute(¶ms, &()).unwrap(); + let constants = Configs::compute(¶ms, &()).unwrap(); let json = constants.convert_to_json().unwrap(); - let decoded: Constants = serde_json::from_value(json).unwrap(); + let decoded: Configs = serde_json::from_value(json).unwrap(); assert_eq!(decoded.n, constants.n); assert_eq!(decoded.l, constants.l); assert_eq!(decoded.moduli, constants.moduli); + assert_eq!(decoded.bits, constants.bits); + assert_eq!(decoded.bounds, constants.bounds); } } diff --git a/crates/zk-helpers/src/circuits/pk_bfv/mod.rs b/crates/zk-helpers/src/circuits/pk_bfv/mod.rs index 607b722b93..adfe084f06 100644 --- a/crates/zk-helpers/src/circuits/pk_bfv/mod.rs +++ b/crates/zk-helpers/src/circuits/pk_bfv/mod.rs @@ -13,7 +13,6 @@ pub mod circuit; pub mod codegen; pub mod computation; - pub use circuit::*; pub use codegen::*; pub use computation::*; diff --git a/crates/zk-helpers/src/registry/registry.rs b/crates/zk-helpers/src/registry/registry.rs index 41d8af8a37..f99d75bb9a 100644 --- a/crates/zk-helpers/src/registry/registry.rs +++ b/crates/zk-helpers/src/registry/registry.rs @@ -4,6 +4,7 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +use crate::computation::DkgInputType; use e3_fhe_params::ParameterType; use std::collections::HashMap; use std::sync::Arc; @@ -16,23 +17,12 @@ pub enum RegistryError { UnknownCircuit { name: String }, } -/// Variant for input types for DKG. -#[derive(Clone)] -pub enum DkgInputType { - /// The input type that generates shares of a secret key using secret sharing. - SecretKey, - /// The input type that generates shares of smudging noise instead of secret key shares. - SmudgingNoise, -} - /// Trait for circuit metadata. pub trait Circuit: Send + Sync { const NAME: &'static str; const PREFIX: &'static str; const SUPPORTED_PARAMETER: ParameterType; const DKG_INPUT_TYPE: Option; - const N_PROOFS: usize; - const N_PUBLIC_INPUTS: usize; fn name(&self) -> &'static str { Self::NAME @@ -49,22 +39,12 @@ pub trait Circuit: Send + Sync { fn dkg_input_type(&self) -> Option { Self::DKG_INPUT_TYPE } - - fn n_recursive_proofs(&self) -> usize { - Self::N_PROOFS - } - - fn n_public_inputs(&self) -> usize { - Self::N_PUBLIC_INPUTS - } } pub trait CircuitMetadata: Send + Sync { fn name(&self) -> &'static str; fn supported_parameter(&self) -> ParameterType; fn dkg_input_type(&self) -> Option; - fn n_recursive_proofs(&self) -> usize; - fn n_public_inputs(&self) -> usize; } impl CircuitMetadata for T { @@ -79,14 +59,6 @@ impl CircuitMetadata for T { fn dkg_input_type(&self) -> Option { T::DKG_INPUT_TYPE } - - fn n_recursive_proofs(&self) -> usize { - T::N_PROOFS - } - - fn n_public_inputs(&self) -> usize { - T::N_PUBLIC_INPUTS - } } /// Registry for PVSS circuits. @@ -127,18 +99,6 @@ impl CircuitRegistry { Ok(self.get(name)?.dkg_input_type()) } - /// Get number of recursive proofs for a circuit. - /// This is used for determine the number of proofs required for aggregation. - pub fn n_recursive_proofs(&self, name: &str) -> Result { - Ok(self.get(name)?.n_recursive_proofs()) - } - - /// Get number of public inputs for a circuit. - /// This is used for determine the number of public inputs required for aggregation. - pub fn n_public_inputs(&self, name: &str) -> Result { - Ok(self.get(name)?.n_public_inputs()) - } - /// List all registered circuit names. pub fn list_circuits(&self) -> Vec { self.circuits.keys().cloned().collect() @@ -156,8 +116,6 @@ mod tests { const PREFIX: &'static str = "TEST"; const SUPPORTED_PARAMETER: ParameterType = ParameterType::DKG; const DKG_INPUT_TYPE: Option = Some(DkgInputType::SecretKey); - const N_PROOFS: usize = 1; - const N_PUBLIC_INPUTS: usize = 1; } #[test] @@ -180,13 +138,5 @@ mod tests { assert_eq!(circuit.name(), ::NAME); assert_eq!(circuit.supported_parameter(), ParameterType::DKG); assert!(circuit.dkg_input_type().is_some()); - assert_eq!( - circuit.n_recursive_proofs(), - ::N_PROOFS - ); - assert_eq!( - circuit.n_public_inputs(), - ::N_PUBLIC_INPUTS - ); } } From a19251145f8ad1f5709088999ab01a6657f67153 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 3 Feb 2026 12:28:49 +0100 Subject: [PATCH 07/10] coderabbit issues --- crates/zk-helpers/Cargo.toml | 2 ++ crates/zk-helpers/src/registry/registry.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/zk-helpers/Cargo.toml b/crates/zk-helpers/Cargo.toml index 4e37a71efb..bedddc62c6 100644 --- a/crates/zk-helpers/Cargo.toml +++ b/crates/zk-helpers/Cargo.toml @@ -25,6 +25,8 @@ serde = { workspace = true } serde_json = { workspace = true } toml = "0.8.23" itertools = "0.14.0" + +[dev-dependencies] tempfile = { workspace = true } [[bin]] diff --git a/crates/zk-helpers/src/registry/registry.rs b/crates/zk-helpers/src/registry/registry.rs index f99d75bb9a..265ee3005d 100644 --- a/crates/zk-helpers/src/registry/registry.rs +++ b/crates/zk-helpers/src/registry/registry.rs @@ -61,7 +61,7 @@ impl CircuitMetadata for T { } } -/// Registry for PVSS circuits. +/// Registry for ZK circuits. pub struct CircuitRegistry { circuits: HashMap>, } From 4a2102d329e4adc67a23a28e974a7f2f8e06cfe2 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 3 Feb 2026 12:31:37 +0100 Subject: [PATCH 08/10] update lockfiles --- examples/CRISP/Cargo.lock | 1 - templates/default/Cargo.lock | 1 - 2 files changed, 2 deletions(-) diff --git a/examples/CRISP/Cargo.lock b/examples/CRISP/Cargo.lock index 799aede9e3..306cbc5d04 100644 --- a/examples/CRISP/Cargo.lock +++ b/examples/CRISP/Cargo.lock @@ -2584,7 +2584,6 @@ dependencies = [ "rayon", "serde", "serde_json", - "tempfile", "thiserror 1.0.69", "toml", ] diff --git a/templates/default/Cargo.lock b/templates/default/Cargo.lock index cc43dccbf0..b444b796f6 100644 --- a/templates/default/Cargo.lock +++ b/templates/default/Cargo.lock @@ -1421,7 +1421,6 @@ dependencies = [ "rayon", "serde", "serde_json", - "tempfile", "thiserror", "toml", ] From dce2f670e9b6fe68a2f159b8a42142cab9fd7a45 Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 3 Feb 2026 12:46:00 +0100 Subject: [PATCH 09/10] add types for ciphernode committee; fix ci docker --- crates/Dockerfile | 3 -- .../zk-helpers/src/ciphernodes_committee.rs | 53 +++++++++++++++++++ crates/zk-helpers/src/lib.rs | 2 + 3 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 crates/zk-helpers/src/ciphernodes_committee.rs diff --git a/crates/Dockerfile b/crates/Dockerfile index 5904b15eae..25ec9fa622 100644 --- a/crates/Dockerfile +++ b/crates/Dockerfile @@ -96,9 +96,6 @@ RUN for d in ./*/ ; do \ fi \ done -# Stub binary so first build (dependency cache) succeeds -RUN mkdir -p ./fhe-params/src/bin && echo 'fn main() {}' > ./fhe-params/src/bin/search_params.rs - RUN cargo build --locked --release COPY ./crates . diff --git a/crates/zk-helpers/src/ciphernodes_committee.rs b/crates/zk-helpers/src/ciphernodes_committee.rs new file mode 100644 index 0000000000..c397e51721 --- /dev/null +++ b/crates/zk-helpers/src/ciphernodes_committee.rs @@ -0,0 +1,53 @@ +// 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. + +/// @todo this must be integrated inside Ciphernodes & Smart Contract +/// instead of being a separate type in here. The pvss crate should import this and +/// the default values that must be used and shared among the whole enclave repository. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum CiphernodesCommitteeSize { + /// Small committee size (fast local/testing). + Small, + /// Medium committee size (default). + Medium, + /// Large committee size (higher assurance). + Large, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct CiphernodesCommittee { + /// Total number of parties (N_PARTIES). + n: usize, + /// Number of honest parties (H). + h: usize, + /// Threshold value (T). + threshold: usize, +} + +impl CiphernodesCommitteeSize { + /// Returns `(num_parties, num_honest_parties, threshold)` for this size. + pub fn values(self) -> CiphernodesCommittee { + match self { + CiphernodesCommitteeSize::Small => CiphernodesCommittee { + n: 5, + h: 3, + threshold: 2, + }, + _ => unreachable!(), + } + // @todo add the other committee sizes + // CiphernodesCommitteeSize::Medium => CiphernodesCommittee { + // n: 5, + // h: 3, + // threshold: 2, + // }, + // CiphernodesCommitteeSize::Large => CiphernodesCommittee { + // n: 5, + // h: 3, + // threshold: 2, + // }, + } +} diff --git a/crates/zk-helpers/src/lib.rs b/crates/zk-helpers/src/lib.rs index 18ca81bd7e..979ae79c99 100644 --- a/crates/zk-helpers/src/lib.rs +++ b/crates/zk-helpers/src/lib.rs @@ -4,11 +4,13 @@ // without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. +pub mod ciphernodes_committee; pub mod circuits; pub mod packing; pub mod registry; pub mod utils; +pub use ciphernodes_committee::*; pub use circuits::*; pub use packing::*; pub use registry::*; From 3042b9459cd918227c5c143cf375d83b05e95c3e Mon Sep 17 00:00:00 2001 From: 0xjei Date: Tue, 3 Feb 2026 12:55:49 +0100 Subject: [PATCH 10/10] add stubs --- crates/Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/Dockerfile b/crates/Dockerfile index 25ec9fa622..5c4155b3ea 100644 --- a/crates/Dockerfile +++ b/crates/Dockerfile @@ -96,6 +96,10 @@ RUN for d in ./*/ ; do \ fi \ done +# Crates with [[bin]] in Cargo.toml need stub binaries so the first build succeeds +RUN mkdir -p ./zk-helpers/src/bin && echo 'fn main() {}' > ./zk-helpers/src/bin/zk_cli.rs +RUN mkdir -p ./fhe-params/src/bin && echo 'fn main() {}' > ./fhe-params/src/bin/search_params.rs + RUN cargo build --locked --release COPY ./crates .