Skip to content

Commit f20d77d

Browse files
committed
chore: add threshold keygen tests
1 parent 1ddb301 commit f20d77d

File tree

2 files changed

+200
-10
lines changed

2 files changed

+200
-10
lines changed

core/threshold/src/execution/endpoints/keygen.rs

Lines changed: 192 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,10 @@ where
731731
.clone()
732732
.into_lwe_secret_key();
733733

734+
//Computing and opening BK can take a while, so we increase the timeout.
735+
//This must be set before compression key generation, which internally generates a BK.
736+
session.network().set_timeout_for_bk().await;
737+
734738
// Generate compression public keys if compression params exist
735739
let compression_keys =
736740
if let Some(comp_params) = params_basics_handle.get_compression_decompression_params() {
@@ -767,9 +771,6 @@ where
767771
)
768772
.await?;
769773
tracing::info!("(Party {my_role}) Generating KSK...Done");
770-
771-
//Computing and opening BK can take a while, so we increase the timeout
772-
session.network().set_timeout_for_bk().await;
773774
//Compute the bootstrapping keys
774775
let bk = generate_bootstrap_key(
775776
&private_key_set.glwe_secret_key_share,
@@ -1009,6 +1010,10 @@ where
10091010
.clone()
10101011
.into_lwe_secret_key();
10111012

1013+
//Computing and opening BK can take a while, so we increase the timeout.
1014+
//This must be set before compression key generation, which internally generates a BK.
1015+
session.network().set_timeout_for_bk().await;
1016+
10121017
// Generate compression public keys if compression params exist
10131018
let compression_keys =
10141019
if let Some(comp_params) = params_basics_handle.get_compression_decompression_params() {
@@ -1047,9 +1052,6 @@ where
10471052
)
10481053
.await?;
10491054
tracing::info!("(Party {my_role}) Generating KSK...Done");
1050-
1051-
//Computing and opening BK can take a while, so we increase the timeout
1052-
session.network().set_timeout_for_bk().await;
10531055
//Compute the bootstrapping keys
10541056
let bk = generate_compressed_bootstrap_key(
10551057
&private_key_set.glwe_secret_key_share,
@@ -1612,6 +1614,8 @@ pub mod conformance {
16121614
#[cfg(test)]
16131615
pub mod tests {
16141616
use super::OnlineDistributedKeyGen;
1617+
#[cfg(feature = "slow_tests")]
1618+
use crate::execution::runtime::sessions::base_session::GenericBaseSessionHandles;
16151619
use crate::{
16161620
algebra::{
16171621
base_ring::{Z128, Z64},
@@ -1620,6 +1624,7 @@ pub mod tests {
16201624
},
16211625
execution::{
16221626
endpoints::keygen::conformance::check_drift_technique_key,
1627+
keyset_config::StandardKeySetConfig,
16231628
online::preprocessing::dummy::DummyPreprocessing,
16241629
runtime::sessions::{
16251630
large_session::LargeSession, session_parameters::GenericParameterHandles,
@@ -2469,10 +2474,6 @@ pub mod tests {
24692474
use strum::IntoEnumIterator;
24702475
use tfhe::shortint::parameters::CompressionParameters;
24712476

2472-
use crate::execution::runtime::sessions::{
2473-
base_session::GenericBaseSessionHandles,
2474-
session_parameters::GenericParameterHandles,
2475-
};
24762477
for bound in crate::execution::tfhe_internals::parameters::NoiseBounds::iter() {
24772478
assert_eq!(0, dkg_preproc.noise_len(bound));
24782479
}
@@ -3244,4 +3245,185 @@ pub mod tests {
32443245
assert_eq!(clear_a.wrapping_add(clear_b), dec);
32453246
}
32463247
}
3248+
3249+
/// Phase 1: normal keygen to obtain a `PrivateKeySet`, using dummy preproc
3250+
/// Phase 2: keygen from the existing `PrivateKeySet` to regenerate public keys
3251+
/// Saves the results (phase 1 private keys, phase 2 public keys) to file.
3252+
#[cfg(feature = "slow_tests")]
3253+
async fn run_dkg_from_existing_sk_and_save<const EXTENSION_DEGREE: usize>(
3254+
params: DKGParams,
3255+
tag: tfhe::Tag,
3256+
num_parties: usize,
3257+
threshold: usize,
3258+
prefix_path: &Path,
3259+
run_compressed: bool,
3260+
) where
3261+
ResiduePoly<Z128, EXTENSION_DEGREE>: ErrorCorrect + Invert + Solve,
3262+
ResiduePoly<Z64, EXTENSION_DEGREE>: ErrorCorrect + Invert + Solve,
3263+
{
3264+
let mut task = |mut session: SmallSession<ResiduePoly<Z128, EXTENSION_DEGREE>>,
3265+
tag: Option<String>| async move {
3266+
let my_role = session.my_role();
3267+
let tag = tag
3268+
.map(|s| {
3269+
let mut tag = tfhe::Tag::default();
3270+
tag.set_data(s.as_bytes());
3271+
tag
3272+
})
3273+
.unwrap_or_default();
3274+
3275+
// Phase 1: normal keygen to obtain a PrivateKeySet,
3276+
// note that this is *not* compressed
3277+
let mut phase1_preproc = DummyPreprocessing::new(DUMMY_PREPROC_SEED, &session);
3278+
let (_pk_phase1, sk) =
3279+
super::SecureOnlineDistributedKeyGen128::<EXTENSION_DEGREE>::keygen(
3280+
&mut session,
3281+
&mut phase1_preproc,
3282+
params,
3283+
tag.clone(),
3284+
None,
3285+
)
3286+
.await
3287+
.unwrap();
3288+
3289+
// Phase 2: regenerate public keys from the existing PrivateKeySet
3290+
let keyset_config = KeySetConfig::Standard(StandardKeySetConfig::use_existing_sk());
3291+
session
3292+
.network()
3293+
.set_timeout_for_next_round(Duration::from_secs(240))
3294+
.await;
3295+
let mut phase2_preproc =
3296+
generate_preproc_from_params(&params, keyset_config, &mut session).await;
3297+
3298+
assert_ne!(0, phase2_preproc.bits_len());
3299+
assert_ne!(0, phase2_preproc.triples_len());
3300+
assert_ne!(0, phase2_preproc.randoms_len());
3301+
let pk = if run_compressed {
3302+
let compressed_pk =
3303+
super::SecureOnlineDistributedKeyGen128::<EXTENSION_DEGREE>::compressed_keygen_from_existing_private_keyset(
3304+
&mut session,
3305+
&mut phase2_preproc,
3306+
params,
3307+
tag,
3308+
Some(&sk),
3309+
)
3310+
.await
3311+
.unwrap();
3312+
let (public_key, server_key) = compressed_pk.decompress().unwrap().into_raw_parts();
3313+
FhePubKeySet {
3314+
public_key,
3315+
server_key,
3316+
}
3317+
} else {
3318+
super::SecureOnlineDistributedKeyGen128::<EXTENSION_DEGREE>::keygen_from_existing_private_keyset(
3319+
&mut session,
3320+
&mut phase2_preproc,
3321+
params,
3322+
tag,
3323+
Some(&sk),
3324+
)
3325+
.await
3326+
.unwrap()
3327+
};
3328+
3329+
(my_role, pk, sk)
3330+
};
3331+
3332+
let results =
3333+
execute_protocol_small::<_, _, ResiduePoly<Z128, EXTENSION_DEGREE>, EXTENSION_DEGREE>(
3334+
num_parties,
3335+
threshold as u8,
3336+
None,
3337+
NetworkMode::Sync,
3338+
None,
3339+
&mut task,
3340+
Some(std::str::from_utf8(tag.as_slice()).unwrap().to_string()),
3341+
)
3342+
.await;
3343+
3344+
let pk_ref = results[0].1.clone();
3345+
3346+
for (role, pk, sk) in results {
3347+
assert_eq!(pk, pk_ref);
3348+
write_element(
3349+
prefix_path.join(format!("sk_p{}.der", role.one_based())),
3350+
&sk,
3351+
)
3352+
.unwrap();
3353+
}
3354+
3355+
write_element(prefix_path.join("pk.der"), &pk_ref).unwrap();
3356+
}
3357+
3358+
/// Tests keygen from an existing private keyset using [`PARAMS_TEST_BK_SNS`].
3359+
/// Runs the two-phase DKG, then verifies the resulting keys with TFHE operations.
3360+
#[cfg(feature = "slow_tests")]
3361+
async fn integration_keygen_from_existing_test_bk_sns<const EXTENSION_DEGREE: usize>(
3362+
run_compressed: bool,
3363+
) where
3364+
ResiduePoly<Z64, EXTENSION_DEGREE>: ErrorCorrect + Solve + Invert,
3365+
ResiduePoly<Z128, EXTENSION_DEGREE>: ErrorCorrect + Solve + Invert,
3366+
{
3367+
let params = PARAMS_TEST_BK_SNS;
3368+
let num_parties = 4;
3369+
let threshold = 1;
3370+
let temp_dir = tempfile::tempdir().unwrap();
3371+
let tag = {
3372+
let mut tag = tfhe::Tag::default();
3373+
tag.set_data("hello tag".as_bytes());
3374+
tag
3375+
};
3376+
3377+
run_dkg_from_existing_sk_and_save::<EXTENSION_DEGREE>(
3378+
params,
3379+
tag.clone(),
3380+
num_parties,
3381+
threshold,
3382+
temp_dir.path(),
3383+
run_compressed,
3384+
)
3385+
.await;
3386+
3387+
run_switch_and_squash::<EXTENSION_DEGREE>(
3388+
temp_dir.path(),
3389+
params.try_into().unwrap(),
3390+
tag.clone(),
3391+
num_parties,
3392+
threshold,
3393+
);
3394+
3395+
run_tfhe_computation_shortint::<EXTENSION_DEGREE, DKGParamsSnS>(
3396+
temp_dir.path(),
3397+
params,
3398+
num_parties,
3399+
threshold,
3400+
true,
3401+
);
3402+
3403+
run_tfhe_computation_fheuint::<EXTENSION_DEGREE>(
3404+
temp_dir.path(),
3405+
params,
3406+
num_parties,
3407+
threshold,
3408+
true,
3409+
true,
3410+
);
3411+
3412+
run_tag_test::<EXTENSION_DEGREE>(temp_dir.path(), params, num_parties, threshold, &tag);
3413+
}
3414+
3415+
// #[tokio::test]
3416+
// #[serial_test::serial]
3417+
// #[cfg(feature = "slow_tests")]
3418+
// async fn keygen_from_existing_private_keyset_bk_sns_f4() {
3419+
// keygen_from_existing_test_bk_sns::<4>(false).await
3420+
// }
3421+
3422+
#[tokio::test]
3423+
#[serial_test::serial]
3424+
#[cfg(feature = "slow_tests")]
3425+
#[tracing_test::traced_test]
3426+
async fn integration_compressed_keygen_from_existing_private_keyset_bk_sns_f4() {
3427+
integration_keygen_from_existing_test_bk_sns::<4>(true).await
3428+
}
32473429
}

core/threshold/src/execution/keyset_config.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ impl StandardKeySetConfig {
9696
}
9797
}
9898

99+
pub fn use_existing_sk() -> Self {
100+
Self {
101+
computation_key_type: ComputeKeyType::default(),
102+
secret_key_config: KeyGenSecretKeyConfig::UseExisting,
103+
compressed_key_config: CompressedKeyConfig::default(),
104+
}
105+
}
106+
99107
pub fn is_using_existing_compression_sk(&self) -> bool {
100108
self.secret_key_config == KeyGenSecretKeyConfig::UseExistingCompressionSecretKey
101109
}

0 commit comments

Comments
 (0)