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
3 changes: 1 addition & 2 deletions circuits/benchmarks/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
"threshold/pk_generation",
"threshold/pk_aggregation",
"threshold/share_decryption",
"threshold/decrypted_shares_aggregation_bn",
"threshold/decrypted_shares_aggregation_mod"
"threshold/decrypted_shares_aggregation"
],
"oracles": ["default"],
"mode": "insecure",
Expand Down
2 changes: 1 addition & 1 deletion circuits/benchmarks/scripts/generate_prover_toml.sh
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ get_zk_args() {
echo "threshold-share-decryption"
return
;;
threshold/decrypted_shares_aggregation_bn|threshold/decrypted_shares_aggregation_mod)
threshold/decrypted_shares_aggregation)
echo "decrypted-shares-aggregation"
return
;;
Expand Down
9 changes: 0 additions & 9 deletions circuits/benchmarks/scripts/run_benchmarks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@ echo " Base Directory: $CIRCUITS_BASE_DIR"
echo " Output Directory: ${OUTPUT_DIR}"
echo ""

# decrypted_shares_aggregation_mod is for insecure only (Q < 128bit); _bn is for secure (large Q)
# Circuit-specific modes come from config.json (e.g. "config" has "modes": ["secure"]); see circuits/benchmarks/config.json
RUN_CIRCUITS=""
CIRCUIT_MODES=$(jq -r '.circuits[] | (if type == "string" then . else .name end) as $path | (if type == "object" and (.modes != null) then (.modes | join(",")) else "insecure,secure" end) | "\($path)\t\(.)"' "$CONFIG_FILE")
Expand All @@ -148,14 +147,6 @@ while IFS= read -r line; do
continue
fi
fi
if [ "$MODE" = "secure" ] && [ "$c" = "threshold/decrypted_shares_aggregation_mod" ]; then
echo " Skipping $c (modular variant is insecure-only, Q < 128bit)"
continue
fi
if [ "$MODE" = "insecure" ] && [ "$c" = "threshold/decrypted_shares_aggregation_bn" ]; then
echo " Skipping $c (BigNum variant is for secure/large Q only)"
continue
fi
RUN_CIRCUITS="${RUN_CIRCUITS} ${c}"
done <<< "$CIRCUIT_MODES"
# When --circuit was given but not in config.json, no line matched; run it anyway if path exists (see note above)
Expand Down
4 changes: 1 addition & 3 deletions circuits/bin/threshold/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,5 @@ members = [
"user_data_encryption_ct0",
"user_data_encryption_ct1",
"share_decryption",
"decrypted_shares_aggregation_bn",
"decrypted_shares_aggregation_mod"

"decrypted_shares_aggregation",
]
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "decrypted_shares_aggregation_bn"
name = "decrypted_shares_aggregation"
type = "bin"
authors = ["Gnosis Guild / Enclave"]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use lib::configs::default::{MAX_MSG_NON_ZERO_COEFFS, T};
use lib::configs::default::threshold::{
DECRYPTED_SHARES_AGGREGATION_BIT_NOISE, DECRYPTED_SHARES_AGGREGATION_CONFIGS, L,
};
use lib::core::threshold::decrypted_shares_aggregation::DecryptedSharesAggregationBigNum;
use lib::core::threshold::decrypted_shares_aggregation::DecryptedSharesAggregation;
use lib::math::polynomial::Polynomial;

