From 0c9d64c5f9c9c37452ced2eca82be0bed596811c Mon Sep 17 00:00:00 2001 From: Nicolas Villanueva Date: Mon, 31 Jul 2023 13:56:16 +0200 Subject: [PATCH] Add new configuration RPC endpoints (#17) feat: Add new configuration RPC endpoints (config_getShowCalls, config_setShowCalls, and config_setResolveHashes). Add example http REST file for quickly testing the node locally. Add recommended plugins for VSCode. Add SUPPORTED_APIS.md. Update version to 1.0.3 --- .gitignore | 3 +- .vscode/extensions.json | 6 +++ Cargo.lock | 4 +- Cargo.toml | 4 +- README.md | 4 ++ SUPPORTED_APIS.md | 82 ++++++++++++++++++++++++++++++++++++++++ src/configuration_api.rs | 78 ++++++++++++++++++++++++++++++++++++++ src/main.rs | 23 ++++++++++- src/node.rs | 6 ++- test_endpoints.http | 56 +++++++++++++++++++++++++++ 10 files changed, 261 insertions(+), 5 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 SUPPORTED_APIS.md create mode 100644 src/configuration_api.rs create mode 100644 test_endpoints.http diff --git a/.gitignore b/.gitignore index ef0f815f..3a5e52c4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ etc/system-contracts/.yarnrc.yml etc/system-contracts/bootloader/build etc/**/*.zbin -.vscode/ +.vscode/* +!.vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..f3877065 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "rust-lang.rust-analyzer", + "humao.rest-client", + ], +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 688366b5..5ed1f065 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1712,7 +1712,7 @@ checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" [[package]] name = "era_test_node" -version = "1.0.2" +version = "1.0.3" dependencies = [ "anyhow", "bigdecimal", @@ -1724,6 +1724,8 @@ dependencies = [ "hex", "itertools", "jsonrpc-core 18.0.0 (git+https://github.com/matter-labs/jsonrpc.git?branch=master)", + "jsonrpc-core-client", + "jsonrpc-derive", "jsonrpc-http-server", "lazy_static", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 23f2ce8e..120c0f63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "era_test_node" -version = "1.0.2" +version = "1.0.3" edition = "2018" authors = ["The Matter Labs Team "] homepage = "https://zksync.io/" @@ -29,6 +29,8 @@ once_cell = "1.7" jsonrpc-http-server = { git = "https://github.com/matter-labs/jsonrpc.git", branch = "master" } jsonrpc-core = { git = "https://github.com/matter-labs/jsonrpc.git", branch = "master" } +jsonrpc-core-client = { git = "https://github.com/matter-labs/jsonrpc.git", branch = "master" } +jsonrpc-derive = { git = "https://github.com/matter-labs/jsonrpc.git", branch = "master" } clap = { version = "4.2.4", features = ["derive"] } reqwest = { version = "0.11", features = ["blocking"] } diff --git a/README.md b/README.md index 36b97017..eea71890 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,10 @@ Here's a list of the available rich wallets: Feel free to use these wallets in your tests, but remember, they are for development purposes only and should not be used in production or with real assets. +## 🔧 Supported APIs + +See our list of [Supported APIs here](SUPPORTED_APIS.md). + ## 🤝 Contributing We welcome contributions from the community! If you're interested in contributing to the zkSync Era In-Memory Node, please take a look at our [CONTRIBUTING.md](./.github/CONTRIBUTING.md) for guidelines and details on the process. diff --git a/SUPPORTED_APIS.md b/SUPPORTED_APIS.md new file mode 100644 index 00000000..cde44e42 --- /dev/null +++ b/SUPPORTED_APIS.md @@ -0,0 +1,82 @@ +# 🔧 Supported APIs for In-Memory Node 🔧 + +> ⚠️ **WORK IN PROGRESS**: This list is non-comprehensive and being updated + +# Key + +The `status` options are: + ++ `SUPPORTED` - Basic support is complete ++ `PARTIALLY` - Partial support and a description including more specific details ++ `NOT IMPLEMENTED` - Currently not supported/implemented + +# `CONFIG NAMESPACE` + +## `config_getShowCalls` + +[source](src/configuration_api.rs) + +Gets the current value of `show_calls` that's originally set with `--show-calls` option + +### Arguments + ++ _NONE_ + +### Status + +`SUPPORTED` + +### Example + +```bash +curl --request POST \ + --url http://localhost:8011/ \ + --header 'content-type: application/json' \ + --data '{"jsonrpc": "2.0","id": "1","method": "config_getShowCalls","params": []}' +``` + +## `config_setShowCalls` + +[source](src/configuration_api.rs) + +Updates `show_calls` to print more detailed call traces + +### Arguments + ++ `value: String ('None', 'User', 'System', 'All')` + +### Status + +`SUPPORTED` + +### Example + +```bash +curl --request POST \ + --url http://localhost:8011/ \ + --header 'content-type: application/json' \ + --data '{"jsonrpc": "2.0","id": "1","method": "config_setShowCalls","params": ["all"]}' +``` + +## `config_setResolveHashes` + +[source](src/configuration_api.rs) + +Updates `resolve-hashes` to call OpenChain for human-readable ABI names in call traces + +### Arguments + ++ `value: boolean` + +### Status + +`SUPPORTED` + +### Example + +```bash +curl --request POST \ + --url http://localhost:8011/ \ + --header 'content-type: application/json' \ + --data '{"jsonrpc": "2.0","id": "1","method": "config_setResolveHashes","params": [true]}' +``` diff --git a/src/configuration_api.rs b/src/configuration_api.rs new file mode 100644 index 00000000..a9b4ecb1 --- /dev/null +++ b/src/configuration_api.rs @@ -0,0 +1,78 @@ +// Built-in uses +use std::sync::{Arc, RwLock}; + +// External uses +use jsonrpc_core::Result; +use jsonrpc_derive::rpc; + +// Workspace uses + +// Local uses +use crate::{node::InMemoryNodeInner, ShowCalls}; + +pub struct ConfigurationApiNamespace { + node: Arc>, +} + +impl ConfigurationApiNamespace { + pub fn new(node: Arc>) -> Self { + Self { node } + } +} + +#[rpc] +pub trait ConfigurationApiNamespaceT { + /// Get the InMemoryNodeInner's show_calls property as a string + /// + /// # Returns + /// The current `show_calls` value for the InMemoryNodeInner. + #[rpc(name = "config_getShowCalls", returns = "String")] + fn config_get_show_calls(&self) -> Result; + + /// Set show_calls for the InMemoryNodeInner + /// + /// # Parameters + /// - `value`: A ShowCalls enum to update show_calls to + /// + /// # Returns + /// The updated/current `show_calls` value for the InMemoryNodeInner. + #[rpc(name = "config_setShowCalls", returns = "String")] + fn config_set_show_calls(&self, value: String) -> Result; + + /// Set resolve_hashes for the InMemoryNodeInner + /// + /// # Parameters + /// - `value`: A bool to update resolve_hashes to + /// + /// # Returns + /// The updated `resolve_hashes` value for the InMemoryNodeInner. + #[rpc(name = "config_setResolveHashes", returns = "bool")] + fn config_set_resolve_hashes(&self, value: bool) -> Result; +} + +impl ConfigurationApiNamespaceT for ConfigurationApiNamespace { + fn config_get_show_calls(&self) -> Result { + let reader = self.node.read().unwrap(); + Ok(reader.show_calls.to_string()) + } + + fn config_set_show_calls(&self, value: String) -> Result { + let show_calls = match value.parse::() { + Ok(value) => value, + Err(_) => { + let reader = self.node.read().unwrap(); + return Ok(reader.show_calls.to_string()); + } + }; + + let mut inner = self.node.write().unwrap(); + inner.show_calls = show_calls; + Ok(inner.show_calls.to_string()) + } + + fn config_set_resolve_hashes(&self, value: bool) -> Result { + let mut inner = self.node.write().unwrap(); + inner.resolve_hashes = value; + Ok(inner.resolve_hashes) + } +} diff --git a/src/main.rs b/src/main.rs index 5f113fe5..80bf7ad5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ use clap::{Parser, Subcommand}; +use configuration_api::ConfigurationApiNamespaceT; use fork::ForkDetails; use zks::ZkMockNamespaceImpl; +mod configuration_api; mod console_log; mod deps; mod fork; @@ -32,7 +34,7 @@ use futures::{ use jsonrpc_core::IoHandler; use zksync_basic_types::{L2ChainId, H160, H256}; -use crate::node::TEST_NODE_NETWORK_ID; +use crate::{configuration_api::ConfigurationApiNamespace, node::TEST_NODE_NETWORK_ID}; use zksync_core::api_server::web3::backend_jsonrpc::namespaces::{ eth::EthNamespaceT, net::NetNamespaceT, zks::ZksNamespaceT, }; @@ -61,6 +63,7 @@ async fn build_json_http( addr: SocketAddr, node: InMemoryNode, net: NetNamespace, + config_api: ConfigurationApiNamespace, ) -> tokio::task::JoinHandle<()> { let (sender, recv) = oneshot::channel::<()>(); @@ -68,6 +71,7 @@ async fn build_json_http( let mut io = IoHandler::new(); io.extend_with(node.to_delegate()); io.extend_with(net.to_delegate()); + io.extend_with(config_api.to_delegate()); io.extend_with(ZkMockNamespaceImpl.to_delegate()); io @@ -123,6 +127,20 @@ pub enum ShowCalls { All, } +impl FromStr for ShowCalls { + type Err = (); + + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_ref() { + "none" => Ok(ShowCalls::None), + "user" => Ok(ShowCalls::User), + "system" => Ok(ShowCalls::System), + "all" => Ok(ShowCalls::All), + _ => Err(()), + } + } +} + impl Display for ShowCalls { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { write!(f, "{:?}", self) @@ -231,10 +249,13 @@ async fn main() -> anyhow::Result<()> { let net = NetNamespace::new(L2ChainId(TEST_NODE_NETWORK_ID)); + let config_api = ConfigurationApiNamespace::new(node.get_inner()); + let threads = build_json_http( SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), opt.port), node, net, + config_api, ) .await; diff --git a/src/node.rs b/src/node.rs index 37cc1d08..8cb4d6c2 100644 --- a/src/node.rs +++ b/src/node.rs @@ -227,6 +227,10 @@ impl InMemoryNode { } } + pub fn get_inner(&self) -> Arc> { + self.inner.clone() + } + /// Applies multiple transactions - but still one per L1 batch. pub fn apply_txs(&self, txs: Vec) { println!("Running {:?} transactions (one per batch)", txs.len()); @@ -386,7 +390,7 @@ impl InMemoryNode { } println!( - "\n==== {} Use --show-calls flag to display more info.", + "\n==== {} Use --show-calls flag or call config_setResolveHashes to display more info.", format!("{:?} call traces. ", tx_result.call_traces.len()).bold() ); diff --git a/test_endpoints.http b/test_endpoints.http new file mode 100644 index 00000000..f4796f72 --- /dev/null +++ b/test_endpoints.http @@ -0,0 +1,56 @@ +POST http://localhost:8011 +content-type: application/json + +{ + "jsonrpc": "2.0", + "id": "1", + "method": "eth_blockNumber", + "params": [] +} + +### +POST http://localhost:8011 +content-type: application/json + +{ + "jsonrpc": "2.0", + "id": "1", + "method": "net_version", + "params": [] +} + +### +POST http://localhost:8011 +content-type: application/json + +{ + "jsonrpc": "2.0", + "id": "1", + "method": "config_getShowCalls", + "params": [] +} + +### +POST http://localhost:8011 +content-type: application/json + +{ + "jsonrpc": "2.0", + "id": "1", + "method": "config_setShowCalls", + "params": ["All"] +} + +### +POST http://localhost:8011 +content-type: application/json + +{ + "jsonrpc": "2.0", + "id": "1", + "method": "config_setResolveHashes", + "params": [true] +} + +### +