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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions crates/events/src/enclave_event/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,16 @@ impl Proof {
pub enum CircuitName {
/// BFV public key proof (T0).
PkBfv,
/// TrBFV public key share proof (T1).
/// TrBFV public key share proof (T1a).
PkGeneration,
/// Encrypted shares proof (T2/T3).
EncShares,
/// Sk Share computation proof (T1b).
SkShareComputation,
/// E_SM share computation proof (T1c).
ESmShareComputation,
/// Encrypted sk share proof (T1d).
SkShareEncryption,
/// Encrypted E_SM share proof (T1e).
ESmShareEncryption,
/// Decryption share proof (T4/T5).
DecShares,
/// Public key aggregation proof (T6).
Expand All @@ -53,7 +59,10 @@ impl CircuitName {
match self {
CircuitName::PkBfv => "pk",
CircuitName::PkGeneration => "pk_generation",
CircuitName::EncShares => "enc_shares",
CircuitName::SkShareComputation => "sk_share_computation",
Comment thread
ctrlc03 marked this conversation as resolved.
CircuitName::ESmShareComputation => "e_sm_share_computation",
CircuitName::SkShareEncryption => "sk_share_encryption",
CircuitName::ESmShareEncryption => "e_sm_share_encryption",
CircuitName::DecShares => "dec_shares",
CircuitName::PkAgg => "pk_agg",
}
Expand All @@ -63,7 +72,10 @@ impl CircuitName {
match self {
CircuitName::PkBfv => "dkg",
CircuitName::PkGeneration => "threshold",
CircuitName::EncShares => "threshold",
CircuitName::SkShareComputation => "dkg",
CircuitName::ESmShareComputation => "dkg",
CircuitName::SkShareEncryption => "dkg",
CircuitName::ESmShareEncryption => "dkg",
CircuitName::DecShares => "threshold",
CircuitName::PkAgg => "threshold",
}
Expand Down
10 changes: 5 additions & 5 deletions crates/events/src/enclave_event/signed_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ impl ProofType {
match self {
ProofType::T0PkBfv => CircuitName::PkBfv,
ProofType::T1PkGeneration => CircuitName::PkGeneration,
ProofType::T1SkShareComputation
| ProofType::T1ESmShareComputation
| ProofType::T1SkShareEncryption
| ProofType::T1ESmShareEncryption => CircuitName::EncShares,
ProofType::T1SkShareComputation => CircuitName::SkShareComputation,
ProofType::T1ESmShareComputation => CircuitName::ESmShareComputation,
ProofType::T1SkShareEncryption => CircuitName::SkShareEncryption,
ProofType::T1ESmShareEncryption => CircuitName::ESmShareEncryption,
ProofType::T2SkShareDecryption | ProofType::T2ESmShareDecryption => {
CircuitName::DecShares
}
Expand Down Expand Up @@ -305,7 +305,7 @@ mod tests {
);
assert_eq!(
ProofType::T1SkShareEncryption.circuit_name(),
CircuitName::EncShares
CircuitName::SkShareEncryption
);
assert_eq!(
ProofType::T2SkShareDecryption.circuit_name(),
Expand Down
4 changes: 3 additions & 1 deletion crates/zk-helpers/src/circuits/computation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
//! [`CircuitComputation`] extends it for circuits that produce inputs/bounds/bits.
//! [`Toml`] and [`Configs`] are the string types used for Prover.toml and configs.nr.

use serde::{Deserialize, Serialize};

/// Variant for input types for DKG.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[derive(Clone, Copy, PartialEq, Eq, Debug, Deserialize, Serialize)]
pub enum DkgInputType {
/// The input type that generates shares of a secret key using secret sharing.
SecretKey,
Expand Down
34 changes: 5 additions & 29 deletions crates/zk-helpers/src/circuits/dkg/share_computation/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,9 @@ use crate::circuits::dkg::share_computation::{
};
use crate::circuits::{Artifacts, CircuitCodegen, CircuitsErrors, CodegenToml};
use crate::codegen::CodegenConfigs;
use crate::computation::DkgInputType;
use crate::crt_polynomial_to_toml_json;
use crate::poly_coefficients_to_toml_json;
use crate::registry::Circuit;
use e3_fhe_params::build_pair_for_preset;
use e3_fhe_params::BfvPreset;
use serde_json;

/// Implementation of [`CircuitCodegen`] for [`ShareComputationCircuit`].
impl CircuitCodegen for ShareComputationCircuit {
Expand All @@ -32,7 +28,7 @@ impl CircuitCodegen for ShareComputationCircuit {
let ShareComputationOutput { inputs, bits, .. } =
ShareComputationCircuit::compute(preset, data)?;

let toml = generate_toml(&inputs, data.dkg_input_type.clone())?;
let toml = generate_toml(&inputs)?;
let configs = generate_configs(
preset,
&bits,
Expand All @@ -44,30 +40,10 @@ impl CircuitCodegen for ShareComputationCircuit {
}
}

pub fn generate_toml(
inputs: &Inputs,
dkg_input_type: DkgInputType,
) -> Result<CodegenToml, CircuitsErrors> {
let mut json = inputs.to_json().map_err(|e| CircuitsErrors::SerdeJson(e))?;

let obj = json.as_object_mut().ok_or(CircuitsErrors::Other(
"input json is not an object".to_string(),
))?;

obj.remove("secret_crt");

let (key, value) = match dkg_input_type {
DkgInputType::SecretKey => (
"sk_secret",
poly_coefficients_to_toml_json(inputs.secret_crt.limb(0).coefficients()),
),
DkgInputType::SmudgingNoise => (
"e_sm_secret",
serde_json::Value::Array(crt_polynomial_to_toml_json(&inputs.secret_crt)),
),
};

obj.insert(key.to_string(), value);
pub fn generate_toml(witness: &Inputs) -> Result<CodegenToml, CircuitsErrors> {
let json = witness
.to_json()
.map_err(|e| CircuitsErrors::SerdeJson(e))?;

Ok(toml::to_string(&json)?)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::circuits::commitments::{
use crate::computation::DkgInputType;
use crate::dkg::share_computation::ShareComputationCircuit;
use crate::dkg::share_computation::ShareComputationCircuitData;
use crate::poly_coefficients_to_toml_json;
use crate::CircuitsErrors;
use crate::{bigint_3d_to_json_values, get_zkp_modulus};
use crate::{calculate_bit_width, crt_polynomial_to_toml_json};
Expand Down Expand Up @@ -93,6 +94,8 @@ pub struct Inputs {
pub y: Vec<Vec<Vec<BigInt>>>,
/// Expected secret commitment (matches C1's compute_secret_commitment).
pub expected_secret_commitment: BigInt,
/// Which secret type this witness is for (determines which circuit to run).
pub dkg_input_type: DkgInputType,
Comment thread
ctrlc03 marked this conversation as resolved.
Comment thread
ctrlc03 marked this conversation as resolved.
}

impl Computation for Configs {
Expand Down Expand Up @@ -241,21 +244,33 @@ impl Computation for Inputs {
secret_crt,
y,
expected_secret_commitment,
dkg_input_type: data.dkg_input_type.clone(),
})
}

// Used as input for Nargo execution.
fn to_json(&self) -> serde_json::Result<serde_json::Value> {
let secret_crt = crt_polynomial_to_toml_json(&self.secret_crt);
let y = bigint_3d_to_json_values(&self.y);
let expected_secret_commitment = self.expected_secret_commitment.to_string();

let json = serde_json::json!({
"secret_crt": secret_crt,
let (key, value) = match self.dkg_input_type {
DkgInputType::SecretKey => (
"sk_secret",
poly_coefficients_to_toml_json(self.secret_crt.limb(0).coefficients()),
),
DkgInputType::SmudgingNoise => (
"e_sm_secret",
serde_json::Value::Array(crt_polynomial_to_toml_json(&self.secret_crt)),
),
};

let mut json = serde_json::json!({
"y": y,
"expected_secret_commitment": expected_secret_commitment,
});

json.as_object_mut().unwrap().insert(key.to_string(), value);

Ok(json)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,6 @@ pub struct ShareEncryptionCircuitData {
pub e0_rns: Poly,
/// Encryption error e1 in RNS form.
pub e1_rns: Poly,
/// Type of DKG input (SecretKey or SmudgingNoise) to determine which circuit variant to use.
pub dkg_input_type: DkgInputType,
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl ShareEncryptionCircuitData {
u_rns,
e0_rns,
e1_rns,
dkg_input_type,
})
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/zk-prover/src/circuits/dkg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
// or FITNESS FOR A PARTICULAR PURPOSE

mod pk;
mod share_computation;
mod share_encryption;
38 changes: 38 additions & 0 deletions crates/zk-prover/src/circuits/dkg/share_computation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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::traits::Provable;
use e3_events::CircuitName;
use e3_fhe_params::BfvPreset;
use e3_zk_helpers::computation::DkgInputType;
use e3_zk_helpers::dkg::share_computation::{
Inputs, ShareComputationCircuit, ShareComputationCircuitData,
};
use noirc_abi::InputMap;

impl Provable for ShareComputationCircuit {
type Params = BfvPreset;
type Input = ShareComputationCircuitData;
type Inputs = Inputs;

fn resolve_circuit_name(&self, _input: &Self::Input) -> CircuitName {
match _input.dkg_input_type {
DkgInputType::SecretKey => CircuitName::SkShareComputation,
DkgInputType::SmudgingNoise => CircuitName::ESmShareComputation,
}
}

fn valid_circuits(&self) -> Vec<CircuitName> {
vec![
CircuitName::SkShareComputation,
CircuitName::ESmShareComputation,
]
}

fn circuit(&self) -> CircuitName {
CircuitName::SkShareComputation
}
}
37 changes: 37 additions & 0 deletions crates/zk-prover/src/circuits/dkg/share_encryption.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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::traits::Provable;
use e3_events::CircuitName;
use e3_fhe_params::BfvPreset;
use e3_zk_helpers::computation::DkgInputType;
use e3_zk_helpers::dkg::share_encryption::{
Inputs, ShareEncryptionCircuit, ShareEncryptionCircuitData,
};

impl Provable for ShareEncryptionCircuit {
type Params = BfvPreset;
type Input = ShareEncryptionCircuitData;
type Inputs = Inputs;

fn resolve_circuit_name(&self, _input: &Self::Input) -> CircuitName {
match _input.dkg_input_type {
DkgInputType::SecretKey => CircuitName::SkShareEncryption,
DkgInputType::SmudgingNoise => CircuitName::ESmShareEncryption,
}
}

fn valid_circuits(&self) -> Vec<CircuitName> {
vec![
CircuitName::SkShareEncryption,
CircuitName::ESmShareEncryption,
]
}

fn circuit(&self) -> CircuitName {
CircuitName::SkShareEncryption
}
}
5 changes: 5 additions & 0 deletions crates/zk-prover/src/circuits/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ pub fn inputs_json_to_input_map(json: &serde_json::Value) -> Result<InputMap, Zk
}

fn json_value_to_input_value(v: &serde_json::Value) -> Result<InputValue, ZkError> {
if let Some(s) = v.as_str() {
return FieldElement::try_from_str(s)
.map(InputValue::Field)
.ok_or_else(|| ZkError::SerializationError(format!("invalid field element: {}", s)));
}
if let Some(arr) = v.as_array() {
let items = arr
.iter()
Expand Down
31 changes: 24 additions & 7 deletions crates/zk-prover/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,24 @@ pub trait Provable: Send + Sync {

fn circuit(&self) -> CircuitName;

/// Override this to select a circuit variant based on input.
/// Default just returns the standard circuit name.
fn resolve_circuit_name(&self, _input: &Self::Input) -> CircuitName {
self.circuit()
}

fn valid_circuits(&self) -> Vec<CircuitName> {
vec![self.circuit()]
}

fn build_inputs(&self, params: &Self::Params, input: &Self::Input) -> Result<InputMap, ZkError>
where
Self::Inputs: Computation<Preset = Self::Params, Data = Self::Input> + serde::Serialize,
<Self::Inputs as Computation>::Error: Display,
{
let inputs = Self::Inputs::compute(params.clone(), input)
.map_err(|e| ZkError::InputsGenerationFailed(e.to_string()))?;

let json = inputs
.to_json()
.map_err(|e| ZkError::SerializationError(e.to_string()))?;
Expand All @@ -54,18 +65,18 @@ pub trait Provable: Send + Sync {
{
let inputs = self.build_inputs(params, input)?;

let circuit_name = self.circuit().as_str();
let resolved_name = self.resolve_circuit_name(input);
let circuit_path = prover
.circuits_dir()
.join(self.circuit().dir_path())
.join(format!("{}.json", circuit_name));
.join(resolved_name.dir_path())
.join(format!("{}.json", resolved_name.as_str()));

let circuit = CompiledCircuit::from_file(&circuit_path)?;

let witness_gen = WitnessGenerator::new();
let witness = witness_gen.generate_witness(&circuit, inputs)?;

prover.generate_proof(self.circuit(), &witness, e3_id)
prover.generate_proof(resolved_name, &witness, e3_id)
}

fn verify(
Expand All @@ -75,13 +86,19 @@ pub trait Provable: Send + Sync {
e3_id: &str,
party_id: u64,
) -> Result<bool, ZkError> {
if proof.circuit != self.circuit() {
if !self.valid_circuits().contains(&proof.circuit) {
return Err(ZkError::VerifyFailed(format!(
"circuit mismatch: expected {}, got {}",
self.circuit(),
"circuit mismatch: expected one of {:?}, got {}",
self.valid_circuits(),
proof.circuit
)));
}
Comment thread
ctrlc03 marked this conversation as resolved.

println!(
"Verifying proof for circuit {} with e3_id {} and party_id {}",
proof.circuit, e3_id, party_id
);
println!("Proof details: {:?}", proof);
prover.verify(proof, e3_id, party_id)
}
}
16 changes: 16 additions & 0 deletions crates/zk-prover/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,24 @@

use std::path::PathBuf;

use num_bigint::{BigInt, Sign};

pub fn fixtures_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("fixtures")
}

const FIELD_SIZE: usize = 32;

/// Extract a field element from public signals at the given index (0-based).
pub fn extract_field(signals: &[u8], index: usize) -> BigInt {
let offset = index * FIELD_SIZE;
BigInt::from_bytes_be(Sign::Plus, &signals[offset..offset + FIELD_SIZE])
}

/// Extract a field element from the end of public signals (0 = last, 1 = second to last, etc.)
pub fn extract_field_from_end(signals: &[u8], from_end: usize) -> BigInt {
let total_fields = signals.len() / FIELD_SIZE;
extract_field(signals, total_fields - 1 - from_end)
}
Loading