From b1d937344adbc14a30968211cdeb77da689a6c51 Mon Sep 17 00:00:00 2001 From: mw2000 Date: Mon, 28 Oct 2024 23:30:46 -0700 Subject: [PATCH 1/6] feat(web3_clientVersion): Adds RPC method to fetch client version We add the RPC method to fetch the client version via web3_clientVersion. This is also the get_client_version function while calling from a the rust client. Tested with function call in examples/basic.rs. This should tackle #412 --- core/src/client/mod.rs | 4 ++++ core/src/client/node.rs | 4 ++++ core/src/client/rpc.rs | 6 ++++++ core/src/execution/mod.rs | 4 ++++ core/src/execution/rpc/http_rpc.rs | 8 ++++++++ core/src/execution/rpc/mock_rpc.rs | 4 ++++ core/src/execution/rpc/mod.rs | 1 + examples/basic.rs | 2 ++ helios-ts/lib.ts | 3 +++ helios-ts/src/ethereum.rs | 5 +++++ helios-ts/src/opstack.rs | 6 ++++++ rpc.md | 1 + 12 files changed, 48 insertions(+) diff --git a/core/src/client/mod.rs b/core/src/client/mod.rs index 6d1a31f8..dcf49efb 100644 --- a/core/src/client/mod.rs +++ b/core/src/client/mod.rs @@ -153,6 +153,10 @@ impl> Client { self.node.get_block_number().await } + pub async fn get_client_version(&self) -> Result { + self.node.get_client_version().await + } + pub async fn get_block_by_number( &self, block: BlockTag, diff --git a/core/src/client/node.rs b/core/src/client/node.rs index 5b82c199..bce08b9b 100644 --- a/core/src/client/node.rs +++ b/core/src/client/node.rs @@ -140,6 +140,10 @@ impl> Node { self.execution.get_logs(filter).await } + pub async fn get_client_version(&self) -> Result { + self.execution.get_client_version().await + } + pub async fn get_filter_changes(&self, filter_id: U256) -> Result> { self.execution.get_filter_changes(filter_id).await } diff --git a/core/src/client/rpc.rs b/core/src/client/rpc.rs index 42aee77b..82ddc6ae 100644 --- a/core/src/client/rpc.rs +++ b/core/src/client/rpc.rs @@ -74,6 +74,8 @@ trait EthRpc Result; #[method(name = "getCode")] async fn get_code(&self, address: Address, block: BlockTag) -> Result; + #[method(name = "getClientVersion")] + async fn get_client_version(&self) -> Result; #[method(name = "call")] async fn call(&self, tx: TXR, block: BlockTag) -> Result; #[method(name = "estimateGas")] @@ -194,6 +196,10 @@ impl> convert_err(self.node.get_code(address, block).await) } + async fn get_client_version(&self) -> Result { + convert_err(self.node.get_client_version().await) + } + async fn call( &self, tx: N::TransactionRequest, diff --git a/core/src/execution/mod.rs b/core/src/execution/mod.rs index bc8979d6..9ba751eb 100644 --- a/core/src/execution/mod.rs +++ b/core/src/execution/mod.rs @@ -176,6 +176,10 @@ impl> ExecutionClient { .await } + pub async fn get_client_version(&self) -> Result { + self.rpc.get_client_version().await + } + pub async fn get_transaction_receipt( &self, tx_hash: B256, diff --git a/core/src/execution/rpc/http_rpc.rs b/core/src/execution/rpc/http_rpc.rs index 4eb52b96..336f7369 100644 --- a/core/src/execution/rpc/http_rpc.rs +++ b/core/src/execution/rpc/http_rpc.rs @@ -133,6 +133,14 @@ impl ExecutionRpc for HttpRpc { .map_err(|e| RpcError::new("get_logs", e))?) } + async fn get_client_version(&self) -> Result { + Ok(self + .provider + .get_client_version() + .await + .map_err(|e| RpcError::new("get_client_version", e))?) + } + async fn get_filter_changes(&self, filter_id: U256) -> Result> { Ok(self .provider diff --git a/core/src/execution/rpc/mock_rpc.rs b/core/src/execution/rpc/mock_rpc.rs index 17c977bc..46d98311 100644 --- a/core/src/execution/rpc/mock_rpc.rs +++ b/core/src/execution/rpc/mock_rpc.rs @@ -45,6 +45,10 @@ impl ExecutionRpc for MockRpc { Ok(hex::decode(&code[2..code.len() - 1])?) } + async fn get_client_version(&self) -> Result { + Ok("Mock/v0.1.0".to_string()) + } + async fn send_raw_transaction(&self, _bytes: &[u8]) -> Result { Err(eyre!("not implemented")) } diff --git a/core/src/execution/rpc/mod.rs b/core/src/execution/rpc/mod.rs index 56706dc4..d07e83b2 100644 --- a/core/src/execution/rpc/mod.rs +++ b/core/src/execution/rpc/mod.rs @@ -41,6 +41,7 @@ pub trait ExecutionRpc: Send + Clone + Sync + 'static { async fn get_new_pending_transaction_filter(&self) -> Result; async fn chain_id(&self) -> Result; async fn get_block(&self, hash: B256) -> Result>; + async fn get_client_version(&self) -> Result; async fn get_fee_history( &self, diff --git a/examples/basic.rs b/examples/basic.rs index 00d0a3c7..9e501faa 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -46,11 +46,13 @@ async fn main() -> Result<()> { client.start().await?; client.wait_synced().await; + let client_version = client.get_client_version().await?; let head_block_num = client.get_block_number().await?; let addr = Address::from_str("0x00000000219ab540356cBB839Cbe05303d7705Fa")?; let block = BlockTag::Latest; let balance = client.get_balance(addr, block).await?; + info!("client version: {}", client_version); info!("synced up to block: {}", head_block_num); info!("balance of deposit contract: {}", format_ether(balance)); diff --git a/helios-ts/lib.ts b/helios-ts/lib.ts index 1fc1c2da..cd902eb9 100644 --- a/helios-ts/lib.ts +++ b/helios-ts/lib.ts @@ -113,6 +113,9 @@ export class HeliosProvider { case "eth_getBlockByNumber": { return this.#client.get_block_by_number(req.params[0], req.params[1]); } + case "web3_clientVersion": { + return this.#client.get_client_version(); + } default: { throw `method not implemented: ${req.method}`; } diff --git a/helios-ts/src/ethereum.rs b/helios-ts/src/ethereum.rs index 26872ef8..5324136a 100644 --- a/helios-ts/src/ethereum.rs +++ b/helios-ts/src/ethereum.rs @@ -238,4 +238,9 @@ impl EthereumClient { let logs = map_err(self.inner.get_logs(&filter).await)?; Ok(serde_wasm_bindgen::to_value(&logs)?) } + + #[wasm_bindgen] + pub async fn get_client_version(&self) -> Result { + map_err(self.inner.get_client_version().await) + } } diff --git a/helios-ts/src/opstack.rs b/helios-ts/src/opstack.rs index 5e6b887e..cafba369 100644 --- a/helios-ts/src/opstack.rs +++ b/helios-ts/src/opstack.rs @@ -179,4 +179,10 @@ impl OpStackClient { let logs = map_err(self.inner.get_logs(&filter).await)?; Ok(serde_wasm_bindgen::to_value(&logs)?) } + + #[wasm_bindgen] + pub async fn get_client_version(&self) -> Result { + let version = map_err(self.inner.get_client_version().await)?; + Ok(version) + } } diff --git a/rpc.md b/rpc.md index 4df87b2c..ae81107c 100644 --- a/rpc.md +++ b/rpc.md @@ -25,3 +25,4 @@ Helios provides a variety of RPC methods for interacting with the Ethereum netwo | `eth_getBlockTransactionCountByNumber` | `get_block_transaction_count_by_number` | Returns the number of transactions in a block from a block matching the block number. | `client.get_block_transaction_count_by_number(&self, block: BlockTag)` | | `eth_coinbase` | `get_coinbase` | Returns the client coinbase address. | `client.get_coinbase(&self)` | | `eth_syncing` | `syncing` | Returns an object with data about the sync status or false. | `client.syncing(&self)` | +| `web3_getClientVersion` | `get_client_version` | Returns the current version of the chain client. | `client.get_client_version(&self)` | From a91b2c1bbb342f519c65fbddbe0e2878f7ed7c3c Mon Sep 17 00:00:00 2001 From: mw2000 Date: Mon, 28 Oct 2024 23:37:40 -0700 Subject: [PATCH 2/6] fix: small formatting --- core/src/client/node.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/client/node.rs b/core/src/client/node.rs index bce08b9b..96dda2bc 100644 --- a/core/src/client/node.rs +++ b/core/src/client/node.rs @@ -141,7 +141,7 @@ impl> Node { } pub async fn get_client_version(&self) -> Result { - self.execution.get_client_version().await + self.execution.get_client_version().await } pub async fn get_filter_changes(&self, filter_id: U256) -> Result> { From bbc96bd2672c1c3bf8523d229d7627bd8e96ba1b Mon Sep 17 00:00:00 2001 From: mw2000 Date: Tue, 29 Oct 2024 19:19:06 -0700 Subject: [PATCH 3/6] fix: client version returned as helios instead of original rpc's version. --- core/src/execution/mod.rs | 4 +++- core/src/execution/rpc/http_rpc.rs | 8 -------- core/src/execution/rpc/mock_rpc.rs | 4 ---- core/src/execution/rpc/mod.rs | 1 - 4 files changed, 3 insertions(+), 14 deletions(-) diff --git a/core/src/execution/mod.rs b/core/src/execution/mod.rs index 9ba751eb..e4bf7887 100644 --- a/core/src/execution/mod.rs +++ b/core/src/execution/mod.rs @@ -7,6 +7,7 @@ use alloy::rpc::types::{Filter, Log}; use eyre::Result; use futures::future::join_all; use revm::primitives::KECCAK_EMPTY; +use std::env; use triehash_ethereum::ordered_trie_root; use crate::network_spec::NetworkSpec; @@ -177,7 +178,8 @@ impl> ExecutionClient { } pub async fn get_client_version(&self) -> Result { - self.rpc.get_client_version().await + let helios_version = env::var("CARGO_PKG_VERSION"); + Ok(format!("helios-{}", helios_version.unwrap())) } pub async fn get_transaction_receipt( diff --git a/core/src/execution/rpc/http_rpc.rs b/core/src/execution/rpc/http_rpc.rs index 336f7369..4eb52b96 100644 --- a/core/src/execution/rpc/http_rpc.rs +++ b/core/src/execution/rpc/http_rpc.rs @@ -133,14 +133,6 @@ impl ExecutionRpc for HttpRpc { .map_err(|e| RpcError::new("get_logs", e))?) } - async fn get_client_version(&self) -> Result { - Ok(self - .provider - .get_client_version() - .await - .map_err(|e| RpcError::new("get_client_version", e))?) - } - async fn get_filter_changes(&self, filter_id: U256) -> Result> { Ok(self .provider diff --git a/core/src/execution/rpc/mock_rpc.rs b/core/src/execution/rpc/mock_rpc.rs index 46d98311..17c977bc 100644 --- a/core/src/execution/rpc/mock_rpc.rs +++ b/core/src/execution/rpc/mock_rpc.rs @@ -45,10 +45,6 @@ impl ExecutionRpc for MockRpc { Ok(hex::decode(&code[2..code.len() - 1])?) } - async fn get_client_version(&self) -> Result { - Ok("Mock/v0.1.0".to_string()) - } - async fn send_raw_transaction(&self, _bytes: &[u8]) -> Result { Err(eyre!("not implemented")) } diff --git a/core/src/execution/rpc/mod.rs b/core/src/execution/rpc/mod.rs index d07e83b2..56706dc4 100644 --- a/core/src/execution/rpc/mod.rs +++ b/core/src/execution/rpc/mod.rs @@ -41,7 +41,6 @@ pub trait ExecutionRpc: Send + Clone + Sync + 'static { async fn get_new_pending_transaction_filter(&self) -> Result; async fn chain_id(&self) -> Result; async fn get_block(&self, hash: B256) -> Result>; - async fn get_client_version(&self) -> Result; async fn get_fee_history( &self, From e15a2f0ee02221493d8e9c1172f3bc55a23cdcfe Mon Sep 17 00:00:00 2001 From: mw2000 Date: Wed, 30 Oct 2024 11:27:19 -0700 Subject: [PATCH 4/6] fix: environment var now fetched at compile time --- core/src/execution/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/execution/mod.rs b/core/src/execution/mod.rs index e4bf7887..17cca3ed 100644 --- a/core/src/execution/mod.rs +++ b/core/src/execution/mod.rs @@ -7,7 +7,6 @@ use alloy::rpc::types::{Filter, Log}; use eyre::Result; use futures::future::join_all; use revm::primitives::KECCAK_EMPTY; -use std::env; use triehash_ethereum::ordered_trie_root; use crate::network_spec::NetworkSpec; @@ -178,8 +177,8 @@ impl> ExecutionClient { } pub async fn get_client_version(&self) -> Result { - let helios_version = env::var("CARGO_PKG_VERSION"); - Ok(format!("helios-{}", helios_version.unwrap())) + let helios_version = std::env!("CARGO_PKG_VERSION"); + Ok(format!("helios-{}", helios_version)) } pub async fn get_transaction_receipt( From ead61189a528c0bc7cb50984406a2c78f7a7fa0d Mon Sep 17 00:00:00 2001 From: mw2000 Date: Wed, 30 Oct 2024 14:44:43 -0700 Subject: [PATCH 5/6] fix: fixes namespaces from eth to web3 --- core/src/client/mod.rs | 4 ++-- core/src/client/node.rs | 2 +- core/src/client/rpc.rs | 24 +++++++++++++++++------- examples/basic.rs | 2 +- rpc.md | 2 +- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/core/src/client/mod.rs b/core/src/client/mod.rs index dcf49efb..a43c38b1 100644 --- a/core/src/client/mod.rs +++ b/core/src/client/mod.rs @@ -153,8 +153,8 @@ impl> Client { self.node.get_block_number().await } - pub async fn get_client_version(&self) -> Result { - self.node.get_client_version().await + pub async fn client_version(&self) -> Result { + self.node.client_version().await } pub async fn get_block_by_number( diff --git a/core/src/client/node.rs b/core/src/client/node.rs index 96dda2bc..147ff66a 100644 --- a/core/src/client/node.rs +++ b/core/src/client/node.rs @@ -140,7 +140,7 @@ impl> Node { self.execution.get_logs(filter).await } - pub async fn get_client_version(&self) -> Result { + pub async fn client_version(&self) -> Result { self.execution.get_client_version().await } diff --git a/core/src/client/rpc.rs b/core/src/client/rpc.rs index 82ddc6ae..5c126616 100644 --- a/core/src/client/rpc.rs +++ b/core/src/client/rpc.rs @@ -74,8 +74,6 @@ trait EthRpc Result; #[method(name = "getCode")] async fn get_code(&self, address: Address, block: BlockTag) -> Result; - #[method(name = "getClientVersion")] - async fn get_client_version(&self) -> Result; #[method(name = "call")] async fn call(&self, tx: TXR, block: BlockTag) -> Result; #[method(name = "estimateGas")] @@ -143,6 +141,12 @@ trait NetRpc { async fn version(&self) -> Result; } +#[rpc(client, server, namespace = "web3")] +trait Web3Rpc { + #[method(name = "clientVersion")] + async fn client_version(&self) -> Result; +} + struct RpcInner> { node: Arc>, address: SocketAddr, @@ -196,10 +200,6 @@ impl> convert_err(self.node.get_code(address, block).await) } - async fn get_client_version(&self) -> Result { - convert_err(self.node.get_client_version().await) - } - async fn call( &self, tx: N::TransactionRequest, @@ -324,6 +324,14 @@ impl> NetRpcServer for RpcI } } +#[async_trait] +impl> Web3RpcServer for RpcInner { + async fn client_version(&self) -> Result { + convert_err(self.node.client_version().await) + } +} + + async fn start>( rpc: RpcInner, ) -> Result<(ServerHandle, SocketAddr)> { @@ -332,10 +340,12 @@ async fn start>( let mut methods = Methods::new(); let eth_methods: Methods = EthRpcServer::into_rpc(rpc.clone()).into(); - let net_methods: Methods = NetRpcServer::into_rpc(rpc).into(); + let net_methods: Methods = NetRpcServer::into_rpc(rpc.clone()).into(); + let web3_methods: Methods = Web3RpcServer::into_rpc(rpc).into(); methods.merge(eth_methods)?; methods.merge(net_methods)?; + methods.merge(web3_methods)?; let handle = server.start(methods); diff --git a/examples/basic.rs b/examples/basic.rs index 9e501faa..ec648e51 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -46,7 +46,7 @@ async fn main() -> Result<()> { client.start().await?; client.wait_synced().await; - let client_version = client.get_client_version().await?; + let client_version = client.client_version().await?; let head_block_num = client.get_block_number().await?; let addr = Address::from_str("0x00000000219ab540356cBB839Cbe05303d7705Fa")?; let block = BlockTag::Latest; diff --git a/rpc.md b/rpc.md index ae81107c..5cbb1f77 100644 --- a/rpc.md +++ b/rpc.md @@ -25,4 +25,4 @@ Helios provides a variety of RPC methods for interacting with the Ethereum netwo | `eth_getBlockTransactionCountByNumber` | `get_block_transaction_count_by_number` | Returns the number of transactions in a block from a block matching the block number. | `client.get_block_transaction_count_by_number(&self, block: BlockTag)` | | `eth_coinbase` | `get_coinbase` | Returns the client coinbase address. | `client.get_coinbase(&self)` | | `eth_syncing` | `syncing` | Returns an object with data about the sync status or false. | `client.syncing(&self)` | -| `web3_getClientVersion` | `get_client_version` | Returns the current version of the chain client. | `client.get_client_version(&self)` | +| `web3_clientVersion` | `client_version` | Returns the current version of the chain client. | `client.client_version(&self)` | From ae1d4325b28a3a506f00473c4f8ad1c8be19cdae Mon Sep 17 00:00:00 2001 From: mw2000 Date: Wed, 30 Oct 2024 14:46:30 -0700 Subject: [PATCH 6/6] fix: fmt --- core/src/client/rpc.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/client/rpc.rs b/core/src/client/rpc.rs index 5c126616..069a1973 100644 --- a/core/src/client/rpc.rs +++ b/core/src/client/rpc.rs @@ -331,7 +331,6 @@ impl> Web3RpcServer for Rpc } } - async fn start>( rpc: RpcInner, ) -> Result<(ServerHandle, SocketAddr)> {