Skip to content

Commit 94de9f6

Browse files
committed
refactor(stm): applied more suggestions and reverted the use of HOME variable
1 parent aad40d2 commit 94de9f6

3 files changed

Lines changed: 77 additions & 80 deletions

File tree

mithril-stm/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ future_snark = [
3030
"dep:rand",
3131
"dep:sha2",
3232
"dep:rand_chacha",
33+
"dep:reqwest",
3334
]
3435
num-integer-backend = ["dep:num-bigint", "dep:num-integer", "dep:num-rational", "dep:num-traits"]
3536
rug-backend = ["rug/default"]
@@ -55,11 +56,10 @@ rand = { version = "0.10.1", optional = true }
5556
rand_chacha = { workspace = true, optional = true }
5657
rand_core = { workspace = true, features = ["std"] }
5758
rayon = { workspace = true }
58-
reqwest = { workspace = true, default-features = true, features = ["blocking"] }
59+
reqwest = { workspace = true, default-features = true, features = ["blocking"], optional = true }
5960
serde = { workspace = true }
6061
sha2 = { version = "0.10.9", optional = true }
6162
subtle = "2.6.1"
62-
tempfile = "3.27.0"
6363
thiserror = { workspace = true }
6464

6565
[target.'cfg(any(target_family = "wasm", target_env = "musl", windows))'.dependencies]

mithril-stm/src/circuits/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ pub(crate) mod test_utils;
1515
pub(crate) use halo2::witness::{
1616
CircuitInstance, CircuitMerkleTreeLeaf, CircuitWitness, MerklePath,
1717
};
18+
19+
/// Constant holding the current path of the cached values related to the circuits
20+
const MITHRIL_CIRCUIT_CACHE_FOLDER: &str = "mithril-circuit";

mithril-stm/src/circuits/trusted_setup.rs

Lines changed: 72 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
use std::{
22
fs::File,
3-
io::{BufReader, BufWriter, Read, Write},
3+
io::{BufReader, BufWriter, Write},
44
path::PathBuf,
5+
time::Duration,
56
};
67

78
use anyhow::{Context, anyhow};
89
use midnight_curves::Bls12;
910
use midnight_proofs::{poly::kzg::params::ParamsKZG, utils::SerdeFormat};
1011
use sha2::{Digest, Sha256};
11-
use tempfile::NamedTempFile;
1212

13-
use crate::StmResult;
13+
use crate::{StmResult, circuits::MITHRIL_CIRCUIT_CACHE_FOLDER};
1414

1515
/// TODO: remove allow(dead_code) when the constants are used or remove the constatnts
1616
#[allow(dead_code)]
@@ -22,35 +22,36 @@ use crate::StmResult;
2222
/// the proper value available here: https://github.com/midnightntwrk/midnight-trusted-setup/blob/main/MIDNIGHT_SRS_CATALOG.md
2323
const SRS_HASH_K22: &str = "e8ad5eed936d657a0fb59d2a55ba19f81a3083bb3554ef88f464f5377e9b2c2f";
2424
#[allow(dead_code)]
25-
/// Constant storing local path of the SRS of degree 22 used to create proof in production
26-
const SRS_PATH_K22: &str = ".local/local_trusted_setup/";
27-
#[allow(dead_code)]
2825
/// Constant storing URL to download the SRS of degree 22 used to create proof in production
2926
const SRS_URL_K22: &str = "https://srs.midnight.network/midnight-srs-2p22";
3027

