diff --git a/Cargo.lock b/Cargo.lock index 23a586d..9d460de 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" @@ -1087,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" @@ -1270,6 +1301,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,8 +1785,10 @@ dependencies = [ "env_logger", "log", "new", + "prometheus", "rand", "rocket", + "rocket_prometheus", "serde", "serde_json", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 8afac2f..5bdf0a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ tokio = { version = "1.0", features = ["full"] } 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/executor.rs b/src/executor.rs index c1ff28b..beeacea 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 { @@ -119,7 +113,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(); @@ -225,6 +218,14 @@ pub async fn generate_proof( .stderr(Stdio::piped()) .output(); + match output{ + Ok(_) => {} + Err(e) => { + log::error!(target: "prover", "Failed to execute cp proof_{}.json: {}", height, e); + return; + } + } + let output = Command::new("cp") .args(&[ public_h_file_name.as_str(), @@ -234,6 +235,14 @@ pub async fn generate_proof( .stderr(Stdio::piped()) .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()) .args(&["generatecall"]) @@ -732,7 +741,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, @@ -790,37 +800,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, @@ -834,12 +838,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 81d2222..eabc68f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,17 @@ -use base64::read; -use blocking::unblock; -use executor::TestData; -use rand::Rng; +use metrics::ZKMetrics; 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; +mod metrics; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; #[derive(Debug, Serialize, Deserialize)] struct ProofRequestByID { @@ -38,6 +35,7 @@ enum ProverStateStatus { struct ProverState { db: ProofDatabase, + metrics: ZKMetrics, state: Arc>, } @@ -46,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)), } } @@ -129,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; @@ -151,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!({ @@ -168,6 +171,16 @@ fn rocket() -> _ { PORT="8000" ADDRESS="0.0.0.0" RAPIDSNARK_PATH="/home/mike/services/rapidsnark/package/bin/prover" BATCHVERIFY_FOLDER="batchverify_cpp" ED25519CIRCOM_PATH="/home/mike/services/ed25519circom" GNARK_JS_PATH="/usr/local/bin/snarkjs" cargo run */ + // Prometheus metrics + // Create a Registry and register Counter. + // let mut r = Registry::new(); + + // register metrics + let r = rocket_prometheus::PrometheusMetrics::new(); + + let metrics = crate::metrics::ZKMetrics::new(r.registry().clone()); + metrics.registr_metrics(); + executor::setup_logging(); let port = std::env::var("PORT").unwrap_or("8000".to_string()); @@ -201,10 +214,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..d83f71d --- /dev/null +++ b/src/metrics.rs @@ -0,0 +1,48 @@ +use std::time::{SystemTime, UNIX_EPOCH}; + +use prometheus::{Counter, Gauge, Opts, Registry}; + +#[derive(Clone)] +pub struct ZKMetrics { + r: Registry, + latest_successful_proof_secs: Gauge, + number_successful_proofs: Counter, +} + +impl ZKMetrics { + pub fn new(r: Registry) -> Self { + let counter_opts = Opts::new( + "latest_successful_proof_secs", + "latest available successful proof timestamp (in secs)", + ); + let latest_successful_proof_secs = Gauge::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 { + r, + latest_successful_proof_secs, + number_successful_proofs, + } + } + + pub fn registr_metrics(&self) { + self.r + .register(Box::new(self.latest_successful_proof_secs.clone())) + .unwrap(); + self.r + .register(Box::new(self.number_successful_proofs.clone())) + .unwrap(); + } + + 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(); + } +}