Skip to content

Commit 6ba72bc

Browse files
committed
refactor(stm): updated the with_unsafe_srs to reuse existing files andd added tests
1 parent bf1c9b3 commit 6ba72bc

1 file changed

Lines changed: 122 additions & 5 deletions

File tree

mithril-stm/src/circuits/trusted_setup.rs

Lines changed: 122 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,21 +201,42 @@ pub(crate) const UNSAFE_SRS_SEED: u64 = 42;
201201
#[cfg(any(test, feature = "benchmark-internals"))]
202202
impl TrustedSetupProvider {
203203
/// Builds a `TrustedSetupProvider` backed by a freshly generated unsafe SRS of degree `k`, written
204-
/// to `base_dir/srs/srs-parameters` with a matching SHA256 hash so the provider's hash check passes.
204+
/// to `base_dir/{k}/srs/srs-parameters` with a matching SHA256 hash so the provider's hash check passes.
205205
/// For tests and benchmarks only.
206206
pub(crate) fn with_unsafe_srs(base_dir: &std::path::Path, k: u32) -> Self {
207+
let base_dir = base_dir.join(k.to_string());
208+
let srs_file = base_dir
209+
.join(MITHRIL_CIRCUIT_SRS_FOLDER)
210+
.join(MITHRIL_CIRCUIT_SRS_FILENAME);
211+
212+
if srs_file.exists() {
213+
return Self::new(base_dir, "", "", Duration::from_secs(600));
214+
}
215+
207216
let srs = ParamsKZG::<Bls12>::unsafe_setup(k, ChaCha20Rng::seed_from_u64(UNSAFE_SRS_SEED));
208217
let mut srs_bytes = Vec::new();
209-
srs.write_custom(&mut srs_bytes, SerdeFormat::RawBytes).unwrap();
218+
srs.write_custom(&mut srs_bytes, SerdeFormat::RawBytesUnchecked)
219+
.unwrap();
210220

211221
let srs_dir = base_dir.join(MITHRIL_CIRCUIT_SRS_FOLDER);
212222
create_dir_all(&srs_dir).unwrap();
213-
File::create(srs_dir.join(MITHRIL_CIRCUIT_SRS_FILENAME))
214-
.unwrap()
215-
.write_all(&srs_bytes)
223+
224+
let temp_path = srs_dir.join(MITHRIL_CIRCUIT_SRS_FILENAME).with_extension("temp");
225+
let final_path = srs_dir.join(MITHRIL_CIRCUIT_SRS_FILENAME);
226+
let mut temporary_file = File::create(&temp_path)
227+
.with_context(|| format!("Failed to create temporary SRS file at {temp_path:?}."))
216228
.unwrap();
229+
temporary_file.write_all(&srs_bytes).unwrap();
230+
temporary_file
231+
.sync_all()
232+
.with_context(|| "Failed to fsync temporary SRS file before rename.")
233+
.unwrap();
234+
drop(temporary_file);
235+
236+
std::fs::rename(temp_path, final_path).unwrap();
217237

218238
let expected_hash = hex::encode(Sha256::digest(&srs_bytes));
239+
219240
Self::new(base_dir, expected_hash, "", Duration::from_secs(600))
220241
}
221242
}
@@ -466,6 +487,102 @@ mod tests {
466487
assert!(result.is_err());
467488
}
468489

