From a8a989b1f715ed7d06dc9bd8d810dd59cfb736a5 Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Mon, 25 Mar 2024 08:50:53 -0300 Subject: [PATCH 1/4] add dep + remove unused variables --- Cargo.lock | 42 +++++++++++++++++++++++++ Cargo.toml | 1 + src/executor.rs | 84 ++++++++++++++++++++++--------------------------- src/main.rs | 9 ++---- 4 files changed, 82 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3c9279..d28b498 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -893,6 +893,27 @@ dependencies = [ "yansi", ] +[[package]] +name = "prometheus" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "449811d15fbdf5ceb5c1144416066429cf82316e2ec8ce0c1f6f8a02e7bbcf8c" +dependencies = [ + "cfg-if", + "fnv", + "lazy_static", + "memchr", + "parking_lot", + "protobuf", + "thiserror", +] + +[[package]] +name = "protobuf" +version = "2.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" + [[package]] name = "quote" version = "1.0.35" @@ -1270,6 +1291,26 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.7" @@ -1734,6 +1775,7 @@ dependencies = [ "env_logger", "log", "new", + "prometheus", "rand", "rocket", "serde", diff --git a/Cargo.toml b/Cargo.toml index 8afac2f..fb0d688 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ tokio = { version = "1.0", features = ["full"] } serde_json = "1.0.68" log = "0.4.17" env_logger = "0.9.0" +prometheus = "0.13.3" [dev-dependencies] new = "0.0.0" diff --git a/src/executor.rs b/src/executor.rs index f2d6018..ca65503 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -1,11 +1,5 @@ -use blocking::unblock; use serde::Deserialize; use serde::Serialize; -use std::process::Command; -use std::process::ExitStatus; -use std::process::Stdio; -use std::sync::{Arc, Mutex}; -use tokio::sync::RwLock; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct TestData { @@ -114,7 +108,6 @@ pub async fn generate_proof( .output() .expect("failed to execute process"); - log::info!(target: "prover", "npm test output: {:?}", output); let batchverify_folder = batchverify_folder(); @@ -174,7 +167,7 @@ pub async fn generate_proof( log::info!(target: "prover", "Executing command: "); log::info!(target: "prover", "snarkjs groth16 prove batchverify_0001.zkey ./{}/witness.wtns {} {}", batchverify_folder, proof_h_file_name, public_h_file_name); - let output = Command::new(path_to_gnark_js()) + let _ = Command::new(path_to_gnark_js()) .args(&[ "groth16", "prove", @@ -185,26 +178,29 @@ pub async fn generate_proof( ]) .stdout(Stdio::piped()) .stderr(Stdio::piped()) - .output(); + .output() + .unwrap(); //copy proof and public with a new name - let output = Command::new("cp") + let _ = Command::new("cp") .args(&[ proof_h_file_name.as_str(), format!("proof_{}.json", height).as_str(), ]) .stdout(Stdio::piped()) .stderr(Stdio::piped()) - .output(); + .output() + .unwrap(); - let output = Command::new("cp") + let _ = Command::new("cp") .args(&[ public_h_file_name.as_str(), format!("public_{}.json", height).as_str(), ]) .stdout(Stdio::piped()) .stderr(Stdio::piped()) - .output(); + .output() + .unwrap(); log::info!(target: "prover", "snarkjs generatecall"); let output = Command::new(path_to_gnark_js()) @@ -270,7 +266,6 @@ pub fn setup_logging() { } mod tests { - const TEST_BLOCK_HEIGHT: u64 = 123456789; use super::*; #[tokio::test(flavor = "multi_thread", worker_threads = 10)] @@ -684,7 +679,8 @@ mod tests { 33, 251, 215, 204, 183, 218, 227, 31, 121, 13, 3, ] .to_vec(), - ].to_vec(); + ] + .to_vec(); let mut data = TestData { msg: msg, sigs: sig, @@ -741,37 +737,31 @@ mod tests { assert!(proof.is_some()); } - fn get_pub_inputs_12_118_the_same_12() -> TestData { - let msg = [ - [ - 117, 8, 2, 17, 139, 68, 14, 0, 0, 0, 0, 0, 34, 72, 10, 32, 94, 6, 100, 90, 207, - 146, 4, 250, 161, 103, 142, 60, 242, 24, 112, 218, 190, 149, 84, 107, 179, 191, - 113, 199, 12, 203, 89, 102, 31, 250, 227, 169, 18, 36, 8, 1, 18, 32, 51, 187, 39, - 182, 141, 59, 69, 240, 33, 54, 13, 12, 170, 184, 89, 35, 189, 41, 120, 6, 3, 226, - 202, 202, 23, 37, 4, 207, 62, 204, 24, 188, 42, 12, 8, 133, 128, 195, 175, 6, 16, - 128, 128, 128, 128, 1, 50, 16, 98, 97, 110, 107, 115, 121, 45, 116, 101, 115, 116, - 110, 101, 116, 45, 53, - ].to_vec() + let msg = [[ + 117, 8, 2, 17, 139, 68, 14, 0, 0, 0, 0, 0, 34, 72, 10, 32, 94, 6, 100, 90, 207, 146, 4, + 250, 161, 103, 142, 60, 242, 24, 112, 218, 190, 149, 84, 107, 179, 191, 113, 199, 12, + 203, 89, 102, 31, 250, 227, 169, 18, 36, 8, 1, 18, 32, 51, 187, 39, 182, 141, 59, 69, + 240, 33, 54, 13, 12, 170, 184, 89, 35, 189, 41, 120, 6, 3, 226, 202, 202, 23, 37, 4, + 207, 62, 204, 24, 188, 42, 12, 8, 133, 128, 195, 175, 6, 16, 128, 128, 128, 128, 1, 50, + 16, 98, 97, 110, 107, 115, 121, 45, 116, 101, 115, 116, 110, 101, 116, 45, 53, ] + .to_vec()] .to_vec(); - let pubkey = [ - [ - 58, 216, 70, 53, 81, 202, 230, 255, 230, 114, 57, 127, 213, 92, 106, 48, 54, 202, - 226, 135, 50, 16, 58, 144, 251, 110, 244, 70, 221, 125, 5, 98, - ] - .to_vec(), + let pubkey = [[ + 58, 216, 70, 53, 81, 202, 230, 255, 230, 114, 57, 127, 213, 92, 106, 48, 54, 202, 226, + 135, 50, 16, 58, 144, 251, 110, 244, 70, 221, 125, 5, 98, ] + .to_vec()] + .to_vec(); + let sig = [[ + 232, 29, 124, 231, 226, 58, 169, 241, 54, 121, 219, 150, 109, 78, 227, 185, 244, 118, + 187, 220, 87, 100, 224, 205, 220, 185, 119, 205, 7, 78, 195, 49, 184, 96, 77, 183, 196, + 120, 226, 125, 90, 86, 107, 218, 81, 193, 84, 161, 174, 43, 219, 223, 162, 175, 26, + 221, 182, 220, 105, 168, 16, 45, 49, 7, + ] + .to_vec()] .to_vec(); - let sig = [ - [ - 232, 29, 124, 231, 226, 58, 169, 241, 54, 121, 219, 150, 109, 78, 227, 185, 244, - 118, 187, 220, 87, 100, 224, 205, 220, 185, 119, 205, 7, 78, 195, 49, 184, 96, 77, - 183, 196, 120, 226, 125, 90, 86, 107, 218, 81, 193, 84, 161, 174, 43, 219, 223, - 162, 175, 26, 221, 182, 220, 105, 168, 16, 45, 49, 7, - ] - .to_vec(), - ].to_vec(); let mut data = TestData { msg: msg, sigs: sig, @@ -785,12 +775,12 @@ mod tests { assert!(data.msg.len() == 12); assert!(data.sigs.len() == 12); assert!(data.pubkeys.len() == 12); - - // [ - // "0", - // "211318896230210628196574274176250526140", - // "293870744648832153179681560962762359603" - // ] + + // [ + // "0", + // "211318896230210628196574274176250526140", + // "293870744648832153179681560962762359603" + // ] return data; } } diff --git a/src/main.rs b/src/main.rs index 336cc7a..abdc30e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,15 @@ -use base64::read; -use blocking::unblock; -use executor::TestData; -use rand::Rng; use rocket::serde::json::Json; use rocket::serde::json::{json, Value}; use rocket::time::Instant; use rocket::tokio::sync::RwLock; use serde::{Deserialize, Serialize}; -use std::borrow::{Borrow, BorrowMut}; +use std::borrow::Borrow; use std::collections::HashMap; use std::ops::Deref; -use std::process::{Command, Stdio}; mod executor; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; #[derive(Debug, Serialize, Deserialize)] struct ProofRequestByID { From c3961d92aa1641d2ec6892bd5d35cfb77d790bdf Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Mon, 25 Mar 2024 09:27:37 -0300 Subject: [PATCH 2/4] add metrics for Rocket + ZK Server --- Cargo.lock | 11 +++++++++++ Cargo.toml | 1 + src/main.rs | 13 ++++++++++++- src/metrics.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/metrics.rs diff --git a/Cargo.lock b/Cargo.lock index d28b498..8def111 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1108,6 +1108,16 @@ dependencies = [ "uncased", ] +[[package]] +name = "rocket_prometheus" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18faabccdfcd08d4501768f5b6936f6332af10496f1ea8107eb48a7766e03439" +dependencies = [ + "prometheus", + "rocket", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -1778,6 +1788,7 @@ dependencies = [ "prometheus", "rand", "rocket", + "rocket_prometheus", "serde", "serde_json", "tokio", diff --git a/Cargo.toml b/Cargo.toml index fb0d688..5bdf0a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ serde_json = "1.0.68" log = "0.4.17" env_logger = "0.9.0" prometheus = "0.13.3" +rocket_prometheus = "0.10.0" [dev-dependencies] new = "0.0.0" diff --git a/src/main.rs b/src/main.rs index abdc30e..0c9266e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ use std::collections::HashMap; use std::ops::Deref; mod executor; +mod metrics; use std::sync::Arc; @@ -161,6 +162,15 @@ fn rocket() -> _ { BATCHVERIFY_FOLDER="batchverify_cpp" ED25519CIRCOM_PATH="/Users/mykyta/development/rustninja/ed25519circom" GNARK_JS_PATH="/Users/mykyta/.nvm/versions/node/v18.19.0/bin/snarkjs" cargo run */ + // Prometheus metrics + // Create a Registry and register Counter. + // let mut r = Registry::new(); + + // register metrics + let mut r = rocket_prometheus::PrometheusMetrics::new(); + let metrics = crate::metrics::ZKMetrics::new(); + metrics.registr_metrics(&mut r); + executor::setup_logging(); let port = std::env::var("PORT").unwrap_or("8000".to_string()); @@ -190,10 +200,11 @@ fn rocket() -> _ { port: port, ..Default::default() }; - // rocket::build() rocket::custom(config) .mount("/", rocket::routes![status, get_proof, create_proof]) .manage(prover_state) + .attach(r.clone()) + .mount("/metrics", r) } pub fn get_string_from_env(s: &str) -> String { diff --git a/src/metrics.rs b/src/metrics.rs new file mode 100644 index 0000000..0c7123a --- /dev/null +++ b/src/metrics.rs @@ -0,0 +1,43 @@ +use prometheus::{Counter, Opts}; +use rocket_prometheus::PrometheusMetrics; + +pub struct ZKMetrics { + latest_successful_proof_ms: Counter, + number_successful_proofs: Counter, +} + +impl ZKMetrics { + pub fn new() -> Self { + let counter_opts = Opts::new( + "latest_successful_proof_ms", + "latest available successful proof timestamp (in ms)", + ); + let latest_successful_proof_ms = Counter::with_opts(counter_opts).unwrap(); + + let counter_opts = Opts::new( + "number_successful_proofs", + "number of successful proofs created by the zk prover", + ); + let number_successful_proofs = Counter::with_opts(counter_opts).unwrap(); + + Self { + latest_successful_proof_ms, + number_successful_proofs, + } + } + + pub fn registr_metrics(&self, r: &mut PrometheusMetrics) { + r.registry() + .register(Box::new(self.latest_successful_proof_ms.clone())) + .unwrap(); + r.registry() + .register(Box::new(self.number_successful_proofs.clone())) + .unwrap(); + } +} + +impl Default for ZKMetrics { + fn default() -> Self { + Self::new() + } +} From c6f215c0234fc7365c14445f2f3e88897440baea Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Mon, 25 Mar 2024 09:44:46 -0300 Subject: [PATCH 3/4] update metrics with new proof --- src/main.rs | 18 +++++++++++++----- src/metrics.rs | 37 +++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0c9266e..29e923b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use metrics::ZKMetrics; use rocket::serde::json::Json; use rocket::serde::json::{json, Value}; use rocket::time::Instant; @@ -34,6 +35,7 @@ enum ProverStateStatus { struct ProverState { db: ProofDatabase, + metrics: ZKMetrics, state: Arc>, } @@ -42,11 +44,12 @@ struct ProofDatabase { } impl ProverState { - fn new() -> Self { + fn new(metrics: ZKMetrics) -> Self { Self { db: ProofDatabase { inner: HashMap::new().into(), }, + metrics, state: Arc::new(RwLock::new(ProverStateStatus::IDLE)), } } @@ -125,6 +128,9 @@ async fn create_proof( }); } + // get a handler of metrics so that they can be sent to the thread that monitors that the proof has been created. + let metrics = state.metrics.clone(); + let _task_handle = tokio::spawn(async move { let mut s = status.write().await; *s = ProverStateStatus::PROVING; @@ -147,6 +153,7 @@ async fn create_proof( log::info!(target: "prover", "Proof generation completed for block_height: {:?}", create_proof_request.height); log::info!(target: "prover", "Server went to IDLE status"); + metrics.register_new_successful_proof(); }); return json!({ @@ -167,9 +174,10 @@ fn rocket() -> _ { // let mut r = Registry::new(); // register metrics - let mut r = rocket_prometheus::PrometheusMetrics::new(); - let metrics = crate::metrics::ZKMetrics::new(); - metrics.registr_metrics(&mut r); + let r = rocket_prometheus::PrometheusMetrics::new(); + + let metrics = crate::metrics::ZKMetrics::new(r.registry().clone()); + metrics.registr_metrics(); executor::setup_logging(); @@ -194,7 +202,7 @@ fn rocket() -> _ { log::warn!(target: "prover", "To specify the path to the BATCHVERIFY_FOLDER, set the BATCHVERIFY_FOLDER environment variable to batchverify_cpp or batchverify_js."); log::info!(target: "prover", "BATCHVERIFY_FOLDER: {:?}", batchverify_folder); - let prover_state = ProverState::new(); + let prover_state = ProverState::new(metrics); let config = rocket::config::Config { address: address.parse().unwrap(), port: port, diff --git a/src/metrics.rs b/src/metrics.rs index 0c7123a..d83f71d 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -1,18 +1,21 @@ -use prometheus::{Counter, Opts}; -use rocket_prometheus::PrometheusMetrics; +use std::time::{SystemTime, UNIX_EPOCH}; +use prometheus::{Counter, Gauge, Opts, Registry}; + +#[derive(Clone)] pub struct ZKMetrics { - latest_successful_proof_ms: Counter, + r: Registry, + latest_successful_proof_secs: Gauge, number_successful_proofs: Counter, } impl ZKMetrics { - pub fn new() -> Self { + pub fn new(r: Registry) -> Self { let counter_opts = Opts::new( - "latest_successful_proof_ms", - "latest available successful proof timestamp (in ms)", + "latest_successful_proof_secs", + "latest available successful proof timestamp (in secs)", ); - let latest_successful_proof_ms = Counter::with_opts(counter_opts).unwrap(); + let latest_successful_proof_secs = Gauge::with_opts(counter_opts).unwrap(); let counter_opts = Opts::new( "number_successful_proofs", @@ -21,23 +24,25 @@ impl ZKMetrics { let number_successful_proofs = Counter::with_opts(counter_opts).unwrap(); Self { - latest_successful_proof_ms, + r, + latest_successful_proof_secs, number_successful_proofs, } } - pub fn registr_metrics(&self, r: &mut PrometheusMetrics) { - r.registry() - .register(Box::new(self.latest_successful_proof_ms.clone())) + pub fn registr_metrics(&self) { + self.r + .register(Box::new(self.latest_successful_proof_secs.clone())) .unwrap(); - r.registry() + self.r .register(Box::new(self.number_successful_proofs.clone())) .unwrap(); } -} -impl Default for ZKMetrics { - fn default() -> Self { - Self::new() + pub fn register_new_successful_proof(&self) { + let now = SystemTime::now(); + self.latest_successful_proof_secs + .set(now.duration_since(UNIX_EPOCH).unwrap().as_secs_f64()); + self.number_successful_proofs.inc(); } } From af6688b2d416237719c08f8002002d82aca2dd29 Mon Sep 17 00:00:00 2001 From: rustdev Date: Thu, 4 Apr 2024 17:19:20 +0100 Subject: [PATCH 4/4] replace unwrap to match. to not panic during prove execution flow, --- src/executor.rs | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/executor.rs b/src/executor.rs index ca65503..ca3e9b1 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -167,7 +167,7 @@ pub async fn generate_proof( log::info!(target: "prover", "Executing command: "); log::info!(target: "prover", "snarkjs groth16 prove batchverify_0001.zkey ./{}/witness.wtns {} {}", batchverify_folder, proof_h_file_name, public_h_file_name); - let _ = Command::new(path_to_gnark_js()) + let output = Command::new(path_to_gnark_js()) .args(&[ "groth16", "prove", @@ -178,29 +178,51 @@ pub async fn generate_proof( ]) .stdout(Stdio::piped()) .stderr(Stdio::piped()) - .output() - .unwrap(); + .output(); + + match output{ + Ok(_) => {} + Err(e) => { + log::error!(target: "prover", "snarkjs groth16 prove batchverify_0001.zkey: {}", e); + return; + } + } + //copy proof and public with a new name - let _ = Command::new("cp") + let output = Command::new("cp") .args(&[ proof_h_file_name.as_str(), format!("proof_{}.json", height).as_str(), ]) .stdout(Stdio::piped()) .stderr(Stdio::piped()) - .output() - .unwrap(); + .output(); + + match output{ + Ok(_) => {} + Err(e) => { + log::error!(target: "prover", "Failed to execute cp proof_{}.json: {}", height, e); + return; + } + } - let _ = Command::new("cp") + let output = Command::new("cp") .args(&[ public_h_file_name.as_str(), format!("public_{}.json", height).as_str(), ]) .stdout(Stdio::piped()) .stderr(Stdio::piped()) - .output() - .unwrap(); + .output(); + + match output{ + Ok(_) => {} + Err(e) => { + log::error!(target: "prover", "Failed to execute cp public_{}.json: {}", height, e); + return; + } + } log::info!(target: "prover", "snarkjs generatecall"); let output = Command::new(path_to_gnark_js())