Skip to content

Commit c486fca

Browse files
authored
chore(deps): replace parity-ipc-server with interprocess (#7862)
1 parent 784e382 commit c486fca

File tree

8 files changed

+153
-181
lines changed

8 files changed

+153
-181
lines changed

Cargo.lock

Lines changed: 70 additions & 116 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/anvil/core/src/eth/trie.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
//! Utility functions for Ethereum adapted from https://github.dev/rust-blockchain/ethereum/blob/755dffaa4903fbec1269f50cde9863cf86269a14/src/util.rs
2-
use std::collections::BTreeMap;
1+
//! Utility functions for Ethereum adapted from <https://github.com/rust-blockchain/ethereum/blob/755dffaa4903fbec1269f50cde9863cf86269a14/src/util.rs>
32
43
use alloy_primitives::{fixed_bytes, B256};
54
use alloy_trie::{HashBuilder, Nibbles};
5+
use std::collections::BTreeMap;
66

77
/// The KECCAK of the RLP encoding of empty data.
88
pub const KECCAK_NULL_RLP: B256 =

crates/anvil/server/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ parking_lot = "0.12"
2525
futures = "0.3"
2626

2727
# ipc
28-
parity-tokio-ipc = { version = "0.9", optional = true }
28+
interprocess = { version = "2", optional = true, features = ["tokio"] }
2929
bytes = { version = "1.4", optional = true }
3030
tokio-util = { version = "0.7", features = ["codec"], optional = true }
3131

@@ -40,4 +40,4 @@ pin-project = "1"
4040

4141
[features]
4242
default = ["ipc"]
43-
ipc = ["parity-tokio-ipc", "bytes", "tokio-util"]
43+
ipc = ["dep:interprocess", "dep:bytes", "dep:tokio-util"]

crates/anvil/server/src/ipc.rs

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{error::RequestError, pubsub::PubSubConnection, PubSubRpcHandler};
44
use anvil_rpc::request::Request;
55
use bytes::BytesMut;
66
use futures::{ready, Sink, Stream, StreamExt};
7-
use parity_tokio_ipc::Endpoint;
7+
use interprocess::local_socket::{self as ls, tokio::prelude::*};
88
use std::{
99
future::Future,
1010
io,
@@ -18,14 +18,14 @@ use std::{
1818
pub struct IpcEndpoint<Handler> {
1919
/// the handler for the websocket connection
2020
handler: Handler,
21-
/// The endpoint we listen for incoming transactions
22-
endpoint: Endpoint,
21+
/// The path to the socket
22+
path: String,
2323
}
2424

2525
impl<Handler: PubSubRpcHandler> IpcEndpoint<Handler> {
2626
/// Creates a new endpoint with the given handler
27-
pub fn new(handler: Handler, endpoint: String) -> Self {
28-
Self { handler, endpoint: Endpoint::new(endpoint) }
27+
pub fn new(handler: Handler, path: String) -> Self {
28+
Self { handler, path }
2929
}
3030

3131
/// Returns a stream of incoming connection handlers
@@ -34,39 +34,43 @@ impl<Handler: PubSubRpcHandler> IpcEndpoint<Handler> {
3434
/// connections, See [`PubSubConnection`] that should be spawned
3535
#[instrument(target = "ipc", skip_all)]
3636
pub fn incoming(self) -> io::Result<impl Stream<Item = impl Future<Output = ()>>> {
37-
let IpcEndpoint { handler, endpoint } = self;
38-
trace!(endpoint=?endpoint.path(), "starting IPC server" );
37+
let IpcEndpoint { handler, path } = self;
38+
39+
trace!(%path, "starting IPC server");
3940

4041
if cfg!(unix) {
4142
// ensure the file does not exist
42-
if std::fs::remove_file(endpoint.path()).is_ok() {
43-
warn!(endpoint=?endpoint.path(), "removed existing file");
43+
if std::fs::remove_file(&path).is_ok() {
44+
warn!(%path, "removed existing file");
4445
}
4546
}
4647

47-
let connections = match endpoint.incoming() {
48-
Ok(connections) => connections,
49-
Err(err) => {
50-
error!(%err, "Failed to create IPC listener");
51-
return Err(err)
52-
}
53-
};
48+
let name = to_name(path.as_ref())?;
49+
let listener = ls::ListenerOptions::new().name(name).create_tokio()?;
50+
// TODO: https://github.com/kotauskas/interprocess/issues/64
51+
let connections = futures::stream::unfold(listener, |listener| async move {
52+
let conn = listener.accept().await;
53+
Some((conn, listener))
54+
});
5455

5556
trace!("established connection listener");
5657

57-
let connections = connections.filter_map(move |stream| {
58+
Ok(connections.filter_map(move |stream| {
5859
let handler = handler.clone();
59-
Box::pin(async move {
60-
if let Ok(stream) = stream {
61-
trace!("successful incoming IPC connection");
62-
let framed = tokio_util::codec::Decoder::framed(JsonRpcCodec, stream);
63-
Some(PubSubConnection::new(IpcConn(framed), handler))
64-
} else {
65-
None
60+
async move {
61+
match stream {
62+
Ok(stream) => {
63+
trace!("successful incoming IPC connection");
64+
let framed = tokio_util::codec::Decoder::framed(JsonRpcCodec, stream);
65+
Some(PubSubConnection::new(IpcConn(framed), handler))
66+
}
67+
Err(err) => {
68+
trace!(%err, "unsuccessful incoming IPC connection");
69+
None
70+
}
6671
}
67-
})
68-
});
69-
Ok(connections)
72+
}
73+
}))
7074
}
7175
}
7276

@@ -118,7 +122,7 @@ where
118122

119123
struct JsonRpcCodec;
120124

121-
// Adapted from <https://github.dev/paritytech/jsonrpc/blob/38af3c9439aa75481805edf6c05c6622a5ab1e70/server-utils/src/stream_codec.rs#L47-L105>
125+
// Adapted from <https://github.com/paritytech/jsonrpc/blob/38af3c9439aa75481805edf6c05c6622a5ab1e70/server-utils/src/stream_codec.rs#L47-L105>
122126
impl tokio_util::codec::Decoder for JsonRpcCodec {
123127
type Item = String;
124128
type Error = io::Error;
@@ -171,3 +175,11 @@ impl tokio_util::codec::Encoder<String> for JsonRpcCodec {
171175
Ok(())
172176
}
173177
}
178+
179+
fn to_name(path: &std::ffi::OsStr) -> io::Result<ls::Name<'_>> {
180+
if cfg!(windows) && !path.as_encoded_bytes().starts_with(br"\\.\pipe\") {
181+
ls::ToNsName::to_ns_name::<ls::GenericNamespaced>(path)
182+
} else {
183+
ls::ToFsName::to_fs_name::<ls::GenericFilePath>(path)
184+
}
185+
}

crates/anvil/src/config.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,8 @@ pub const CHAIN_ID: u64 = 31337;
5959
pub const DEFAULT_MNEMONIC: &str = "test test test test test test test test test test test junk";
6060

6161
/// The default IPC endpoint
62-
#[cfg(windows)]
63-
pub const DEFAULT_IPC_ENDPOINT: &str = r"\\.\pipe\anvil.ipc";
64-
65-
/// The default IPC endpoint
66-
#[cfg(not(windows))]
67-
pub const DEFAULT_IPC_ENDPOINT: &str = "/tmp/anvil.ipc";
62+
pub const DEFAULT_IPC_ENDPOINT: &str =
63+
if cfg!(unix) { "/tmp/anvil.ipc" } else { r"\\.\pipe\anvil.ipc" };
6864

6965
/// `anvil 0.1.0 (f01b232bc 2022-04-13T23:28:39.493201+00:00)`
7066
pub const VERSION_MESSAGE: &str = concat!(
@@ -801,7 +797,7 @@ impl NodeConfig {
801797

802798
/// Returns the ipc path for the ipc endpoint if any
803799
pub fn get_ipc_path(&self) -> Option<String> {
804-
match self.ipc_path.as_ref() {
800+
match &self.ipc_path {
805801
Some(path) => path.clone().or_else(|| Some(DEFAULT_IPC_ENDPOINT.to_string())),
806802
None => None,
807803
}

crates/anvil/src/lib.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
},
1313
filter::Filters,
1414
logging::{LoggingManager, NodeLogLayer},
15+
server::error::{NodeError, NodeResult},
1516
service::NodeService,
1617
shutdown::Signal,
1718
tasks::TaskManager,
@@ -23,6 +24,7 @@ use foundry_common::provider::{ProviderBuilder, RetryProvider};
2324
use foundry_evm::revm;
2425
use futures::{FutureExt, TryFutureExt};
2526
use parking_lot::Mutex;
27+
use server::try_spawn_ipc;
2628
use std::{
2729
future::Future,
2830
io,
@@ -41,11 +43,8 @@ mod service;
4143

4244
mod config;
4345
pub use config::{AccountGenerator, NodeConfig, CHAIN_ID, VERSION_MESSAGE};
46+
4447
mod hardfork;
45-
use crate::server::{
46-
error::{NodeError, NodeResult},
47-
spawn_ipc,
48-
};
4948
pub use hardfork::Hardfork;
5049

5150
/// ethereum related implementations
@@ -223,7 +222,8 @@ pub async fn try_spawn(mut config: NodeConfig) -> io::Result<(EthApi, NodeHandle
223222
let (signal, on_shutdown) = shutdown::signal();
224223
let task_manager = TaskManager::new(tokio_handle, on_shutdown);
225224

226-
let ipc_task = config.get_ipc_path().map(|path| spawn_ipc(api.clone(), path));
225+
let ipc_task =
226+
config.get_ipc_path().map(|path| try_spawn_ipc(api.clone(), path)).transpose()?;
227227

228228
let handle = NodeHandle {
229229
config,
@@ -310,8 +310,10 @@ impl NodeHandle {
310310

311311
/// Constructs a [`RetryProvider`] for this handle's HTTP endpoint.
312312
pub fn http_provider(&self) -> RetryProvider {
313-
ProviderBuilder::new(&self.http_endpoint()).build().expect("failed to build HTTP provider")
314-
// .interval(Duration::from_millis(500))
313+
ProviderBuilder::new(&self.http_endpoint())
314+
.aggressive()
315+
.build()
316+
.expect("failed to build HTTP provider")
315317
}
316318

317319
/// Constructs a [`RetryProvider`] for this handle's WS endpoint.

crates/anvil/tests/it/ipc.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,34 @@
11
//! IPC tests
22
3-
use crate::utils::connect_pubsub;
3+
use crate::{init_tracing, utils::connect_pubsub};
44
use alloy_primitives::U256;
55
use alloy_provider::Provider;
66
use anvil::{spawn, NodeConfig};
77
use futures::StreamExt;
8-
9-
pub fn rand_ipc_endpoint() -> String {
10-
let num: u64 = rand::Rng::gen(&mut rand::thread_rng());
11-
if cfg!(windows) {
12-
format!(r"\\.\pipe\anvil-ipc-{num}")
8+
use tempfile::TempDir;
9+
10+
fn ipc_config() -> (Option<TempDir>, NodeConfig) {
11+
let path;
12+
let dir;
13+
if cfg!(unix) {
14+
let tmp = tempfile::tempdir().unwrap();
15+
path = tmp.path().join("anvil.ipc").to_string_lossy().into_owned();
16+
dir = Some(tmp);
1317
} else {
14-
format!(r"/tmp/anvil-ipc-{num}")
18+
dir = None;
19+
path = format!(r"\\.\pipe\anvil_test_{}.ipc", rand::random::<u64>());
1520
}
16-
}
17-
18-
fn ipc_config() -> NodeConfig {
19-
NodeConfig::test().with_ipc(Some(Some(rand_ipc_endpoint())))
21+
let config = NodeConfig::test().with_ipc(Some(Some(path)));
22+
(dir, config)
2023
}
2124

2225
#[tokio::test(flavor = "multi_thread")]
23-
#[cfg_attr(target_os = "windows", ignore)]
26+
#[cfg_attr(windows, ignore = "TODO")]
2427
async fn can_get_block_number_ipc() {
25-
let (api, handle) = spawn(ipc_config()).await;
28+
init_tracing();
29+
30+
let (_dir, config) = ipc_config();
31+
let (api, handle) = spawn(config).await;
2632

2733
let block_num = api.block_number().unwrap();
2834
assert_eq!(block_num, U256::ZERO);
@@ -34,17 +40,19 @@ async fn can_get_block_number_ipc() {
3440
}
3541

3642
#[tokio::test(flavor = "multi_thread")]
37-
#[cfg_attr(target_os = "windows", ignore)]
43+
#[cfg_attr(windows, ignore = "TODO")]
3844
async fn test_sub_new_heads_ipc() {
39-
let (api, handle) = spawn(ipc_config()).await;
40-
41-
let provider = connect_pubsub(handle.ipc_path().unwrap().as_str()).await;
45+
init_tracing();
4246

43-
let blocks = provider.subscribe_blocks().await.unwrap().into_stream();
47+
let (_dir, config) = ipc_config();
48+
let (api, handle) = spawn(config).await;
4449

50+
let provider = connect_pubsub(handle.ipc_path().unwrap().as_str()).await;
4551
// mine a block every 1 seconds
4652
api.anvil_set_interval_mining(1).unwrap();
4753

54+
let blocks = provider.subscribe_blocks().await.unwrap().into_stream();
55+
4856
let blocks = blocks.take(3).collect::<Vec<_>>().await;
4957
let block_numbers = blocks.into_iter().map(|b| b.header.number.unwrap()).collect::<Vec<_>>();
5058

crates/common/src/provider/runtime_transport.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl RuntimeTransport {
195195
async fn connect_ipc(&self) -> Result<InnerTransport, RuntimeTransportError> {
196196
let path = url_to_file_path(&self.url)
197197
.map_err(|_| RuntimeTransportError::BadPath(self.url.to_string()))?;
198-
let ipc_connector: IpcConnect<PathBuf> = path.clone().into();
198+
let ipc_connector = IpcConnect::new(path.clone());
199199
let ipc = ipc_connector.into_service().await.map_err(|e| {
200200
RuntimeTransportError::TransportError(e, path.clone().display().to_string())
201201
})?;

0 commit comments

Comments
 (0)