490+
mod with_unsafe_srs {
491+
use super::*;
492+
493+
#[test]
494+
fn creates_srs_file_nested_under_degree_subdirectory_and_loads_successfully() {
495+
let temp_dir = tempfile::tempdir_in("/tmp").unwrap();
496+
let k = 1;
497+
498+
let provider = TrustedSetupProvider::with_unsafe_srs(temp_dir.path(), k);
499+
500+
let expected_srs_path = temp_dir
501+
.path()
502+
.join(k.to_string())
503+
.join(MITHRIL_CIRCUIT_SRS_FOLDER)
504+
.join(MITHRIL_CIRCUIT_SRS_FILENAME);
505+
assert!(expected_srs_path.exists());
506+
assert!(provider.get_trusted_setup_parameters().is_ok());
507+
}
508+
509+
#[test]
510+
fn uses_separate_subdirectory_and_produces_distinct_files_per_degree() {
511+
let temp_dir = tempfile::tempdir_in("/tmp").unwrap();
512+
513+
TrustedSetupProvider::with_unsafe_srs(temp_dir.path(), 1);
514+
TrustedSetupProvider::with_unsafe_srs(temp_dir.path(), 2);
515+
516+
let srs_path_k1 = temp_dir
517+
.path()
518+
.join("1")
519+
.join(MITHRIL_CIRCUIT_SRS_FOLDER)
520+
.join(MITHRIL_CIRCUIT_SRS_FILENAME);
521+
let srs_path_k2 = temp_dir
522+
.path()
523+
.join("2")
524+
.join(MITHRIL_CIRCUIT_SRS_FOLDER)
525+
.join(MITHRIL_CIRCUIT_SRS_FILENAME);
526+
527+
assert!(srs_path_k1.exists());
528+
assert!(srs_path_k2.exists());
529+
assert_ne!(
530+
std::fs::read(srs_path_k1).unwrap(),
531+
std::fs::read(srs_path_k2).unwrap()
532+
);
533+
}
534+
535+
#[test]
536+
fn is_deterministic_for_the_same_degree_across_different_base_dirs() {
537+
let temp_dir_a = tempfile::tempdir_in("/tmp").unwrap();
538+
let temp_dir_b = tempfile::tempdir_in("/tmp").unwrap();
539+
let k = 1;
540+
541+
let provider_a = TrustedSetupProvider::with_unsafe_srs(temp_dir_a.path(), k);
542+
let provider_b = TrustedSetupProvider::with_unsafe_srs(temp_dir_b.path(), k);
543+
544+
let srs_subpath = std::path::Path::new(&k.to_string())
545+
.join(MITHRIL_CIRCUIT_SRS_FOLDER)
546+
.join(MITHRIL_CIRCUIT_SRS_FILENAME);
547+
let bytes_a = std::fs::read(temp_dir_a.path().join(&srs_subpath)).unwrap();
548+
let bytes_b = std::fs::read(temp_dir_b.path().join(&srs_subpath)).unwrap();
549+
550+
assert_eq!(bytes_a, bytes_b);
551+
assert!(provider_a.get_trusted_setup_parameters().is_ok());
552+
assert!(provider_b.get_trusted_setup_parameters().is_ok());
553+
}
554+
555+
#[test]
556+
fn does_not_regenerate_or_overwrite_an_existing_srs_file() {
557+
let temp_dir = tempfile::tempdir_in("/tmp").unwrap();
558+
let k = 1;
559+
let srs_dir = temp_dir.path().join(k.to_string()).join(MITHRIL_CIRCUIT_SRS_FOLDER);
560+
std::fs::create_dir_all(&srs_dir).unwrap();
561+
let srs_path = srs_dir.join(MITHRIL_CIRCUIT_SRS_FILENAME);
562+
std::fs::write(&srs_path, b"sentinel-content-not-a-real-srs").unwrap();
563+
564+
TrustedSetupProvider::with_unsafe_srs(temp_dir.path(), k);
565+
566+
let bytes_after = std::fs::read(&srs_path).unwrap();
567+
assert_eq!(bytes_after, b"sentinel-content-not-a-real-srs");
568+
}
569+
570+
#[test]
571+
fn leaves_no_temporary_file_behind_after_generation() {
572+
let temp_dir = tempfile::tempdir_in("/tmp").unwrap();
573+
let k = 1;
574+
575+
TrustedSetupProvider::with_unsafe_srs(temp_dir.path(), k);
576+
577+
let temp_path = temp_dir
578+
.path()
579+
.join(k.to_string())
580+
.join(MITHRIL_CIRCUIT_SRS_FOLDER)
581+
.join(MITHRIL_CIRCUIT_SRS_FILENAME)
582+
.with_extension("temp");
583+
assert!(!temp_path.exists());
584+
}
585+
}
469586
mod golden {
470587
use super::*;
471588

0 commit comments

Comments
 (0)