diff --git a/coordinator/conf/config.json b/coordinator/conf/config.json index de8944a7b9..bbb839e082 100644 --- a/coordinator/conf/config.json +++ b/coordinator/conf/config.json @@ -2,9 +2,6 @@ "prover_manager": { "provers_per_session": 1, "session_attempts": 5, - "bundle_collection_time_sec": 180, - "batch_collection_time_sec": 180, - "chunk_collection_time_sec": 180, "verifier": { "mock_mode": true, "low_version_circuit": { @@ -19,7 +16,11 @@ "fork_name": "darwinV2", "min_prover_version": "v4.4.45" } - } + }, + "bundle_collection_time_sec": 180, + "batch_collection_time_sec": 180, + "chunk_collection_time_sec": 180, + "prover_sentry_endpoint": "" }, "db": { "driver_name": "postgres", diff --git a/coordinator/internal/config/config.go b/coordinator/internal/config/config.go index dbdaa40b02..7ed1554437 100644 --- a/coordinator/internal/config/config.go +++ b/coordinator/internal/config/config.go @@ -24,6 +24,8 @@ type ProverManager struct { ChunkCollectionTimeSec int `json:"chunk_collection_time_sec"` // BundleCollectionTimeSec bundle Proof collection time (in seconds). BundleCollectionTimeSec int `json:"bundle_collection_time_sec"` + // ProverSentryEndpoint the sentry endpoint being sent to each prover in login response + ProverSentryEndpoint string `json:"prover_sentry_endpoint"` } // L2 loads l2geth configuration items. diff --git a/coordinator/internal/controller/api/auth.go b/coordinator/internal/controller/api/auth.go index 07c676bba4..feef9f2f33 100644 --- a/coordinator/internal/controller/api/auth.go +++ b/coordinator/internal/controller/api/auth.go @@ -3,11 +3,14 @@ package api import ( "errors" "fmt" + "time" jwt "github.com/appleboy/gin-jwt/v2" "github.com/gin-gonic/gin" "gorm.io/gorm" + commonTypes "scroll-tech/common/types" + "scroll-tech/coordinator/internal/config" "scroll-tech/coordinator/internal/logic/auth" "scroll-tech/coordinator/internal/logic/verifier" @@ -16,12 +19,14 @@ import ( // AuthController is login API type AuthController struct { + cfg *config.Config loginLogic *auth.LoginLogic } // NewAuthController returns an LoginController instance func NewAuthController(db *gorm.DB, cfg *config.Config, vf *verifier.Verifier) *AuthController { return &AuthController{ + cfg: cfg, loginLogic: auth.NewLoginLogic(db, cfg, vf), } } @@ -98,3 +103,13 @@ func (a *AuthController) IdentityHandler(c *gin.Context) interface{} { return nil } + +// LoginResponse replies to client for /login +func (a *AuthController) LoginResponse(c *gin.Context, code int, message string, time time.Time) { + resp := types.LoginSchema{ + Time: time, + Token: message, + SentryEndpoint: a.cfg.ProverManager.ProverSentryEndpoint, + } + commonTypes.RenderSuccess(c, resp) +} diff --git a/coordinator/internal/middleware/login_jwt.go b/coordinator/internal/middleware/login_jwt.go index b04810b0b7..a067fad7f3 100644 --- a/coordinator/internal/middleware/login_jwt.go +++ b/coordinator/internal/middleware/login_jwt.go @@ -24,7 +24,7 @@ func LoginMiddleware(conf *config.Config) *jwt.GinJWTMiddleware { TokenLookup: "header: Authorization, query: token, cookie: jwt", TokenHeadName: "Bearer", TimeFunc: time.Now, - LoginResponse: loginResponse, + LoginResponse: api.Auth.LoginResponse, }) if err != nil { diff --git a/coordinator/internal/types/auth.go b/coordinator/internal/types/auth.go index a8b1c669ec..39f3a22681 100644 --- a/coordinator/internal/types/auth.go +++ b/coordinator/internal/types/auth.go @@ -24,8 +24,9 @@ const ( // LoginSchema for /login response type LoginSchema struct { - Time time.Time `json:"time"` - Token string `json:"token"` + Time time.Time `json:"time"` + Token string `json:"token"` + SentryEndpoint string `json:"sentry_endpoint,omitempty"` } // Message the login message struct diff --git a/prover/Cargo.lock b/prover/Cargo.lock index cff651cc37..e2fe397e8b 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -155,6 +155,17 @@ dependencies = [ "bytes", ] +[[package]] +name = "alterable_logger" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914a2c81a0e8d57d88d11554612d5e0afe5f942cecbcc239b10a394fd7ce404b" +dependencies = [ + "arc-swap", + "log", + "once_cell", +] + [[package]] name = "android-tzdata" version = "0.1.1" @@ -1081,6 +1092,16 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "serde", + "uuid 1.10.0", +] + [[package]] name = "der" version = "0.7.9" @@ -1091,6 +1112,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derivative" version = "2.2.0" @@ -1304,7 +1334,7 @@ dependencies = [ "sha2", "sha3 0.10.8", "thiserror", - "uuid", + "uuid 0.8.2", ] [[package]] @@ -1609,6 +1639,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "findshlibs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +dependencies = [ + "cc", + "lazy_static", + "libc", + "winapi", +] + [[package]] name = "fixed-hash" version = "0.8.0" @@ -2159,6 +2201,17 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "hostname" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "windows", +] + [[package]] name = "http" version = "0.2.12" @@ -2780,6 +2833,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-derive" version = "0.3.3" @@ -2974,6 +3033,17 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_info" +version = "3.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" +dependencies = [ + "log", + "serde", + "windows-sys 0.52.0", +] + [[package]] name = "pairing" version = "0.23.0" @@ -3205,6 +3275,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -3277,6 +3353,7 @@ dependencies = [ name = "prover" version = "0.1.0" dependencies = [ + "alterable_logger", "anyhow", "base64 0.13.1", "clap", @@ -3294,10 +3371,13 @@ dependencies = [ "prover 0.12.0", "prover 0.13.0", "rand", + "regex", "reqwest 0.12.4", "reqwest-middleware", "reqwest-retry", "rlp", + "sentry", + "sentry-log", "serde", "serde_json", "sled", @@ -3483,9 +3563,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -3561,6 +3641,7 @@ dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", + "futures-channel", "futures-core", "futures-util", "h2 0.4.5", @@ -4127,6 +4208,124 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +[[package]] +name = "sentry" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5484316556650182f03b43d4c746ce0e3e48074a21e2f51244b648b6542e1066" +dependencies = [ + "httpdate", + "native-tls", + "reqwest 0.12.4", + "sentry-backtrace", + "sentry-contexts", + "sentry-core", + "sentry-debug-images", + "sentry-panic", + "sentry-tracing", + "tokio", + "ureq", +] + +[[package]] +name = "sentry-backtrace" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40aa225bb41e2ec9d7c90886834367f560efc1af028f1c5478a6cce6a59c463a" +dependencies = [ + "backtrace", + "once_cell", + "regex", + "sentry-core", +] + +[[package]] +name = "sentry-contexts" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a8dd746da3d16cb8c39751619cefd4fcdbd6df9610f3310fd646b55f6e39910" +dependencies = [ + "hostname", + "libc", + "os_info", + "rustc_version 0.4.0", + "sentry-core", + "uname", +] + +[[package]] +name = "sentry-core" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "161283cfe8e99c8f6f236a402b9ccf726b201f365988b5bb637ebca0abbd4a30" +dependencies = [ + "once_cell", + "rand", + "sentry-types", + "serde", + "serde_json", +] + +[[package]] +name = "sentry-debug-images" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc6b25e945fcaa5e97c43faee0267eebda9f18d4b09a251775d8fef1086238a" +dependencies = [ + "findshlibs", + "once_cell", + "sentry-core", +] + +[[package]] +name = "sentry-log" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75bbcc61886955045a1dd4bdb173412a80bb2571be3c5bfcf7eb8f55a442bbf5" +dependencies = [ + "log", + "sentry-core", +] + +[[package]] +name = "sentry-panic" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc74f229c7186dd971a9491ffcbe7883544aa064d1589bd30b83fb856cd22d63" +dependencies = [ + "sentry-backtrace", + "sentry-core", +] + +[[package]] +name = "sentry-tracing" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c5faf2103cd01eeda779ea439b68c4ee15adcdb16600836e97feafab362ec" +dependencies = [ + "sentry-backtrace", + "sentry-core", + "tracing-core", + "tracing-subscriber", +] + +[[package]] +name = "sentry-types" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d68cdf6bc41b8ff3ae2a9c4671e97426dcdd154cc1d4b6b72813f285d6b163f" +dependencies = [ + "debugid", + "hex", + "rand", + "serde", + "serde_json", + "thiserror", + "time", + "url", + "uuid 1.10.0", +] + [[package]] name = "serde" version = "1.0.203" @@ -4589,6 +4788,37 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -4623,6 +4853,7 @@ dependencies = [ "bytes", "libc", "mio", + "num_cpus", "pin-project-lite", "socket2", "windows-sys 0.48.0", @@ -4760,6 +4991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", ] [[package]] @@ -4772,6 +5004,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "tracing-core", +] + [[package]] name = "try-lock" version = "0.2.5" @@ -4823,6 +5064,15 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "uname" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72f89f0ca32e4db1c04e2a72f5345d59796d4866a1ee0609084569f73683dc8" +dependencies = [ + "libc", +] + [[package]] name = "unarray" version = "0.1.4" @@ -4868,6 +5118,19 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72139d247e5f97a3eff96229a7ae85ead5328a39efe76f8bf5a06313d505b6ea" +dependencies = [ + "base64 0.22.1", + "log", + "native-tls", + "once_cell", + "url", +] + [[package]] name = "url" version = "2.5.0" @@ -4877,6 +5140,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] @@ -4901,6 +5165,15 @@ dependencies = [ "serde", ] +[[package]] +name = "uuid" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +dependencies = [ + "serde", +] + [[package]] name = "valuable" version = "0.1.0" @@ -5090,6 +5363,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets 0.52.5", +] + [[package]] name = "windows-core" version = "0.52.0" diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 36db6a39b2..d5358d4aae 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -21,6 +21,7 @@ bls12_381 = { git = "https://github.com/scroll-tech/bls12_381", branch = "feat/i anyhow = "1.0" log = "0.4" env_logger = "0.11.3" +alterable_logger = "1.0.0" serde = { version = "1.0.198", features = ["derive"] } serde_json = "1.0.116" futures = "0.3.30" @@ -46,3 +47,6 @@ sled = "0.34.7" http = "1.1.0" clap = { version = "4.5", features = ["derive"] } ctor = "0.2.8" +sentry = "0.34.0" +sentry-log = "0.34.0" +regex = "1.10.6" \ No newline at end of file diff --git a/prover/Makefile b/prover/Makefile index 6bcd3faa7f..79e681f2bd 100644 --- a/prover/Makefile +++ b/prover/Makefile @@ -35,8 +35,10 @@ else ZK_VERSION=${ZKEVM_COMMIT}-${HALO2_GPU_VERSION} endif +RELEASE_VERSION=${GO_TAG}-${GIT_REV}-${ZK_VERSION} + prover: - GO_TAG=${GO_TAG} GIT_REV=${GIT_REV} ZK_VERSION=${ZK_VERSION} cargo build --release + RELEASE_VERSION=${RELEASE_VERSION} cargo build --release tests_binary: cargo clean && cargo test --release --no-run diff --git a/prover/src/config.rs b/prover/src/config.rs index 4e3c1f2ccc..f47be301e7 100644 --- a/prover/src/config.rs +++ b/prover/src/config.rs @@ -1,4 +1,5 @@ use anyhow::{bail, Result}; +use regex::Regex; use serde::{Deserialize, Serialize}; use std::fs::File; @@ -49,6 +50,21 @@ impl Config { let file = File::open(file_name)?; Config::from_reader(&file) } + + pub fn partner_name(&self) -> String { + let prover_name = &self.prover_name; + let scroll_prefix = Regex::new(r"^scroll-.*").unwrap(); + let idc_prefix = Regex::new(r"^idc-.*").unwrap(); + + if scroll_prefix.is_match(prover_name) || idc_prefix.is_match(prover_name) { + let parts = prover_name.split('-').collect::>(); + format!("{}-{}", parts[0], parts[1]) + } else { + let split_re = Regex::new(r"[-_]").unwrap(); + let parts = split_re.split(prover_name).collect::>(); + parts[0].to_string() + } + } } static SCROLL_PROVER_ASSETS_DIR_ENV_NAME: &str = "SCROLL_PROVER_ASSETS_DIR"; diff --git a/prover/src/coordinator_client.rs b/prover/src/coordinator_client.rs index 46067d7ccf..a56a4aa83a 100644 --- a/prover/src/coordinator_client.rs +++ b/prover/src/coordinator_client.rs @@ -14,11 +14,12 @@ use types::*; use crate::{config::Config, key_signer::KeySigner}; -pub use errors::ProofStatusNotOKError; +pub use errors::{GetEmptyTaskError, ProofStatusNotOKError}; pub struct CoordinatorClient<'a> { api: Api, token: Option, + sentry_endpoint: Option, config: &'a Config, key_signer: Rc, rt: Runtime, @@ -46,6 +47,7 @@ impl<'a> CoordinatorClient<'a> { let mut client = Self { api, token: None, + sentry_endpoint: None, config, key_signer, rt, @@ -90,6 +92,7 @@ impl<'a> CoordinatorClient<'a> { } if let Some(r) = login_response.data { token = r.token; + self.sentry_endpoint = r.sentry_endpoint.filter(|s| !s.is_empty()); } else { bail!("login failed: got empty token") } @@ -139,4 +142,8 @@ impl<'a> CoordinatorClient<'a> { ) -> Result> { self.action_with_re_login(req, |s, req| s.do_submit_proof(req)) } + + pub fn get_sentry_dsn(&self) -> Option { + self.sentry_endpoint.clone() + } } diff --git a/prover/src/coordinator_client/api.rs b/prover/src/coordinator_client/api.rs index 905a1e61c5..d654de5a39 100644 --- a/prover/src/coordinator_client/api.rs +++ b/prover/src/coordinator_client/api.rs @@ -69,7 +69,15 @@ impl Api { token: &String, ) -> Result> { let method = "/coordinator/v1/get_task"; - self.post_with_token(method, req, token).await + let response = self + .post_with_token::>(method, req, token) + .await?; + + if response.errcode == ErrorCode::ErrCoordinatorEmptyProofData { + log::info!("coordinator return empty task"); + return Err(anyhow::anyhow!(GetEmptyTaskError)); + } + Ok(response) } pub async fn submit_proof( diff --git a/prover/src/coordinator_client/errors.rs b/prover/src/coordinator_client/errors.rs index 9bad256fac..55f0e37f0d 100644 --- a/prover/src/coordinator_client/errors.rs +++ b/prover/src/coordinator_client/errors.rs @@ -55,6 +55,15 @@ impl<'de> Deserialize<'de> for ErrorCode { // ==================================================== +#[derive(Debug, Clone)] +pub struct GetEmptyTaskError; + +impl fmt::Display for GetEmptyTaskError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "get empty task") + } +} + #[derive(Debug, Clone)] pub struct ProofStatusNotOKError; @@ -63,3 +72,30 @@ impl fmt::Display for ProofStatusNotOKError { write!(f, "proof status not ok") } } + +// =================================== tests module ======================================== + +#[cfg(test)] +mod tests { + use super::*; + use anyhow::{Context, Ok, Result}; + + #[ctor::ctor] + fn init() { + crate::utils::log_init(None); + log::info!("logger initialized"); + } + + #[test] + fn test_anyhow_error_is() -> Result<()> { + let err: Result<()> = + Err(anyhow::anyhow!(GetEmptyTaskError)).context("this is a test context"); + + assert!( + err.unwrap_err().is::(), + "error matches after anyhow context" + ); + + Ok(()) + } +} diff --git a/prover/src/coordinator_client/types.rs b/prover/src/coordinator_client/types.rs index c646a9afd4..d1e961b33e 100644 --- a/prover/src/coordinator_client/types.rs +++ b/prover/src/coordinator_client/types.rs @@ -52,6 +52,7 @@ pub struct LoginRequest { pub struct LoginResponseData { pub time: String, pub token: String, + pub sentry_endpoint: Option, } pub type ChallengeResponseData = LoginResponseData; diff --git a/prover/src/main.rs b/prover/src/main.rs index 75553187a9..f0048ca845 100644 --- a/prover/src/main.rs +++ b/prover/src/main.rs @@ -1,5 +1,6 @@ #![feature(lazy_cell)] #![feature(core_intrinsics)] +#![feature(const_option)] mod config; mod coordinator_client; @@ -38,6 +39,62 @@ struct Args { log_file: Option, } +fn start_loop<'a>( + config: &'a Config, + prover: &'a Prover<'a>, + task_cache: Rc, + log_file: Option, + current_dsn: Option, +) -> Option { + let mut new_dsn: Option = None; + let should_stop = || { + new_dsn = prover.coordinator_client.borrow().get_sentry_dsn(); + + current_dsn != new_dsn + }; + + let _guard = current_dsn.clone().map(|dsn| { + log::info!("successfully get dsn from coordinator"); + let gurad = sentry::init(( + dsn, + sentry::ClientOptions { + release: Some(version::get_version_cow()), + environment: Some(utils::get_environment()), + ..Default::default() + }, + )); + utils::set_logger_with_sentry(log_file); + gurad + }); + + _guard.iter().for_each(|_| { + sentry::configure_scope(|scope| { + scope.set_tag("prover_type", config.prover_type); + scope.set_tag("partner_name", config.partner_name()); + scope.set_tag("prover_name", config.prover_name.clone()); + + let public_key = sentry::protocol::Value::from(prover.get_public_key()); + scope.set_extra("public_key", public_key); + }); + + sentry::capture_message("test message on start", sentry::Level::Info); + }); + + log::info!( + "prover start successfully. name: {}, type: {:?}, publickey: {}, version: {}", + config.prover_name, + config.prover_type, + prover.get_public_key(), + version::get_version(), + ); + + let task_processor = TaskProcessor::new(prover, task_cache); + + task_processor.start(should_stop); + + new_dsn +} + fn start() -> Result<()> { let args = Args::parse(); @@ -46,10 +103,10 @@ fn start() -> Result<()> { std::process::exit(0); } - utils::log_init(args.log_file); - let config: Config = Config::from_file(args.config_file)?; + utils::log_init(args.log_file.clone()); + if let Err(e) = AssetsDirEnvConfig::init() { log::error!("AssetsDirEnvConfig init failed: {:#}", e); std::process::exit(-2); @@ -63,19 +120,16 @@ fn start() -> Result<()> { let prover = Prover::new(&config, coordinator_listener)?; - log::info!( - "prover start successfully. name: {}, type: {:?}, publickey: {}, version: {}", - config.prover_name, - config.prover_type, - prover.get_public_key(), - version::get_version(), - ); - - let task_processor = TaskProcessor::new(&prover, task_cache); - - task_processor.start(); - - Ok(()) + let mut current_dsn = None; + loop { + current_dsn = start_loop( + &config, + &prover, + task_cache.clone(), + args.log_file.clone(), + current_dsn, + ); + } } fn main() { diff --git a/prover/src/prover.rs b/prover/src/prover.rs index 7de83906e0..963d9bd47f 100644 --- a/prover/src/prover.rs +++ b/prover/src/prover.rs @@ -19,7 +19,7 @@ pub struct Prover<'a> { config: &'a Config, key_signer: Rc, circuits_handler_provider: RefCell>, - coordinator_client: RefCell>, + pub coordinator_client: RefCell>, geth_client: Option>>, } diff --git a/prover/src/task_processor.rs b/prover/src/task_processor.rs index df4629d5bd..f92990fb11 100644 --- a/prover/src/task_processor.rs +++ b/prover/src/task_processor.rs @@ -1,4 +1,8 @@ -use super::{coordinator_client::ProofStatusNotOKError, prover::Prover, task_cache::TaskCache}; +use super::{ + coordinator_client::{GetEmptyTaskError, ProofStatusNotOKError}, + prover::Prover, + task_cache::TaskCache, +}; use anyhow::{Context, Result}; use std::rc::Rc; @@ -12,11 +16,20 @@ impl<'a> TaskProcessor<'a> { TaskProcessor { prover, task_cache } } - pub fn start(&self) { + pub fn start(&self, mut should_stop: F) + where + F: FnMut() -> bool, + { loop { + if should_stop() { + log::info!("task processor should stop."); + break; + } log::info!("start a new round."); if let Err(err) = self.prove_and_submit() { - if err.is::() { + if err.is::() { + log::info!("get empty task, skip."); + } else if err.is::() { log::info!("proof status not ok, downgrade level to info."); } else { log::error!("encounter error: {:#}", err); diff --git a/prover/src/types.rs b/prover/src/types.rs index 513995d6d1..e5a8048d4c 100644 --- a/prover/src/types.rs +++ b/prover/src/types.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use ethers_core::types::H256; use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -101,6 +103,13 @@ impl<'de> Deserialize<'de> for ProverType { } } +impl Display for ProverType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(format!("{:?}", self).as_str())?; + Ok(()) + } +} + #[derive(Serialize, Deserialize, Default)] pub struct Task { pub uuid: String, @@ -243,3 +252,27 @@ impl Default for ProofStatus { Self::Ok } } + +// =================================== tests module ======================================== + +#[cfg(test)] +mod tests { + use super::*; + use anyhow::{Ok, Result}; + + #[ctor::ctor] + fn init() { + crate::utils::log_init(None); + log::info!("logger initialized"); + } + + #[test] + fn test_prover_type_display() -> Result<()> { + let chunk = ProverType::Chunk; + let batch = ProverType::Batch; + + assert_eq!(chunk.to_string(), "Chunk"); + assert_eq!(batch.to_string(), "Batch"); + Ok(()) + } +} diff --git a/prover/src/utils.rs b/prover/src/utils.rs index 18be4ac7a1..b6db76fa95 100644 --- a/prover/src/utils.rs +++ b/prover/src/utils.rs @@ -1,27 +1,36 @@ use env_logger::Env; -use std::{fs::OpenOptions, sync::Once}; +use std::{borrow::Cow, fs::OpenOptions}; use crate::types::{ProverType, TaskType}; -static LOG_INIT: Once = Once::new(); +pub fn build_logger(log_file: Option) -> env_logger::Logger { + let mut builder = env_logger::Builder::from_env(Env::default().default_filter_or("info")); + if let Some(file_path) = log_file { + let target = Box::new( + OpenOptions::new() + .write(true) + .create(true) + .truncate(false) + .open(file_path) + .expect("Can't create log file"), + ); + builder.target(env_logger::Target::Pipe(target)); + } + builder.build() +} -/// Initialize log pub fn log_init(log_file: Option) { - LOG_INIT.call_once(|| { - let mut builder = env_logger::Builder::from_env(Env::default().default_filter_or("info")); - if let Some(file_path) = log_file { - let target = Box::new( - OpenOptions::new() - .write(true) - .create(true) - .truncate(false) - .open(file_path) - .expect("Can't create log file"), - ); - builder.target(env_logger::Target::Pipe(target)); - } - builder.init(); - }); + let logger = build_logger(log_file); + let max_level = logger.filter(); + let boxed_logger = Box::new(logger); + alterable_logger::configure(max_level, boxed_logger); +} + +pub fn set_logger_with_sentry(log_file: Option) { + let logger = build_logger(log_file); + let max_level = logger.filter(); + let boxed_logger = Box::new(sentry_log::SentryLogger::with_dest(logger)); + alterable_logger::configure(max_level, boxed_logger); } pub fn get_task_types(prover_type: ProverType) -> Vec { @@ -30,3 +39,20 @@ pub fn get_task_types(prover_type: ProverType) -> Vec { ProverType::Batch => vec![TaskType::Batch, TaskType::Bundle], } } + +static ENV_UNKNOWN: &str = "unknown"; +static ENV_DEVNET: &str = "devnet"; +static ENV_SEPOLIA: &str = "sepolia"; +static ENV_MAINNET: &str = "mainnet"; + +pub fn get_environment() -> Cow<'static, str> { + let env: &'static str = match std::env::var("CHAIN_ID") { + Ok(chain_id) => match chain_id.as_str() { + "534352" => ENV_MAINNET, + "534351" => ENV_SEPOLIA, + _ => ENV_DEVNET, + }, + Err(_) => ENV_UNKNOWN, + }; + std::borrow::Cow::Borrowed(env) +} diff --git a/prover/src/version.rs b/prover/src/version.rs index 76249adeae..11de9d59cb 100644 --- a/prover/src/version.rs +++ b/prover/src/version.rs @@ -1,18 +1,36 @@ -use std::cell::OnceCell; +use std::borrow::Cow; -static DEFAULT_COMMIT: &str = "unknown"; -static mut VERSION: OnceCell = OnceCell::new(); +static RELEASE_VERSION: Option<&str> = option_env!("RELEASE_VERSION"); +const DEFAULT_VERSION: &str = "v0.0.0-unknown-000000-000000"; -pub const TAG: &str = "v0.0.0"; -pub const DEFAULT_ZK_VERSION: &str = "000000-000000"; +pub fn get_version() -> String { + RELEASE_VERSION.unwrap_or(DEFAULT_VERSION).to_string() +} -fn init_version() -> String { - let commit = option_env!("GIT_REV").unwrap_or(DEFAULT_COMMIT); - let tag = option_env!("GO_TAG").unwrap_or(TAG); - let zk_version = option_env!("ZK_VERSION").unwrap_or(DEFAULT_ZK_VERSION); - format!("{tag}-{commit}-{zk_version}") +pub fn get_version_cow() -> Cow<'static, str> { + let v = RELEASE_VERSION.unwrap_or(DEFAULT_VERSION); + std::borrow::Cow::Borrowed(v) } -pub fn get_version() -> String { - unsafe { VERSION.get_or_init(init_version).clone() } +// =================================== tests module ======================================== + +#[cfg(test)] +mod tests { + use super::*; + use anyhow::{Ok, Result}; + + #[ctor::ctor] + fn init() { + crate::utils::log_init(None); + log::info!("logger initialized"); + } + + #[test] + fn test_get_version_cow() -> Result<()> { + let version = get_version_cow(); + + assert_eq!(get_version(), DEFAULT_VERSION); + assert_eq!(&version, DEFAULT_VERSION); + Ok(()) + } }