From 669dc505f752d9d7ecf955b25d5fef72f64c91ab Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Thu, 28 Nov 2024 19:02:56 +0530 Subject: [PATCH 1/8] feat: specify `rpc_headers` in cast and config --- crates/cli/src/opts/ethereum.rs | 7 +++++++ crates/cli/src/utils/mod.rs | 4 ++++ crates/common/src/provider/runtime_transport.rs | 1 + crates/config/src/lib.rs | 10 ++++++++++ crates/forge/tests/cli/config.rs | 1 + 5 files changed, 23 insertions(+) diff --git a/crates/cli/src/opts/ethereum.rs b/crates/cli/src/opts/ethereum.rs index b858d998fafb..1ba8f4c8a4be 100644 --- a/crates/cli/src/opts/ethereum.rs +++ b/crates/cli/src/opts/ethereum.rs @@ -48,6 +48,10 @@ pub struct RpcOpts { /// Default value: 45 #[arg(long, env = "ETH_RPC_TIMEOUT")] pub rpc_timeout: Option, + + /// Specify custom headers for RPC requests. + #[arg(long, env = "ETH_RPC_HEADERS", value_delimiter(','), value_delimiter(' '))] + pub headers: Option>, } impl_figment_convert_cast!(RpcOpts); @@ -95,6 +99,9 @@ impl RpcOpts { if let Some(rpc_timeout) = self.rpc_timeout { dict.insert("eth_rpc_timeout".into(), rpc_timeout.into()); } + if let Some(headers) = &self.headers { + dict.insert("rpc_headers".into(), headers.clone().into()); + } dict } } diff --git a/crates/cli/src/utils/mod.rs b/crates/cli/src/utils/mod.rs index 2d8471e62685..eefe7537844d 100644 --- a/crates/cli/src/utils/mod.rs +++ b/crates/cli/src/utils/mod.rs @@ -110,6 +110,10 @@ pub fn get_provider_builder(config: &Config) -> Result { builder = builder.timeout(Duration::from_secs(rpc_timeout)); } + if let Some(rpc_headers) = &config.rpc_headers { + builder = builder.headers(rpc_headers.clone()); + } + Ok(builder) } diff --git a/crates/common/src/provider/runtime_transport.rs b/crates/common/src/provider/runtime_transport.rs index a95969be5a40..f2b616f36587 100644 --- a/crates/common/src/provider/runtime_transport.rs +++ b/crates/common/src/provider/runtime_transport.rs @@ -170,6 +170,7 @@ impl RuntimeTransport { let (key, val) = header.split_once(':').ok_or_else(make_err)?; + tracing::info!("Adding header: {}={}", key, val); headers.insert( HeaderName::from_str(key.trim()).map_err(|_| make_err())?, HeaderValue::from_str(val.trim()).map_err(|_| make_err())?, diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 5a159c3925b8..1c3af3213bdc 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -248,6 +248,15 @@ pub struct Config { pub eth_rpc_jwt: Option, /// Timeout that should be used for any rpc calls pub eth_rpc_timeout: Option, + /// Headers that should be used for any rpc calls + /// + /// # Example + /// + /// rpc_headers = ["x-custom-header:value", "x-another-header:another-value"] + /// + /// You can also the ETH_RPC_HEADERS env variable like so: + /// `ETH_RPC_HEADERS="x-custom-header:value x-another-header:another-value"` + pub rpc_headers: Option>, /// etherscan API key, or alias for an `EtherscanConfig` in `etherscan` table pub etherscan_api_key: Option, /// Multiple etherscan api configs and their aliases @@ -2271,6 +2280,7 @@ impl Default for Config { eth_rpc_url: None, eth_rpc_jwt: None, eth_rpc_timeout: None, + rpc_headers: None, etherscan_api_key: None, verbosity: 0, remappings: vec![], diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index db87a85ba0d1..51add5081719 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -107,6 +107,7 @@ forgetest!(can_extract_config_values, |prj, cmd| { eth_rpc_url: Some("localhost".to_string()), eth_rpc_jwt: None, eth_rpc_timeout: None, + rpc_headers: None, etherscan_api_key: None, etherscan: Default::default(), verbosity: 4, From 7f98fd7310093c698d9f20b7e157dd71b57aa76e Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Thu, 28 Nov 2024 19:39:10 +0530 Subject: [PATCH 2/8] test --- Cargo.lock | 18 +++++++++++ Cargo.toml | 1 + crates/cast/Cargo.toml | 1 + crates/cast/tests/cli/main.rs | 32 ++++++++++++++++++- crates/cli/src/opts/ethereum.rs | 2 +- .../common/src/provider/runtime_transport.rs | 1 - 6 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d94d710ac07f..2cba52150d92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,23 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-node-bindings" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9805d126f24be459b958973c0569c73e1aadd27d4535eee82b2b6764aa03616" +dependencies = [ + "alloy-genesis", + "alloy-primitives", + "k256", + "rand", + "serde_json", + "tempfile", + "thiserror 1.0.69", + "tracing", + "url", +] + [[package]] name = "alloy-primitives" version = "0.8.12" @@ -1957,6 +1974,7 @@ dependencies = [ "alloy-json-abi", "alloy-json-rpc", "alloy-network", + "alloy-node-bindings", "alloy-primitives", "alloy-provider", "alloy-rlp", diff --git a/Cargo.toml b/Cargo.toml index 814c43aa556a..b07d99cc9f92 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -205,6 +205,7 @@ alloy-transport = { version = "0.6.4", default-features = false } alloy-transport-http = { version = "0.6.4", default-features = false } alloy-transport-ipc = { version = "0.6.4", default-features = false } alloy-transport-ws = { version = "0.6.4", default-features = false } +alloy-node-bindings = { version = "0.6.4", default-features = false } ## alloy-core alloy-dyn-abi = "0.8.11" diff --git a/crates/cast/Cargo.toml b/crates/cast/Cargo.toml index 0887649e58dd..f6011831accb 100644 --- a/crates/cast/Cargo.toml +++ b/crates/cast/Cargo.toml @@ -94,6 +94,7 @@ tikv-jemallocator = { workspace = true, optional = true } [dev-dependencies] anvil.workspace = true foundry-test-utils.workspace = true +alloy-node-bindings.workspace = true async-trait.workspace = true divan.workspace = true diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index d2c70a779e65..2832d26f74dc 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -2,8 +2,12 @@ use alloy_chains::NamedChain; use alloy_network::TransactionResponse; +use alloy_node_bindings::{utils::run_with_tempdir_sync, Reth}; use alloy_primitives::{b256, B256}; -use alloy_rpc_types::{BlockNumberOrTag, Index}; +use alloy_rpc_types::{ + engine::{Claims, JwtSecret}, + BlockNumberOrTag, Index, +}; use anvil::{EthereumHardfork, NodeConfig}; use foundry_test_utils::{ casttest, file, forgetest_async, @@ -1867,3 +1871,29 @@ Transaction successfully executed. "#]]); }); + +#[cfg(not(windows))] +casttest!(test_rpc_headers, |_prj, cmd| { + run_with_tempdir_sync("temp", |path| { + let jwt_secret = "f79ae8046bc11c9927afe911db7143c51a806c4a537cc08e0d37140b0192f430"; + + let reth = + Reth::new().data_dir(path.join("data")).args(["--rpc.jwtsecret", jwt_secret]).spawn(); + + let endpoint = reth.endpoint(); + + let secret = JwtSecret::from_hex(jwt_secret).unwrap(); + + let token = secret.encode(&Claims::with_current_timestamp()).unwrap(); + + cmd.args([ + "rpc", + "eth_blockNumber", + "--rpc-url", + &endpoint, + "--headers", + &format!("Authorization:Bearer {token}"), + ]) + .assert_success(); + }); +}); diff --git a/crates/cli/src/opts/ethereum.rs b/crates/cli/src/opts/ethereum.rs index 1ba8f4c8a4be..755f18e56ac3 100644 --- a/crates/cli/src/opts/ethereum.rs +++ b/crates/cli/src/opts/ethereum.rs @@ -50,7 +50,7 @@ pub struct RpcOpts { pub rpc_timeout: Option, /// Specify custom headers for RPC requests. - #[arg(long, env = "ETH_RPC_HEADERS", value_delimiter(','), value_delimiter(' '))] + #[arg(long, env = "ETH_RPC_HEADERS", value_delimiter(','))] pub headers: Option>, } diff --git a/crates/common/src/provider/runtime_transport.rs b/crates/common/src/provider/runtime_transport.rs index f2b616f36587..a95969be5a40 100644 --- a/crates/common/src/provider/runtime_transport.rs +++ b/crates/common/src/provider/runtime_transport.rs @@ -170,7 +170,6 @@ impl RuntimeTransport { let (key, val) = header.split_once(':').ok_or_else(make_err)?; - tracing::info!("Adding header: {}={}", key, val); headers.insert( HeaderName::from_str(key.trim()).map_err(|_| make_err())?, HeaderValue::from_str(val.trim()).map_err(|_| make_err())?, From e606feb21d77d59835dcc04a3cb796ec1c3d1dba Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Thu, 28 Nov 2024 19:51:45 +0530 Subject: [PATCH 3/8] fix --- crates/cli/src/opts/ethereum.rs | 2 +- crates/cli/src/utils/mod.rs | 2 +- crates/config/src/lib.rs | 4 ++-- crates/forge/tests/cli/config.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/cli/src/opts/ethereum.rs b/crates/cli/src/opts/ethereum.rs index 755f18e56ac3..99af4481ca08 100644 --- a/crates/cli/src/opts/ethereum.rs +++ b/crates/cli/src/opts/ethereum.rs @@ -100,7 +100,7 @@ impl RpcOpts { dict.insert("eth_rpc_timeout".into(), rpc_timeout.into()); } if let Some(headers) = &self.headers { - dict.insert("rpc_headers".into(), headers.clone().into()); + dict.insert("eth_rpc_headers".into(), headers.clone().into()); } dict } diff --git a/crates/cli/src/utils/mod.rs b/crates/cli/src/utils/mod.rs index eefe7537844d..f66fcefd1bf7 100644 --- a/crates/cli/src/utils/mod.rs +++ b/crates/cli/src/utils/mod.rs @@ -110,7 +110,7 @@ pub fn get_provider_builder(config: &Config) -> Result { builder = builder.timeout(Duration::from_secs(rpc_timeout)); } - if let Some(rpc_headers) = &config.rpc_headers { + if let Some(rpc_headers) = &config.eth_rpc_headers { builder = builder.headers(rpc_headers.clone()); } diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 1c3af3213bdc..01cbc492d6b8 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -256,7 +256,7 @@ pub struct Config { /// /// You can also the ETH_RPC_HEADERS env variable like so: /// `ETH_RPC_HEADERS="x-custom-header:value x-another-header:another-value"` - pub rpc_headers: Option>, + pub eth_rpc_headers: Option>, /// etherscan API key, or alias for an `EtherscanConfig` in `etherscan` table pub etherscan_api_key: Option, /// Multiple etherscan api configs and their aliases @@ -2280,7 +2280,7 @@ impl Default for Config { eth_rpc_url: None, eth_rpc_jwt: None, eth_rpc_timeout: None, - rpc_headers: None, + eth_rpc_headers: None, etherscan_api_key: None, verbosity: 0, remappings: vec![], diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index 51add5081719..4ef86153af17 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -107,7 +107,7 @@ forgetest!(can_extract_config_values, |prj, cmd| { eth_rpc_url: Some("localhost".to_string()), eth_rpc_jwt: None, eth_rpc_timeout: None, - rpc_headers: None, + eth_rpc_headers: None, etherscan_api_key: None, etherscan: Default::default(), verbosity: 4, From 96f7990f65979c71b8ba13cc9397de78694104dd Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Thu, 28 Nov 2024 19:54:29 +0530 Subject: [PATCH 4/8] fix --- crates/cli/src/opts/ethereum.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/cli/src/opts/ethereum.rs b/crates/cli/src/opts/ethereum.rs index 99af4481ca08..4b15b8551940 100644 --- a/crates/cli/src/opts/ethereum.rs +++ b/crates/cli/src/opts/ethereum.rs @@ -50,8 +50,8 @@ pub struct RpcOpts { pub rpc_timeout: Option, /// Specify custom headers for RPC requests. - #[arg(long, env = "ETH_RPC_HEADERS", value_delimiter(','))] - pub headers: Option>, + #[arg(long, alias = "headers", env = "ETH_RPC_HEADERS", value_delimiter(','))] + pub rpc_headers: Option>, } impl_figment_convert_cast!(RpcOpts); @@ -99,7 +99,7 @@ impl RpcOpts { if let Some(rpc_timeout) = self.rpc_timeout { dict.insert("eth_rpc_timeout".into(), rpc_timeout.into()); } - if let Some(headers) = &self.headers { + if let Some(headers) = &self.rpc_headers { dict.insert("eth_rpc_headers".into(), headers.clone().into()); } dict From ebcc853fdaa45b67448370dffaa973ff7fd4edb5 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Fri, 29 Nov 2024 11:10:14 +0530 Subject: [PATCH 5/8] default user agent --- crates/cli/src/utils/mod.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/cli/src/utils/mod.rs b/crates/cli/src/utils/mod.rs index f66fcefd1bf7..be228c37ffac 100644 --- a/crates/cli/src/utils/mod.rs +++ b/crates/cli/src/utils/mod.rs @@ -39,6 +39,8 @@ pub const STATIC_FUZZ_SEED: [u8; 32] = [ 0x5d, 0x64, 0x0b, 0x19, 0xad, 0xf0, 0xe3, 0x57, 0xb8, 0xd4, 0xbe, 0x7d, 0x49, 0xee, 0x70, 0xe6, ]; +const DEFAULT_USER_AGENT: &str = concat!("foundry/", env!("CARGO_PKG_VERSION")); + /// Useful extensions to [`std::path::Path`]. pub trait FoundryPathExt { /// Returns true if the [`Path`] ends with `.t.sol` @@ -110,8 +112,12 @@ pub fn get_provider_builder(config: &Config) -> Result { builder = builder.timeout(Duration::from_secs(rpc_timeout)); } - if let Some(rpc_headers) = &config.eth_rpc_headers { - builder = builder.headers(rpc_headers.clone()); + if let Some(mut rpc_headers) = config.eth_rpc_headers.clone() { + if rpc_headers.iter().find(|h| h.starts_with("User-Agent:")).is_none() { + rpc_headers.push(format!("User-Agent:{}", DEFAULT_USER_AGENT)); + } + + builder = builder.headers(rpc_headers); } Ok(builder) From fcb297b0fa75e890fb0630328a518aa669817337 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Fri, 29 Nov 2024 13:52:40 +0530 Subject: [PATCH 6/8] fix --- crates/cast/tests/cli/main.rs | 33 +++++++++++++++------------------ crates/cli/src/utils/mod.rs | 4 ++-- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 2832d26f74dc..655e1412dc98 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -2,7 +2,7 @@ use alloy_chains::NamedChain; use alloy_network::TransactionResponse; -use alloy_node_bindings::{utils::run_with_tempdir_sync, Reth}; +use alloy_node_bindings::Reth; use alloy_primitives::{b256, B256}; use alloy_rpc_types::{ engine::{Claims, JwtSecret}, @@ -1874,26 +1874,23 @@ Transaction successfully executed. #[cfg(not(windows))] casttest!(test_rpc_headers, |_prj, cmd| { - run_with_tempdir_sync("temp", |path| { - let jwt_secret = "f79ae8046bc11c9927afe911db7143c51a806c4a537cc08e0d37140b0192f430"; + let jwt_secret = "f79ae8046bc11c9927afe911db7143c51a806c4a537cc08e0d37140b0192f430"; - let reth = - Reth::new().data_dir(path.join("data")).args(["--rpc.jwtsecret", jwt_secret]).spawn(); + let reth = Reth::new().args(["--rpc.jwtsecret", jwt_secret]).spawn(); - let endpoint = reth.endpoint(); + let endpoint = reth.endpoint(); - let secret = JwtSecret::from_hex(jwt_secret).unwrap(); + let secret = JwtSecret::from_hex(jwt_secret).unwrap(); - let token = secret.encode(&Claims::with_current_timestamp()).unwrap(); + let token = secret.encode(&Claims::with_current_timestamp()).unwrap(); - cmd.args([ - "rpc", - "eth_blockNumber", - "--rpc-url", - &endpoint, - "--headers", - &format!("Authorization:Bearer {token}"), - ]) - .assert_success(); - }); + cmd.args([ + "rpc", + "eth_blockNumber", + "--rpc-url", + &endpoint, + "--headers", + &format!("Authorization:Bearer {token}"), + ]) + .assert_success(); }); diff --git a/crates/cli/src/utils/mod.rs b/crates/cli/src/utils/mod.rs index be228c37ffac..f833924f57fe 100644 --- a/crates/cli/src/utils/mod.rs +++ b/crates/cli/src/utils/mod.rs @@ -113,8 +113,8 @@ pub fn get_provider_builder(config: &Config) -> Result { } if let Some(mut rpc_headers) = config.eth_rpc_headers.clone() { - if rpc_headers.iter().find(|h| h.starts_with("User-Agent:")).is_none() { - rpc_headers.push(format!("User-Agent:{}", DEFAULT_USER_AGENT)); + if !rpc_headers.iter().any(|h| h.starts_with("User-Agent:")) { + rpc_headers.push(format!("User-Agent:{DEFAULT_USER_AGENT}")); } builder = builder.headers(rpc_headers); From 7d0a7331f77a2deceb5dcaa47df26aa56d6436e0 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Fri, 29 Nov 2024 14:10:11 +0530 Subject: [PATCH 7/8] fix: cast run and rm flaky test --- crates/cast/bin/cmd/run.rs | 8 +++----- crates/cast/tests/cli/main.rs | 25 ------------------------- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index cfad7263a1e4..bb5c505b11c3 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -107,11 +107,9 @@ impl RunArgs { let compute_units_per_second = if self.no_rate_limit { Some(u64::MAX) } else { self.compute_units_per_second }; - let provider = foundry_common::provider::ProviderBuilder::new( - &config.get_rpc_url_or_localhost_http()?, - ) - .compute_units_per_second_opt(compute_units_per_second) - .build()?; + let provider = foundry_cli::utils::get_provider_builder(&config)? + .compute_units_per_second_opt(compute_units_per_second) + .build()?; let tx_hash = self.tx_hash.parse().wrap_err("invalid tx hash")?; let tx = provider diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 655e1412dc98..d000e9ae9622 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -2,10 +2,8 @@ use alloy_chains::NamedChain; use alloy_network::TransactionResponse; -use alloy_node_bindings::Reth; use alloy_primitives::{b256, B256}; use alloy_rpc_types::{ - engine::{Claims, JwtSecret}, BlockNumberOrTag, Index, }; use anvil::{EthereumHardfork, NodeConfig}; @@ -1871,26 +1869,3 @@ Transaction successfully executed. "#]]); }); - -#[cfg(not(windows))] -casttest!(test_rpc_headers, |_prj, cmd| { - let jwt_secret = "f79ae8046bc11c9927afe911db7143c51a806c4a537cc08e0d37140b0192f430"; - - let reth = Reth::new().args(["--rpc.jwtsecret", jwt_secret]).spawn(); - - let endpoint = reth.endpoint(); - - let secret = JwtSecret::from_hex(jwt_secret).unwrap(); - - let token = secret.encode(&Claims::with_current_timestamp()).unwrap(); - - cmd.args([ - "rpc", - "eth_blockNumber", - "--rpc-url", - &endpoint, - "--headers", - &format!("Authorization:Bearer {token}"), - ]) - .assert_success(); -}); From 8d3937a63a852c6ddd9ba8eadcf43c2d9161ef84 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Fri, 29 Nov 2024 18:25:47 +0530 Subject: [PATCH 8/8] fmt --- crates/cast/tests/cli/main.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index d000e9ae9622..d2c70a779e65 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -3,9 +3,7 @@ use alloy_chains::NamedChain; use alloy_network::TransactionResponse; use alloy_primitives::{b256, B256}; -use alloy_rpc_types::{ - BlockNumberOrTag, Index, -}; +use alloy_rpc_types::{BlockNumberOrTag, Index}; use anvil::{EthereumHardfork, NodeConfig}; use foundry_test_utils::{ casttest, file, forgetest_async,