From 0223bc37f77a12ef599200e2664af5a3d0c367b0 Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Wed, 1 May 2024 09:45:42 +0200 Subject: [PATCH] chore(general): add CI workflow for Windows + fix IPC test (#642) * add windows workflow * make sure it runs on the target * export path after modification * update workflow, set tracing for failing geth script * check if geth is in path * comment out other jobs * attempt * use bash shell * works! error on access denied for ipc * make sure Geth tests run serially to avoid ipc access denied * disable ipc by default * remove serial tag * log path * attempt fix by pointing towards Geths spawned IPC * use geth port * windows doesnt allow specific paths to ipc * ipcpath on windows is just the name, not the path * re-enable other jobs tasks * clean up * use custom ipc name to show working * clean up --- .github/workflows/ci.yml | 29 +++++++++++++++++++------ crates/node-bindings/src/geth.rs | 26 +++++++++++++++++----- crates/provider/src/ext/admin.rs | 7 +++--- crates/provider/src/ext/txpool.rs | 8 +++---- crates/rpc-client/Cargo.toml | 1 + crates/rpc-client/tests/it/ipc.rs | 35 ++++++++++++------------------ crates/signer-ledger/src/signer.rs | 13 ++++++----- 7 files changed, 73 insertions(+), 46 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f94672cff05..381be49d430 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,17 +14,31 @@ concurrency: jobs: test: - name: test ${{ matrix.rust }} ${{ matrix.flags }} - runs-on: ubuntu-latest + name: test ${{ matrix.os }} ${{ matrix.rust }} ${{ matrix.flags }} timeout-minutes: 30 + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - rust: ["stable", "nightly", "1.76"] # MSRV - flags: ["--no-default-features", "", "--all-features"] - exclude: - # Some features have higher MSRV. - - rust: "1.76" # MSRV + os: ["ubuntu-latest", "windows-latest"] + rust: [ + "stable", + "nightly", + "1.76" # MSRV + ] + flags: [ + # No features + "--no-default-features", + # Default features + "", + ] + include: + # All features + - os: "ubuntu-latest" + rust: "stable" + flags: "--all-features" + - os: "ubuntu-latest" + rust: "nightly" flags: "--all-features" steps: - uses: actions/checkout@v3 @@ -49,6 +63,7 @@ jobs: if: ${{ matrix.rust == '1.76' }} # MSRV run: cargo build --workspace ${{ matrix.flags }} - name: test + shell: bash if: ${{ matrix.rust != '1.76' }} # MSRV run: cargo nextest run --workspace ${{ matrix.flags }} diff --git a/crates/node-bindings/src/geth.rs b/crates/node-bindings/src/geth.rs index 0233310137d..6bbf44e60b3 100644 --- a/crates/node-bindings/src/geth.rs +++ b/crates/node-bindings/src/geth.rs @@ -77,6 +77,15 @@ impl GethInstance { format!("ws://localhost:{}", self.port) } + /// Returns the IPC endpoint of this instance + pub fn ipc_endpoint(&self) -> String { + if let Some(ipc) = self.ipc.clone() { + ipc.display().to_string() + } else { + "geth.ipc".to_string() + } + } + /// Returns the HTTP endpoint url of this instance pub fn endpoint_url(&self) -> Url { Url::parse(&self.endpoint()).unwrap() @@ -87,11 +96,6 @@ impl GethInstance { Url::parse(&self.ws_endpoint()).unwrap() } - /// Returns the path to this instances' IPC socket - pub fn ipc_path(&self) -> &Option { - &self.ipc - } - /// Returns the path to this instances' data directory pub fn data_dir(&self) -> &Option { &self.data_dir @@ -246,6 +250,7 @@ pub struct Geth { port: Option, authrpc_port: Option, ipc_path: Option, + ipc_enabled: bool, data_dir: Option, chain_id: Option, insecure_unlock: bool, @@ -355,6 +360,12 @@ impl Geth { self } + /// Enable IPC for the geth instance. + pub fn enable_ipc(mut self) -> Self { + self.ipc_enabled = true; + self + } + /// Disable discovery for the geth instance. /// /// This will put the geth instance into non-dev mode, discarding any previously set dev-mode @@ -428,6 +439,11 @@ impl Geth { let mut port = self.port.unwrap_or(0); let port_s = port.to_string(); + // If IPC is not enabled on the builder, disable it. + if !self.ipc_enabled { + cmd.arg("--ipcdisable"); + } + // Open the HTTP API cmd.arg("--http"); cmd.arg("--http.port").arg(&port_s); diff --git a/crates/provider/src/ext/admin.rs b/crates/provider/src/ext/admin.rs index 5d882211695..895c93f4078 100644 --- a/crates/provider/src/ext/admin.rs +++ b/crates/provider/src/ext/admin.rs @@ -74,10 +74,11 @@ mod test { use super::*; use alloy_node_bindings::Geth; + use tempfile::TempDir; #[tokio::test] async fn node_info() { - let temp_dir = tempfile::TempDir::with_prefix("reth-test-").unwrap(); + let temp_dir = TempDir::with_prefix("geth-test-").unwrap(); let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); let node_info = provider.node_info().await.unwrap(); @@ -86,8 +87,8 @@ mod test { #[tokio::test] async fn admin_peers() { - let temp_dir = tempfile::TempDir::with_prefix("reth-test-1").unwrap(); - let temp_dir_2 = tempfile::TempDir::with_prefix("reth-test-2").unwrap(); + let temp_dir = TempDir::with_prefix("geth-test-1").unwrap(); + let temp_dir_2 = TempDir::with_prefix("geth-test-2").unwrap(); let geth1 = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); let mut geth2 = Geth::new().disable_discovery().port(0u16).data_dir(temp_dir_2.path()).spawn(); diff --git a/crates/provider/src/ext/txpool.rs b/crates/provider/src/ext/txpool.rs index 485dc443a12..6dc51c349d6 100644 --- a/crates/provider/src/ext/txpool.rs +++ b/crates/provider/src/ext/txpool.rs @@ -76,7 +76,7 @@ mod tests { #[tokio::test] async fn test_txpool_content() { - let temp_dir = tempfile::TempDir::with_prefix("reth-test-").unwrap(); + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); let content = provider.txpool_content().await.unwrap(); @@ -85,7 +85,7 @@ mod tests { #[tokio::test] async fn test_txpool_content_from() { - let temp_dir = tempfile::TempDir::with_prefix("reth-test-").unwrap(); + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); let content = provider.txpool_content_from(Address::default()).await.unwrap(); @@ -94,7 +94,7 @@ mod tests { #[tokio::test] async fn test_txpool_inspect() { - let temp_dir = tempfile::TempDir::with_prefix("reth-test-").unwrap(); + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); let content = provider.txpool_inspect().await.unwrap(); @@ -103,7 +103,7 @@ mod tests { #[tokio::test] async fn test_txpool_status() { - let temp_dir = tempfile::TempDir::with_prefix("reth-test-").unwrap(); + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); let geth = Geth::new().disable_discovery().data_dir(temp_dir.path()).spawn(); let provider = ProviderBuilder::new().on_http(geth.endpoint_url()); let content = provider.txpool_status().await.unwrap(); diff --git a/crates/rpc-client/Cargo.toml b/crates/rpc-client/Cargo.toml index 540259748bf..7e39caec7ef 100644 --- a/crates/rpc-client/Cargo.toml +++ b/crates/rpc-client/Cargo.toml @@ -42,6 +42,7 @@ alloy-transport-ipc = { workspace = true, optional = true } alloy-primitives.workspace = true alloy-node-bindings.workspace = true alloy-transport-ipc = { workspace = true, features = ["mock"] } +alloy-transport-ws.workspace = true tempfile = "3" futures-util.workspace = true diff --git a/crates/rpc-client/tests/it/ipc.rs b/crates/rpc-client/tests/it/ipc.rs index 11f20c9ebe8..d5ba46c3d5b 100644 --- a/crates/rpc-client/tests/it/ipc.rs +++ b/crates/rpc-client/tests/it/ipc.rs @@ -1,30 +1,23 @@ -use alloy_node_bindings::{Geth, GethInstance}; +use alloy_node_bindings::Geth; use alloy_primitives::U64; -use alloy_pubsub::PubSubFrontend; -use alloy_rpc_client::{ClientBuilder, RpcCall, RpcClient}; +use alloy_rpc_client::{ClientBuilder, RpcCall}; use alloy_transport_ipc::IpcConnect; -use tempfile::NamedTempFile; +use std::path::PathBuf; -async fn connect() -> (RpcClient, GethInstance) { - let temp_file = NamedTempFile::new().unwrap(); - let path = temp_file.into_temp_path().to_path_buf(); - let geth = Geth::new().block_time(1u64).ipc_path(&path).spawn(); - - // [Windows named pipes](https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipes) - // are located at `\\\pipe\`. - #[cfg(windows)] - let path = format!(r"\\.\pipe\{}", path.display()); - - let connector: IpcConnect<_> = path.into(); +#[tokio::test] +async fn it_makes_a_request() { + let temp_dir = tempfile::TempDir::with_prefix("geth-test-").unwrap(); + let geth = Geth::new() + .disable_discovery() + .ipc_path(temp_dir.path().join("alloy.ipc")) + .enable_ipc() + .block_time(1u64) + .data_dir(temp_dir.path()) + .spawn(); + let connector: IpcConnect<_> = PathBuf::from(geth.ipc_endpoint()).into(); let client = ClientBuilder::default().pubsub(connector).await.unwrap(); - (client, geth) -} - -#[tokio::test] -async fn it_makes_a_request() { - let (client, _geth) = connect().await; let req: RpcCall<_, (), U64> = client.request("eth_blockNumber", ()); let timeout = tokio::time::timeout(std::time::Duration::from_secs(2), req); let res = timeout.await.unwrap().unwrap(); diff --git a/crates/signer-ledger/src/signer.rs b/crates/signer-ledger/src/signer.rs index 3bc5ef64696..028a229e0fa 100644 --- a/crates/signer-ledger/src/signer.rs +++ b/crates/signer-ledger/src/signer.rs @@ -289,6 +289,7 @@ mod tests { use alloy_network::TxSigner; use alloy_primitives::{address, bytes, U256}; use alloy_rlp::Decodable; + use serial_test::serial; use std::sync::OnceLock; const DTYPE: DerivationType = DerivationType::LedgerLive(0); @@ -310,7 +311,7 @@ mod tests { } #[tokio::test] - #[serial_test::serial] + #[serial] #[ignore] async fn test_get_address() { let ledger = init_ledger().await; @@ -319,7 +320,7 @@ mod tests { } #[tokio::test] - #[serial_test::serial] + #[serial] #[ignore] async fn test_version() { let ledger = init_ledger().await; @@ -329,7 +330,7 @@ mod tests { } #[tokio::test] - #[serial_test::serial] + #[serial] #[ignore] async fn test_sign_tx_legacy() { // https://github.com/gakonst/ethers-rs/blob/90b87bd85be98caa8bb592b67f3f9acbc8a409cf/ethers-signers/src/ledger/app.rs#L321 @@ -352,7 +353,7 @@ mod tests { } #[tokio::test] - #[serial_test::serial] + #[serial] #[ignore] async fn test_sign_tx_eip2930() { // From the Ledger Ethereum app example: https://github.com/LedgerHQ/app-ethereum/blob/2264f677568cbc1e3177f9eccb3c14a229ab3255/examples/signTx.py#L104-L106 @@ -368,7 +369,7 @@ mod tests { } #[tokio::test] - #[serial_test::serial] + #[serial] #[ignore] async fn test_sign_tx_eip1559() { // From the Ledger Ethereum app example: https://github.com/LedgerHQ/app-ethereum/blob/2264f677568cbc1e3177f9eccb3c14a229ab3255/examples/signTx.py#L100-L102 @@ -390,7 +391,7 @@ mod tests { } #[tokio::test] - #[serial_test::serial] + #[serial] #[ignore] async fn test_sign_message() { let ledger = init_ledger().await;