fn main(
Expand All @@ -18,7 +18,7 @@ fn main(
u_global: Polynomial<MAX_MSG_NON_ZERO_COEFFS>,
crt_quotients: [Polynomial<MAX_MSG_NON_ZERO_COEFFS>; L],
) {
let decrypted_shares_aggregation: DecryptedSharesAggregationBigNum<MAX_MSG_NON_ZERO_COEFFS, L, T, DECRYPTED_SHARES_AGGREGATION_BIT_NOISE> = DecryptedSharesAggregationBigNum::new(
let decrypted_shares_aggregation: DecryptedSharesAggregation<MAX_MSG_NON_ZERO_COEFFS, L, T, DECRYPTED_SHARES_AGGREGATION_BIT_NOISE> = DecryptedSharesAggregation::new(
DECRYPTED_SHARES_AGGREGATION_CONFIGS,
decryption_shares,
party_ids,
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

131 changes: 5 additions & 126 deletions circuits/lib/src/core/threshold/decrypted_shares_aggregation.nr
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ impl<let L: u32> Configs<L> {
}
}

/// Decrypted Shares Aggregation Circuit (Circuit 7) using BigNum
/// for large Q values.
/// Decrypted Shares Aggregation Circuit (Circuit 7).
/// Uses BigNum for Q values (works for both insecure and secure parameter sets).
///
/// Verifies:
/// 1. Lagrange interpolation to compute u^{(l)} for each CRT basis
/// 2. CRT reconstruction: u^{(l)} + r^{(l)} * q_l = u_global
/// 3. Decoding verification: message = -Q^{-1} * (t * u_global)_Q mod t
pub struct DecryptedSharesAggregationBigNum<let MAX_MSG_NON_ZERO_COEFFS: u32, let L: u32, let T: u32, let BIT_NOISE: u32> {
pub struct DecryptedSharesAggregation<let MAX_MSG_NON_ZERO_COEFFS: u32, let L: u32, let T: u32, let BIT_NOISE: u32> {
/// Circuit parameters including crypto constants
configs: Configs<L>,

Expand All @@ -53,34 +53,8 @@ pub struct DecryptedSharesAggregationBigNum<let MAX_MSG_NON_ZERO_COEFFS: u32, le
/// CRT quotient polynomials (secret witnesses)
crt_quotients: [Polynomial<MAX_MSG_NON_ZERO_COEFFS>; L],
}
/// Decrypted Shares Aggregation Circuit (Circuit 7) using modular arithmetic
///
/// Verifies:
/// 1. Lagrange interpolation to compute u^{(l)} for each CRT basis
/// 2. CRT reconstruction: u^{(l)} + r^{(l)} * q_l = u_global
/// 3. Decoding verification: message = -Q^{-1} * (t * u_global)_Q mod t
pub struct DecryptedSharesAggregationModular<let MAX_MSG_NON_ZERO_COEFFS: u32, let L: u32, let T: u32, let BIT_NOISE: u32> {
/// Circuit parameters including crypto constants
configs: Configs<L>,

/// Decryption shares from t+1 parties (public witnesses)
decryption_shares: [[Polynomial<MAX_MSG_NON_ZERO_COEFFS>; L]; T + 1],

/// Party IDs (x-coordinates) for interpolation (public witnesses)
/// Note: Must be in strictly increasing order for correct Lagrange sign computation
party_ids: [Field; T + 1],

/// Message polynomial m(x) (public witness)
message: Polynomial<MAX_MSG_NON_ZERO_COEFFS>,

/// Global u polynomial (secret witness)
u_global: Polynomial<MAX_MSG_NON_ZERO_COEFFS>,

/// CRT quotient polynomials (secret witnesses)
crt_quotients: [Polynomial<MAX_MSG_NON_ZERO_COEFFS>; L],
}

impl<let MAX_MSG_NON_ZERO_COEFFS: u32, let L: u32, let T: u32, let BIT_NOISE: u32> DecryptedSharesAggregationBigNum<MAX_MSG_NON_ZERO_COEFFS, L, T, BIT_NOISE> {
impl<let MAX_MSG_NON_ZERO_COEFFS: u32, let L: u32, let T: u32, let BIT_NOISE: u32> DecryptedSharesAggregation<MAX_MSG_NON_ZERO_COEFFS, L, T, BIT_NOISE> {
pub fn new(
configs: Configs<L>,
decryption_shares: [[Polynomial<MAX_MSG_NON_ZERO_COEFFS>; L]; T + 1],
Expand All @@ -89,7 +63,7 @@ impl<let MAX_MSG_NON_ZERO_COEFFS: u32, let L: u32, let T: u32, let BIT_NOISE: u3
u_global: Polynomial<MAX_MSG_NON_ZERO_COEFFS>,
crt_quotients: [Polynomial<MAX_MSG_NON_ZERO_COEFFS>; L],
) -> Self {
DecryptedSharesAggregationBigNum {
DecryptedSharesAggregation {
configs,
decryption_shares,
party_ids,
Expand Down Expand Up @@ -178,101 +152,6 @@ impl<let MAX_MSG_NON_ZERO_COEFFS: u32, let L: u32, let T: u32, let BIT_NOISE: u3
}
}

impl<let MAX_MSG_NON_ZERO_COEFFS: u32, let L: u32, let T: u32, let BIT_NOISE: u32> DecryptedSharesAggregationModular<MAX_MSG_NON_ZERO_COEFFS, L, T, BIT_NOISE> {
pub fn new(
configs: Configs<L>,
decryption_shares: [[Polynomial<MAX_MSG_NON_ZERO_COEFFS>; L]; T + 1],
party_ids: [Field; T + 1],
message: Polynomial<MAX_MSG_NON_ZERO_COEFFS>,
u_global: Polynomial<MAX_MSG_NON_ZERO_COEFFS>,
crt_quotients: [Polynomial<MAX_MSG_NON_ZERO_COEFFS>; L],
) -> Self {
DecryptedSharesAggregationModular {
configs,
decryption_shares,
party_ids,
message,
u_global,
crt_quotients,
}
}

/// Alternative verification function using efficient modular arithmetic without BigNum.
///
/// Uses `ModU128` for decoding verification instead of BigNum. More efficient when
/// Q (the product of all CRT moduli) fits within u128 (e.g., 72 bits for insecure parameter sets).
pub fn execute(self) {
// Step 1: Compute Lagrange coefficients in-circuit
let lagrange_coeffs = compute_all_lagrange_coeffs::<T, L>(self.configs.qis, self.party_ids);

// Step 2: Compute u^{(l)} for each CRT basis via Lagrange interpolation
let u_crts = compute_crt_components::<MAX_MSG_NON_ZERO_COEFFS, L, T>(
self.configs.qis,
self.decryption_shares,
lagrange_coeffs,
);

// Step 3: Verify CRT reconstruction: u^{(l)} + r^{(l)} * q_l = u_global
verify_crt_reconstruction::<MAX_MSG_NON_ZERO_COEFFS, L>(
self.configs.qis,
self.u_global,
self.crt_quotients,
u_crts,
);
// Step 4: Verify decoding
self.verify_decoding();
}

/// Alternative decoding verification using the formula:
/// message = -Q^{-1} * (t * u_global)_Q mod t
fn verify_decoding(self) {
let t: Field = self.configs.plaintext_modulus;
// Compute Q as product of all CRT moduli
let mut q_modulus = 1;
for l in 0..L {
q_modulus *= self.configs.qis[l];
}

// For centered arithmetic
let q_half = q_modulus as u128 / 2;

for coeff_idx in 0..MAX_MSG_NON_ZERO_COEFFS {
// Compute (t * u_global) mod Q using BigNum
let q_mod = ModU128::new(q_modulus);
let t_mod = ModU128::new(t);

// Compute (t * u_global) mod Q using modular arithmetic functions
let t_times_u_mod_q = q_mod.mul_mod(t, self.u_global.coefficients[coeff_idx]);
let needs_centering = (t_times_u_mod_q as u128) > q_half;

let computed_message = if needs_centering {
// When (t*u) mod Q >= Q/2: treat as negative in centered form
// Centered value is conceptually negative: (t_times_u_mod_q - Q)
// -Q^{-1} * (negative) = positive result
let centered_positive = q_modulus - t_times_u_mod_q;
let centered_positive_mod_t = t_mod.reduce_mod(centered_positive);

t_mod.mul_mod(self.configs.q_inverse_mod_t, centered_positive_mod_t)
} else {
// When (t*u) mod Q < Q/2: stays positive in centered form
// -Q^{-1} * (positive) = negative result = t - result
let t_times_u_mod_t = t_mod.reduce_mod(t_times_u_mod_q);
let product = t_mod.mul_mod(self.configs.q_inverse_mod_t, t_times_u_mod_t);
if product == 0 {
0
} else {
t - product
}
};

// Verify: only check non-zero coefficients
if self.message.coefficients[coeff_idx] != 0 {
assert(computed_message == self.message.coefficients[coeff_idx]);
}
}
}
}

/// Computes all Lagrange coefficients using optimized modular arithmetic
pub fn compute_all_lagrange_coeffs<let T: u32, let L: u32>(
qis: [Field; L],
Expand Down
12 changes: 4 additions & 8 deletions crates/events/src/enclave_event/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,8 @@ pub enum CircuitName {
PkAggregation,
/// Decryption share proof (C6).
ThresholdShareDecryption,
/// Decrypted shares aggregation proof — BigNum variant (C7a).
DecryptedSharesAggregationBn,
/// Decrypted shares aggregation proof — Modular variant (C7b).
DecryptedSharesAggregationMod,
/// Decrypted shares aggregation proof (C7).
DecryptedSharesAggregation,
/// Recursive aggregation fold circuit (independent; lives at recursive_aggregation/fold).
Fold,
}
Expand All @@ -112,8 +110,7 @@ impl CircuitName {
CircuitName::DkgShareDecryption => "share_decryption",
CircuitName::PkAggregation => "pk_aggregation",
CircuitName::ThresholdShareDecryption => "share_decryption",
CircuitName::DecryptedSharesAggregationBn => "decrypted_shares_aggregation_bn",
CircuitName::DecryptedSharesAggregationMod => "decrypted_shares_aggregation_mod",
CircuitName::DecryptedSharesAggregation => "decrypted_shares_aggregation",
CircuitName::Fold => "fold",
}
}
Expand All @@ -128,8 +125,7 @@ impl CircuitName {
CircuitName::PkGeneration => "threshold",
CircuitName::ThresholdShareDecryption => "threshold",
CircuitName::PkAggregation => "threshold",
CircuitName::DecryptedSharesAggregationBn => "threshold",
CircuitName::DecryptedSharesAggregationMod => "threshold",
CircuitName::DecryptedSharesAggregation => "threshold",
CircuitName::Fold => "recursive_aggregation",
}
}
Expand Down
14 changes: 5 additions & 9 deletions crates/events/src/enclave_event/signed_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,14 @@ impl ProofType {
ProofType::C3bESmShareEncryption => vec![CircuitName::ShareEncryption],
ProofType::C4DkgShareDecryption => vec![CircuitName::DkgShareDecryption],
ProofType::C6ThresholdShareDecryption => vec![CircuitName::ThresholdShareDecryption],
ProofType::C7DecryptedSharesAggregation => vec![
CircuitName::DecryptedSharesAggregationBn,
CircuitName::DecryptedSharesAggregationMod,
],
ProofType::C7DecryptedSharesAggregation => {
vec![CircuitName::DecryptedSharesAggregation]
}
ProofType::C5PkAggregation => vec![CircuitName::PkAggregation],
}
}

/// Slash reason identifier for on-chain policies.
/// Slash reason identifier for on-chain policies
pub fn slash_reason(&self) -> &'static str {
match self {
ProofType::C0PkBfv
Expand Down Expand Up @@ -401,10 +400,7 @@ mod tests {
);
assert_eq!(
ProofType::C7DecryptedSharesAggregation.circuit_names(),
vec![
CircuitName::DecryptedSharesAggregationBn,
CircuitName::DecryptedSharesAggregationMod,
]
vec![CircuitName::DecryptedSharesAggregation]
);
}
}
12 changes: 6 additions & 6 deletions crates/tests/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,11 @@ async fn setup_test_zk_backend() -> (ZkBackend, tempfile::TempDir) {
".vk_noir_hash",
)
.await;
// C7 (decrypted_shares_aggregation_mod)
// C7 (decrypted_shares_aggregation)
copy_circuit(
&threshold_target,
&rv.join("threshold/decrypted_shares_aggregation_mod"),
"decrypted_shares_aggregation_mod",
&rv.join("threshold/decrypted_shares_aggregation"),
"decrypted_shares_aggregation",
".vk_noir",
".vk_noir_hash",
)
Expand Down Expand Up @@ -330,11 +330,11 @@ async fn setup_test_zk_backend() -> (ZkBackend, tempfile::TempDir) {
".vk_hash",
)
.await;
// C7 (decrypted_shares_aggregation_mod) — EVM-targeted
// C7 (decrypted_shares_aggregation) — EVM-targeted
copy_circuit(
&threshold_target,
&ev.join("threshold/decrypted_shares_aggregation_mod"),
"decrypted_shares_aggregation_mod",
&ev.join("threshold/decrypted_shares_aggregation"),
"decrypted_shares_aggregation",
".vk",
".vk_hash",
)
Expand Down
Loading
Loading