31-
/// An handle to manage the trusted setup srs. It stores the local path of the srs file
28+
/// A structure to manage the trusted setup SRS. It stores the local path of the SRS file
3229
/// and information to download the file and verify integrity if it is missing.
33-
pub struct TrustedSetupHandle {
34-
/// Path of the local srs file
30+
pub struct TrustedSetupProvider {
31+
/// Path of the local SRS file
3532
local_srs_path: PathBuf,
36-
/// Expected hash of the downloaded srs file
33+
/// Expected hash of the downloaded SRS file
3734
srs_expected_hash: String,
38-
/// URL where to download the srs file if it is not present locally
35+
/// URL where to download the SRS file if it is not present locally
3936
url_to_download_srs: String,
37+
/// The timeout limit when trying to download the SRS file
38+
download_timeout_limit: Duration,
4039
}
4140

4241
/// TODO: remove allow(dead_code) when used
4342
#[allow(dead_code)]
44-
impl TrustedSetupHandle {
45-
fn new<P, S>(local_srs_path: P, srs_expected_hash: S, url_to_download_srs: S) -> Self
46-
where
47-
P: Into<PathBuf>,
48-
S: Into<String>,
49-
{
43+
impl TrustedSetupProvider {
44+
fn new<P: Into<PathBuf>, S: Into<String>>(
45+
local_srs_path: P,
46+
srs_expected_hash: S,
47+
url_to_download_srs: S,
48+
download_timeout_limit: Duration,
49+
) -> Self {
5050
Self {
5151
local_srs_path: local_srs_path.into(),
5252
srs_expected_hash: srs_expected_hash.into(),
5353
url_to_download_srs: url_to_download_srs.into(),
54+
download_timeout_limit,
5455
}
5556
}
5657

@@ -62,18 +63,6 @@ impl TrustedSetupHandle {
6263
hex::encode(hasher.finalize())
6364
}
6465

65-
/// Reads the local SRS file at the stored path and checks its SHA256 hash against the expected value.
66-
// This function can be removed if it is not used.
67-
fn verify_file_sha256_hash(&self) -> StmResult<bool> {
68-
let mut file = File::open(&self.local_srs_path)
69-
.with_context(|| "Loading of the SRS file should have succeeded!")?;
70-
let mut srs_buffer = vec![];
71-
file.read_to_end(&mut srs_buffer)
72-
.with_context(|| "Reading the SRS file should have succeeded!")?;
73-
74-
Ok(self.verify_bytes_sha256_hash(&srs_buffer))
75-
}
76-
7766
/// Checks SHA256 hash of the given bytes against the stored expected value.
7867
fn verify_bytes_sha256_hash(&self, srs_bytes: &[u8]) -> bool {
7968
let recomputed_hash = Self::compute_hash(srs_bytes);
@@ -85,7 +74,7 @@ impl TrustedSetupHandle {
8574
fn download_srs_file(&self) -> StmResult<Vec<u8>> {
8675
let response = reqwest::blocking::Client::builder()
8776
// TODO: For now a timeout but this should be updated depending on the behavior we want
88-
.timeout(std::time::Duration::from_secs(600))
77+
.timeout(self.download_timeout_limit)
8978
.build()?
9079
.get(&self.url_to_download_srs)
9180
.header("User-Agent", "mithril-stm")
@@ -96,8 +85,9 @@ impl TrustedSetupHandle {
9685
Ok(bytes.to_vec())
9786
}
9887

99-
/// Saves the given bytes in a file at the stored path while creating
100-
/// the directories of the path if needed.
88+
/// Saves the given bytes in a temporary file then atomically moves it to the stored path
89+
/// while creating the directories of the path if needed.
90+
/// If the writing is interu
10191
fn store_srs_bytes_to_file(&self, srs_bytes: &[u8]) -> StmResult<()> {
10292
let parent = self
10393
.local_srs_path
@@ -106,12 +96,14 @@ impl TrustedSetupHandle {
10696
std::fs::create_dir_all(parent)
10797
.with_context(|| "Subdirectory creation should have succeeded!")?;
10898

109-
let mut temporary_file = NamedTempFile::new_in(parent)
110-
.with_context(|| "Failed to generate temporary file to store the SRS")?;
99+
let temp_path = self.local_srs_path.with_extension(".temp");
100+
// Create/clean the file
101+
let mut temporary_file = File::create(&temp_path)?;
111102
BufWriter::new(&mut temporary_file).write_all(srs_bytes)?;
112-
temporary_file
113-
.persist(&self.local_srs_path)
114-
.with_context(|| "Failed to atomically rename SRS temp file.")?;
103+
104+
// atomic renaming
105+
std::fs::rename(temp_path, &self.local_srs_path)?;
106+
115107
Ok(())
116108
}
117109

@@ -143,19 +135,18 @@ impl TrustedSetupHandle {
143135
.with_context(|| format!("Failed to open SRS file at {:?}", self.local_srs_path))?;
144136
let mut reader = BufReader::new(file);
145137

146-
ParamsKZG::read_custom(&mut reader, SerdeFormat::RawBytes)
138+
ParamsKZG::read_custom(&mut reader, SerdeFormat::RawBytesUnchecked)
147139
.with_context(|| "Failed to deserialize SRS from file")
148140
}
149141
}
150142

151-
impl Default for TrustedSetupHandle {
143+
impl Default for TrustedSetupProvider {
152144
fn default() -> Self {
153145
Self::new(
154-
PathBuf::from(std::env::var("HOME").unwrap_or_else(|_| ".".to_string()))
155-
.join(SRS_PATH_K22)
156-
.join("midnight-srs-2p22"),
146+
std::env::temp_dir().join(MITHRIL_CIRCUIT_CACHE_FOLDER).join("srs"),
157147
SRS_HASH_K22,
158148
SRS_URL_K22,
149+
Duration::from_secs(600),
159150
)
160151
}
161152
}
@@ -215,7 +206,8 @@ mod tests {
215206
fn both_bytes_encoding_work_to_load_srs_from_file() {
216207
let mut tmp_file = NamedTempFile::new().unwrap();
217208
std::fs::write(&mut tmp_file, SRS_K1.as_slice()).unwrap();
218-
let srs_manager = TrustedSetupHandle::new(tmp_file.path(), "", "");
209+
let srs_manager =
210+
TrustedSetupProvider::new(tmp_file.path(), "", "", Duration::from_secs(600));
219211
let loaded_srs = srs_manager.check_available_file_then_load_srs().unwrap();
220212
let srs_rawbytes: ParamsKZG<Bls12> =
221213
ParamsKZG::read_custom(&mut SRS_K1.as_slice(), SerdeFormat::RawBytes).unwrap();
@@ -243,57 +235,44 @@ mod tests {
243235
assert_eq!(raw_bytes_unchecked_buffer, raw_bytes_buffer);
244236
}
245237

246-
#[test]
247-
fn hash_of_correct_srs_file_verifies() {
248-
let srs_file = NamedTempFile::new_in("/tmp").unwrap();
249-
std::fs::write(&srs_file, SRS_K1).unwrap();
250-
251-
let result = TrustedSetupHandle::new(srs_file.path(), SRS_HASH_K1, "")
252-
.verify_file_sha256_hash()
253-
.unwrap();
254-
255-
assert!(result);
256-
}
257-
258238
#[test]
259239
fn verification_of_hash_of_invalid_srs_file_fails() {
260240
let mut tampered_bytes = SRS_K1.to_vec();
261241
tampered_bytes[0] = tampered_bytes[0].wrapping_add(1);
262242

263-
let result =
264-
TrustedSetupHandle::new("", SRS_HASH_K1, "").verify_bytes_sha256_hash(&tampered_bytes);
243+
let result = TrustedSetupProvider::new("", SRS_HASH_K1, "", Duration::from_secs(600))
244+
.verify_bytes_sha256_hash(&tampered_bytes);
265245

266246
assert!(!result);
267247
}
268248

269249
#[test]
270250
fn hash_of_correct_bytes_verifies() {
271-
let result = TrustedSetupHandle::new("", SRS_HASH_K1, "").verify_bytes_sha256_hash(SRS_K1);
251+
let result = TrustedSetupProvider::new("", SRS_HASH_K1, "", Duration::from_secs(600))
252+
.verify_bytes_sha256_hash(SRS_K1);
272253

273254
assert!(result);
274255
}
275256

276257
#[test]
277-
fn verification_of_hash_of_invalid_bytes_fails() {
258+
fn existing_file_on_disk_skips_download_and_verification() {
278259
let srs_file = NamedTempFile::new_in("/tmp").unwrap();
279-
let mut tampered = SRS_K1.to_vec();
280-
tampered[0] = tampered[0].wrapping_add(1);
281-
std::fs::write(&srs_file, &tampered).unwrap();
260+
std::fs::write(&srs_file, [0, 1, 2, 3, 4]).unwrap();
282261

283-
let result = TrustedSetupHandle::new(srs_file.path(), SRS_HASH_K1, "")
284-
.verify_file_sha256_hash()
285-
.unwrap();
262+
let result = TrustedSetupProvider::new(srs_file.path(), "", "", Duration::from_secs(600))
263+
.ensure_srs_file_is_available();
286264

287-
assert!(!result);
265+
assert!(result.is_ok());
288266
}
289267

290268
#[test]
291-
fn existing_file_on_disk_skips_download_and_verification() {
269+
fn interrupted_writing_of_srs_resumes_properly_at_next_try() {
292270
let srs_file = NamedTempFile::new_in("/tmp").unwrap();
293-
std::fs::write(&srs_file, [0, 1, 2, 3, 4]).unwrap();
271+
let temp_srs_file = srs_file.path().with_extension("temp");
272+
std::fs::write(&temp_srs_file, [0, 1, 2, 3, 4]).unwrap();
294273

295-
let result =
296-
TrustedSetupHandle::new(srs_file.path(), "", "").ensure_srs_file_is_available();
274+
let result = TrustedSetupProvider::new(srs_file.path(), "", "", Duration::from_secs(600))
275+
.ensure_srs_file_is_available();
297276

298277
assert!(result.is_ok());
299278
}
@@ -302,7 +281,7 @@ mod tests {
302281
use super::*;
303282

304283
#[test]
305-
fn missing_srs_file_triggers_download_verifiation_and_storage() {
284+
fn missing_srs_file_triggers_download_verification_and_storage() {
306285
let server = MockServer::start();
307286
let mock = server.mock(|when, then| {
308287
when.method(httpmock::Method::GET).path("/srs");
@@ -312,9 +291,14 @@ mod tests {
312291
let temp_dir = tempfile::tempdir().unwrap();
313292
let srs_path = temp_dir.path().join("missing_file_trigger_dl");
314293

315-
TrustedSetupHandle::new(&srs_path, SRS_HASH_K1, &server.url("/srs"))
316-
.ensure_srs_file_is_available()
317-
.unwrap();
294+
TrustedSetupProvider::new(
295+
&srs_path,
296+
SRS_HASH_K1,
297+
&server.url("/srs"),
298+
Duration::from_secs(600),
299+
)
300+
.ensure_srs_file_is_available()
301+
.unwrap();
318302

319303
mock.assert();
320304
assert!(srs_path.exists());
@@ -331,8 +315,13 @@ mod tests {
331315
let temp_dir = tempfile::tempdir().unwrap();
332316
let srs_path = temp_dir.path().join("dl_wrong_hash");
333317

334-
let result = TrustedSetupHandle::new(&srs_path, SRS_HASH_K1, &server.url("/srs"))
335-
.ensure_srs_file_is_available();
318+
let result = TrustedSetupProvider::new(
319+
&srs_path,
320+
SRS_HASH_K1,
321+
&server.url("/srs"),
322+
Duration::from_secs(600),
323+
)
324+
.ensure_srs_file_is_available();
336325

337326
assert!(result.is_err());
338327
assert!(!srs_path.exists());
@@ -349,8 +338,13 @@ mod tests {
349338
let temp_dir = tempfile::tempdir().unwrap();
350339
let srs_path = temp_dir.path().join("server_error_fails");
351340

352-
let result = TrustedSetupHandle::new(&srs_path, SRS_HASH_K1, &server.url("/srs"))
353-
.ensure_srs_file_is_available();
341+
let result = TrustedSetupProvider::new(
342+
&srs_path,
343+
SRS_HASH_K1,
344+
&server.url("/srs"),
345+
Duration::from_secs(600),
346+
)
347+
.ensure_srs_file_is_available();
354348

355349
assert!(result.is_err());
356350
}

0 commit comments

Comments
 (0)