From b357d22f8565a2709492bff3257130dfd1cf283f Mon Sep 17 00:00:00 2001 From: Igor Zhirkov Date: Mon, 25 Nov 2024 12:01:13 +0100 Subject: [PATCH 1/3] first commit: adoption --- Cargo.lock | 93 ++++++++++++++++- Cargo.toml | 1 + errors-era-test-node.json | 17 ++++ root.json | 209 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 41 ++++++-- 5 files changed, 346 insertions(+), 15 deletions(-) create mode 100644 errors-era-test-node.json create mode 100644 root.json diff --git a/Cargo.lock b/Cargo.lock index cda07a6f..5ee43f54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2508,6 +2508,7 @@ dependencies = [ "tracing-subscriber", "zksync-web3-rs", "zksync_contracts", + "zksync_error", "zksync_multivm", "zksync_types", "zksync_utils", @@ -3404,6 +3405,10 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] [[package]] name = "hashbrown" @@ -5840,9 +5845,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -6115,6 +6120,16 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "regress" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1541daf4e4ed43a0922b7969bdc2170178bcacc5dabf7e39bc508a9fa3953a7a" +dependencies = [ + "hashbrown 0.14.5", + "memchr", +] + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -6931,6 +6946,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_tokenstream" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64060d864397305347a78851c51588fd283767e7e7589829e8121d65512340f1" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "syn 2.0.87", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -8038,6 +8065,53 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "typify" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c644dda9862f0fef3a570d8ddb3c2cfb1d5ac824a1f2ddfa7bc8f071a5ad8a" +dependencies = [ + "typify-impl", + "typify-macro", +] + +[[package]] +name = "typify-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59ab345b6c0d8ae9500b9ff334a4c7c0d316c1c628dc55726b95887eb8dbd11" +dependencies = [ + "heck 0.5.0", + "log", + "proc-macro2", + "quote", + "regress", + "schemars", + "semver 1.0.23", + "serde", + "serde_json", + "syn 2.0.87", + "thiserror", + "unicode-ident", +] + +[[package]] +name = "typify-macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "785e2cdcef0df8160fdd762ed548a637aaec1e83704fdbc14da0df66013ee8d0" +dependencies = [ + "proc-macro2", + "quote", + "schemars", + "semver 1.0.23", + "serde", + "serde_json", + "serde_tokenstream", + "syn 2.0.87", + "typify-impl", +] + [[package]] name = "ucd-trie" version = "0.1.7" @@ -8088,9 +8162,9 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-normalization" @@ -9294,6 +9368,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "zksync_error" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", + "strum 0.26.3", + "strum_macros 0.26.4", + "typify", +] + [[package]] name = "zksync_ff" version = "0.30.1" diff --git a/Cargo.toml b/Cargo.toml index cd31d99a..44558312 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ indexmap = "2.0.1" chrono = { version = "0.4.31", default-features = false } time = "0.3.36" rand = "0.8" +zksync_error = { path = "../zksync_error" } [dev-dependencies] httptest = "0.15.4" diff --git a/errors-era-test-node.json b/errors-era-test-node.json new file mode 100644 index 00000000..fcda2132 --- /dev/null +++ b/errors-era-test-node.json @@ -0,0 +1,17 @@ +{ + "component_name": "TestNode", + "component_code": 2, + "errors": [ + { + "name": "TestNodeError", + "code": 1, + "message": "Some error in EraTestNode happened: {inner}.", + "fields": [ + { + "name": "inner", + "type": "WrappedErrorMessage" + } + ] + } + ] +} diff --git a/root.json b/root.json new file mode 100644 index 00000000..22df5980 --- /dev/null +++ b/root.json @@ -0,0 +1,209 @@ +{ + "types": [ + { + "name": "uint", + "description": "Unsigned 32-bit integer", + "bindings": { + "rust": + { + "name": "u32", + "path": "" + } + } + }, + { + "name": "string", + "description": "Unicode zero-terminated string", + "bindings": { + "rust": { + "name": "String", + "path": "" + } + } + }, + { + "name": "WrappedError", + "description": "Any wrapped error", + "bindings": { + "rust": { + "name": "serde_json::Value", + "path": "" + } + } + }, + { + "name": "WrappedErrorMessage", + "description": "Any wrapped error message", + "bindings": { + "rust": { + "name": "String", + "path": "" + } + } + } + ], + "domains": [ + { + "domain_name": "compiler", + "domain_code": 1, + "identifier_encoding": "comp", + "description": "Errors in compilers: zksolc, solc, zkvyper, etc.", + "bindings": { + "rust": "Compiler" + }, + "components" : [ + { + "component_name": "zksolc", + "component_code": 1, + "identifier_encoding": "zksolc", + "description": "Errors in zksolc compiler", + "bindings": { + "rust" : "Zksolc" + }, + "errors" : + [ + { + "name": "Umbrella", + "code": 42, + "message": "Any error!", + "bindings": { + "rust": + { + "name": "Umbrella" + } + }, + "fields": [ + { + "name": "inner", + "type": "WrappedError" + } + ] + }, + { + "name": "SolcNotFound", + "code": 1, + "message": "I just can't find solc!", + "bindings": { + "rust": + { + "name": "SolcNotFound" + } + }, + "fields": [ + { + "name": "path", + "type": "string" + }, + { + "name": "payload", + "type": "uint" + } + + ] + }, + { + "name": "FileNotFound", + "code": 2, + "message": "Can't find the file {path} to compile.", + "bindings": { + "rust": + { + "name": "FileNotFound" + }, + "typescript": + { + "name": "TSFileNotFound" + } + }, + "fields": [ + { + "name": "path", + "type": "string" + }, + { + "name": "file_index", + "type": "uint" + } + + ], + "doc" : { + "description": "The compiler is unable to find the file with the source code that it needs", + "short_description": "No input file", + "likely_causes": [ + { + "cause": "You did not provide a file to compile", + "fixes": [ + "Check if you have provided a correct Solidity or YUL file to compile." + ], + "report": "https://matter-labs.io", + "owner": { + "name": "solc", + "version": "> 1.0.0" + } + } + ], + "references": ["https://matter-labs.io", "https://github.com"] + } + } + + ] + + } + ] + }, + { + "domain_name": "core", + "domain_code": 2, + "identifier_encoding": "core", + "description": "Errors in core components such as sequencer", + "bindings": { + "rust": "Core" + }, + "components" : [ + { + "component_name": "Sequencer", + "component_code": 1, + "identifier_encoding": "seq", + "bindings": { + "rust": "Sequencer", + "typescript": "Sequencer" + }, + "description": "Errors in core components such as sequencer", + "errors" : [ + { + "name": "NotFound", + "code": 1, + "message": "I just can't find solc!", + "bindings": { + "rust": + { + "name": "NotFound" + } + }, + "fields": [ + { + "name": "path", + "type": "string" + } + ] + } + ] + }, + { + "component_name": "TestNode", + "component_code": 2, + "identifier_encoding": "testnode", + "bindings": { + "rust": "TestNode" + }, + "description": "Errors in Era Test Node", + "takeFrom": [ + "errors-era-test-node.json" + ] + } + + ] + } + ] +} + diff --git a/src/main.rs b/src/main.rs index c6b83689..35065a2c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,6 +55,11 @@ use crate::namespaces::{ ZksNamespaceT, }; +use zksync_error::error::definitions::TestNode; +use zksync_error::packed::pack; +use zksync_error::serialized::serialize; +use zksync_error::serialized::SerializedError; + #[allow(clippy::too_many_arguments)] async fn build_json_http< S: std::marker::Sync + std::marker::Send + 'static + ForkSource + std::fmt::Debug + Clone, @@ -107,21 +112,32 @@ async fn build_json_http< } #[tokio::main] -async fn main() -> anyhow::Result<()> { +async fn main() -> Result<(), SerializedError> { + fn generic_error(e: T) -> SerializedError { + serialize(pack(TestNode::TestNodeError { + inner: e.to_string(), + })) + .unwrap() + } + fn generic_error_msg(msg: impl Into) -> SerializedError { + serialize(pack(TestNode::TestNodeError { inner: msg.into() })).unwrap() + } + // Check for deprecated options Cli::deprecated_config_option(); let opt = Cli::parse(); let command = opt.command.clone(); - let mut config = opt.into_test_node_config().map_err(|e| anyhow!(e))?; + let mut config = opt.into_test_node_config().map_err(generic_error)?; let log_level_filter = LevelFilter::from(config.log_level); - let log_file = File::create(&config.log_file_path)?; + let log_file = File::create(&config.log_file_path).map_err(generic_error)?; // Initialize the tracing subscriber let observability = - Observability::init(vec!["era_test_node".into()], log_level_filter, log_file)?; + Observability::init(vec!["era_test_node".into()], log_level_filter, log_file) + .map_err(generic_error)?; // Use `Command::Run` as default. let command = command.as_ref().unwrap_or(&Command::Run); @@ -135,12 +151,13 @@ async fn main() -> anyhow::Result<()> { None } else { // Initialize the client to get the fee params - let (_, client) = ForkDetails::fork_network_and_client("mainnet") - .map_err(|e| anyhow!("Failed to initialize client: {:?}", e))?; + let (_, client) = ForkDetails::fork_network_and_client("mainnet").map_err(|e| { + generic_error_msg(format!("Failed to initialize client: {e:?}")) + })?; let fee = client.get_fee_params().await.map_err(|e| { tracing::error!("Failed to fetch fee params: {:?}", e); - anyhow!(e) + generic_error(e) })?; match fee { @@ -153,7 +170,9 @@ async fn main() -> anyhow::Result<()> { .with_l1_pubdata_price(Some(fee_v2.l1_pubdata_price())); } FeeParams::V1(_) => { - return Err(anyhow!("Unsupported FeeParams::V1 in this context")); + return Err(generic_error_msg( + "Unsupported FeeParams::V1 in this context", + )); } } @@ -181,7 +200,7 @@ async fn main() -> anyhow::Result<()> { } Err(error) => { tracing::error!("cannot fork: {:?}", error); - return Err(anyhow!(error)); + return Err(generic_error(error)); } } } @@ -206,7 +225,7 @@ async fn main() -> anyhow::Result<()> { } Err(error) => { tracing::error!("cannot replay: {:?}", error); - return Err(anyhow!(error)); + return Err(generic_error(error)); } } } @@ -226,7 +245,7 @@ async fn main() -> anyhow::Result<()> { "failed to get earlier transactions in the same block for replay tx: {:?}", error ); - return Err(anyhow!(error)); + return Err(generic_error(error)); } } } else { From 188f3b5200bb7a0871b4d04378794f7c4abc66c1 Mon Sep 17 00:00:00 2001 From: Igor Zhirkov Date: Mon, 25 Nov 2024 12:07:45 +0100 Subject: [PATCH 2/3] second commit: first custom error type --- errors-era-test-node.json | 15 +++++++++++++++ src/main.rs | 8 +++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/errors-era-test-node.json b/errors-era-test-node.json index fcda2132..efcdc0f5 100644 --- a/errors-era-test-node.json +++ b/errors-era-test-node.json @@ -12,6 +12,21 @@ "type": "WrappedErrorMessage" } ] + }, + { + "name": "LogFileCreationError", + "code": 2, + "message": "Unable to create log file {path}: {inner}", + "fields": [ + { + "name": "path", + "type": "string" + }, + { + "name": "inner", + "type": "WrappedErrorMessage" + } + ] } ] } diff --git a/src/main.rs b/src/main.rs index 35065a2c..c2acc4c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -132,7 +132,13 @@ async fn main() -> Result<(), SerializedError> { let mut config = opt.into_test_node_config().map_err(generic_error)?; let log_level_filter = LevelFilter::from(config.log_level); - let log_file = File::create(&config.log_file_path).map_err(generic_error)?; + let log_file = File::create(&config.log_file_path).map_err(|e| { + serialize(pack(TestNode::LogFileCreationError { + path: config.log_file_path.to_string(), + inner: e.to_string(), + })) + .unwrap() + })?; // Initialize the tracing subscriber let observability = From 8a97b94b349d068b7715ef0b74c13aa6e5e268be Mon Sep 17 00:00:00 2001 From: Igor Zhirkov Date: Mon, 25 Nov 2024 22:28:59 +0100 Subject: [PATCH 3/3] fixup! second commit: first custom error type --- src/main.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/main.rs b/src/main.rs index c2acc4c2..089cc09e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,8 +56,6 @@ use crate::namespaces::{ }; use zksync_error::error::definitions::TestNode; -use zksync_error::packed::pack; -use zksync_error::serialized::serialize; use zksync_error::serialized::SerializedError; #[allow(clippy::too_many_arguments)] @@ -113,14 +111,13 @@ async fn build_json_http< #[tokio::main] async fn main() -> Result<(), SerializedError> { - fn generic_error(e: T) -> SerializedError { - serialize(pack(TestNode::TestNodeError { + fn generic_error(e: T) -> TestNode { + TestNode::TestNodeError { inner: e.to_string(), - })) - .unwrap() + }.into() } - fn generic_error_msg(msg: impl Into) -> SerializedError { - serialize(pack(TestNode::TestNodeError { inner: msg.into() })).unwrap() + fn generic_error_msg(msg: impl Into) -> TestNode { + TestNode::TestNodeError { inner: msg.into() }.into() } // Check for deprecated options @@ -133,11 +130,10 @@ async fn main() -> Result<(), SerializedError> { let log_level_filter = LevelFilter::from(config.log_level); let log_file = File::create(&config.log_file_path).map_err(|e| { - serialize(pack(TestNode::LogFileCreationError { + TestNode::LogFileCreationError { path: config.log_file_path.to_string(), inner: e.to_string(), - })) - .unwrap() + } })?; // Initialize the tracing subscriber