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
463 changes: 240 additions & 223 deletions Cargo.lock

Large diffs are not rendered by default.

46 changes: 40 additions & 6 deletions circuits/crates/libs/greco/src/lib.nr
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ impl<let N: u32, let L: u32> Params<N, L> {
/// * `BIT_P2` - Bit-width bound per coefficient for randomness polynomials `p2is`
///
/// # Circuit Inputs
/// * `pk_commitment` - Public key commitment
/// * `pk0is`, `pk1is` - Public key polynomials
/// * `ct0is`, `ct1is` - Ciphertext polynomials
/// * `u` - Secret polynomial sampled from ternary distribution
Expand All @@ -182,6 +183,7 @@ impl<let N: u32, let L: u32> Params<N, L> {
pub struct Greco<let N: u32, let L: u32, let BIT_PK: u32, let BIT_CT: u32, let BIT_U: u32, let BIT_E0: u32, let BIT_E1: u32, let BIT_K: u32, let BIT_R1: u32, let BIT_R2: u32, let BIT_P1: u32, let BIT_P2: u32> {
/// Cryptographic parameters including bounds, moduli, and constants.
params: Params<N, L>,
pk_commitment: Field,
pk0is: [Polynomial<N>; L],
pk1is: [Polynomial<N>; L],
ct0is: [Polynomial<N>; L],
Expand All @@ -206,6 +208,7 @@ impl<let N: u32, let L: u32, let BIT_PK: u32, let BIT_CT: u32, let BIT_U: u32, l
///
/// # Arguments
/// * `params` - Cryptographic parameters including bounds and moduli
/// * `pk_commitment` - Public key commitment
/// * `pk0is` - Public key polynomials pk0i = [ai*s + E] for each CRT basis
/// * `pk1is` - Public key polynomials pk1i = -[ai] for each CRT basis
/// * `ct0is` - First ciphertext component for each CRT basis
Expand All @@ -225,6 +228,7 @@ impl<let N: u32, let L: u32, let BIT_PK: u32, let BIT_CT: u32, let BIT_U: u32, l
/// A new Greco instance ready for constraint checking
pub fn new(
params: Params<N, L>,
pk_commitment: Field,
pk0is: [Polynomial<N>; L],
pk1is: [Polynomial<N>; L],
ct0is: [Polynomial<N>; L],
Expand All @@ -242,6 +246,7 @@ impl<let N: u32, let L: u32, let BIT_PK: u32, let BIT_CT: u32, let BIT_U: u32, l
) -> Greco<N, L, BIT_PK, BIT_CT, BIT_U, BIT_E0, BIT_E1, BIT_K, BIT_R1, BIT_R2, BIT_P1, BIT_P2> {
Greco {
params,
pk_commitment,
pk0is,
pk1is,
ct0is,
Expand All @@ -268,12 +273,12 @@ impl<let N: u32, let L: u32, let BIT_PK: u32, let BIT_CT: u32, let BIT_U: u32, l
///
/// # Returns
/// An array containing all polynomials coefficients in flattened form
fn payload(self) -> Vec<Field> {
fn gammas_payload(self) -> Vec<Field> {
let mut inputs = Vec::new();

// Flatten public key and ciphertext polynomials first (public inputs)
inputs = flatten::<_, _, BIT_PK>(inputs, self.pk0is);
inputs = flatten::<_, _, BIT_PK>(inputs, self.pk1is);
inputs.push(self.pk_commitment);

// Flatten ciphertext polynomials first (public inputs)
inputs = flatten::<_, _, BIT_CT>(inputs, self.ct0is);
inputs = flatten::<_, _, BIT_CT>(inputs, self.ct1is);

Expand All @@ -292,6 +297,23 @@ impl<let N: u32, let L: u32, let BIT_PK: u32, let BIT_CT: u32, let BIT_U: u32, l
inputs
}

/// Flattens public key polynomials into a single array for commitment generation.
///
/// This function serializes all public key polynomial coefficients into a 1D array to enable
/// the generation of a public key commitment using a cryptographic sponge.
///
/// # Returns
/// An array containing all public key polynomial coefficients in flattened form
fn commitment_payload(self) -> Vec<Field> {
let mut inputs = Vec::new();

// Flatten public key polynomials
inputs = flatten::<_, _, BIT_PK>(inputs, self.pk0is);
inputs = flatten::<_, _, BIT_PK>(inputs, self.pk1is);

inputs
}

/// Performs coefficient-wise CRT consistency check for e0 polynomial.
///
/// Verifies that for each CRT basis i and each coefficient j:
Expand Down Expand Up @@ -416,8 +438,6 @@ impl<let N: u32, let L: u32, let BIT_PK: u32, let BIT_CT: u32, let BIT_U: u32, l
/// # Returns
/// Vector of challenge values [gamma_0, gamma_1, ..., gamma_{2L-1}]
fn generate_challenge(self) -> Vec<Field> {
let inputs = self.payload();

// Domain separator for Greco circuit - "Greco" in hex
let domain_separator = [
0x47, 0x72, 0x65, 0x63, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Expand All @@ -427,13 +447,27 @@ impl<let N: u32, let L: u32, let BIT_PK: u32, let BIT_CT: u32, let BIT_U: u32, l
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];

// IO Pattern: ABSORB(input_size), SQUEEZE(1)
let inputs = self.commitment_payload();
let input_size = inputs.len();
let io_pattern = [0x80000000 | input_size, 0x00000000 | 1];

let mut sponge = SafeSponge::start(io_pattern, domain_separator);
sponge.absorb(inputs);
let commitment = sponge.squeeze();
sponge.finish();

assert_eq(commitment.get(0), self.pk_commitment);

// IO Pattern: ABSORB(input_size), SQUEEZE(2*L)
let inputs = self.gammas_payload();
let input_size = inputs.len();
let io_pattern = [0x80000000 | input_size, 0x00000000 | (2 * L)];

let mut sponge = SafeSponge::start(io_pattern, domain_separator);
sponge.absorb(inputs);
let gammas = sponge.squeeze();

sponge.finish();
gammas
}
Expand Down
6 changes: 6 additions & 0 deletions crates/bfv-helpers/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use anyhow::{anyhow, Result};
use fhe::bfv::{Encoding, Plaintext, PublicKey};
use fhe::Error as FheError;
use fhe_traits::{DeserializeParametrized, FheEncoder, FheEncrypter, Serialize};
use greco::bounds::GrecoBounds;
use greco::vectors::GrecoVectors;
use rand::thread_rng;

Expand Down Expand Up @@ -103,6 +104,10 @@ where
.try_encrypt_extended(&plaintext, &mut thread_rng())
.map_err(|e| anyhow!("Error encrypting data: {}", e))?;

let (_, bounds) = GrecoBounds::compute(&params, 0)?;

let bit_pk = shared::template::calculate_bit_width(&bounds.pk_bounds[0].to_string())?;

// Create Greco input validation ZK proof
let input_val_vectors = GrecoVectors::compute(
&plaintext,
Expand All @@ -112,6 +117,7 @@ where
&cipher_text,
&pk,
&params,
bit_pk,
)
.map_err(|e| anyhow!("Error computing input validation vectors: {}", e))?;

Expand Down
9 changes: 8 additions & 1 deletion crates/bfv-helpers/src/utils/greco.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ mod tests {
use alloy_primitives::FixedBytes;
use fhe::bfv::{Encoding, Plaintext, PublicKey, SecretKey};
use fhe_traits::{DeserializeParametrized, FheEncoder, Serialize};
use greco::bounds::GrecoBounds;
use greco::vectors::GrecoVectors;
use rand::thread_rng;

Expand All @@ -220,8 +221,14 @@ mod tests {
let pt = Plaintext::try_encode(&vote, Encoding::poly(), &params).unwrap();
let (ct, u_rns, e0_rns, e1_rns) = pk.try_encrypt_extended(&pt, &mut rng).unwrap();

let (_, bounds) = GrecoBounds::compute(&params, 0).unwrap();

let bit_pk =
shared::template::calculate_bit_width(&bounds.pk_bounds[0].to_string()).unwrap();

let greco_vectors =
GrecoVectors::compute(&pt, &u_rns, &e0_rns, &e1_rns, &ct, &pk, &params).unwrap();
GrecoVectors::compute(&pt, &u_rns, &e0_rns, &e1_rns, &ct, &pk, &params, bit_pk)
.unwrap();
let standard_vectors = greco_vectors.standard_form();

(params, ct, (standard_vectors.ct0is, standard_vectors.ct1is))
Expand Down
9 changes: 9 additions & 0 deletions crates/tests/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,19 @@ async fn test_trbfv_actor() -> Result<()> {
let threshold_m = 2;
let threshold_n = 5;
let esi_per_ct = 3;

// WARNING: INSECURE SECURITY PARAMETER LAMBDA.
// This is just for INSECURE parameter set.
// This is not secure and should not be used in production.
// For production use lambda = 80.
let lambda = 2;

let seed = create_seed_from_u64(123);
let error_size = ArcBytes::from_bytes(&BigUint::to_bytes_be(&calculate_error_size(
params_raw.clone(),
threshold_n,
threshold_m,
lambda,
)?));

// Cipher
Expand Down Expand Up @@ -219,6 +227,7 @@ async fn test_trbfv_actor() -> Result<()> {
//
// - m=2.
// - n=5
// - lambda=2
// - error_size -> calculate using calculate_error_size
// - esi_per_ciphertext = 3
///////////////////////////////////////////////////////////////////////////////////
Expand Down
3 changes: 2 additions & 1 deletion crates/trbfv/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ pub fn calculate_error_size(
params: Arc<bfv::BfvParameters>,
n: usize,
num_ciphertexts: usize,
lambda: usize,
) -> Result<BigUint> {
let config = SmudgingBoundCalculatorConfig::new(params, n, num_ciphertexts);
let config = SmudgingBoundCalculatorConfig::new(params, n, num_ciphertexts, lambda);
let calculator = SmudgingBoundCalculator::new(config);
Ok(calculator.calculate_sm_bound()?)
}
Expand Down
24 changes: 15 additions & 9 deletions crates/trbfv/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,26 @@ async fn test_trbfv_isolation() -> Result<()> {
let params_raw = build_bfv_params_arc(degree, plaintext_modulus, moduli, None);
let params = ArcBytes::from_bytes(&encode_bfv_params(&params_raw.clone()));

let cipher = Arc::new(Cipher::from_password("I am the music man.").await?);
let error_size = ArcBytes::from_bytes(&BigUint::to_bytes_be(&calculate_error_size(
params_raw.clone(),
5,
3,
)?));

// E3Parameters
let threshold_m = 2;
let threshold_n = 5;
let esi_per_ct = 3;
// WARNING: INSECURE SECURITY PARAMETER LAMBDA.
// This is just for INSECURE parameter set.
// This is not secure and should not be used in production.
// For production use lambda = 80.
let lambda = 2;
let seed = create_seed_from_u64(123);

let trbfv_config = TrBFVConfig::new(params, threshold_n, threshold_m);
let cipher = Arc::new(Cipher::from_password("I am the music man.").await?);
let error_size = ArcBytes::from_bytes(&BigUint::to_bytes_be(&calculate_error_size(
params_raw.clone(),
threshold_n,
esi_per_ct,
lambda,
)?));

let trbfv_config = TrBFVConfig::new(params, threshold_n as u64, threshold_m as u64);
let crp_raw = create_crp(
trbfv_config.params(),
Arc::new(Mutex::new(ChaCha20Rng::from_seed(seed.into()))),
Expand All @@ -79,7 +85,7 @@ async fn test_trbfv_isolation() -> Result<()> {
// let crp = ArcBytes::from_bytes(crp_raw.to_bytes());
let shares_hash_map = usecase_helpers::generate_shares_hash_map(
&trbfv_config,
esi_per_ct,
esi_per_ct as u64,
&error_size,
&crp_raw,
&rng,
Expand Down
Loading
Loading