Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.8.2" }

# debug flag
console-subscriber = { version = "0.4", optional = true }
tracing-subscriber = "0.3.20"

[dev-dependencies]
rblib = { git = "https://github.com/flashbots/rblib", rev = "989b942d0facdde135f05bf66a376e30ce21ebc7", features = [
Expand Down
83 changes: 23 additions & 60 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,40 +215,15 @@ fn expand_path(s: &str) -> Result<PathBuf> {
impl FlashblocksArgs {
/// Configures flashblocks for tests. Handles WS port assignment.
pub fn default_on_for_tests() -> Self {
use {
core::net::{Ipv4Addr, SocketAddrV4},
std::{
collections::HashSet,
net::TcpListener,
sync::{Mutex, OnceLock},
},
};

static RESERVED_PORTS: OnceLock<Mutex<HashSet<u16>>> = OnceLock::new();
let reserved = RESERVED_PORTS.get_or_init(|| Mutex::new(HashSet::new()));

let port = (12000..19000)
.find(|port| {
let addr = format!("0.0.0.0:{port}");
if let Ok(listener) = TcpListener::bind(&addr) {
drop(listener);
let mut set = reserved.lock().unwrap();
if set.contains(port) {
false
} else {
set.insert(*port);
true
}
} else {
false
}
})
.expect("No available ports found for test");
use core::net::{Ipv4Addr, SocketAddrV4};

Self {
interval: Duration::from_millis(250),
leeway_time: Duration::from_millis(75),
enabled: Some(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port).into()),
enabled: Some(
SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, Self::get_available_port())
.into(),
),
calculate_state_root: true,
}
}
Expand All @@ -257,41 +232,29 @@ impl FlashblocksArgs {
leeway_time: Duration,
interval: Duration,
) -> Self {
use {
core::net::{Ipv4Addr, SocketAddrV4},
std::{
collections::HashSet,
net::TcpListener,
sync::{Mutex, OnceLock},
},
};

static RESERVED_PORTS: OnceLock<Mutex<HashSet<u16>>> = OnceLock::new();
let reserved = RESERVED_PORTS.get_or_init(|| Mutex::new(HashSet::new()));

let port = (12000..19000)
.find(|port| {
let addr = format!("0.0.0.0:{port}");
if let Ok(listener) = TcpListener::bind(&addr) {
drop(listener);
let mut set = reserved.lock().unwrap();
if set.contains(port) {
false
} else {
set.insert(*port);
true
}
} else {
false
}
})
.expect("No available ports found for test");
use core::net::{Ipv4Addr, SocketAddrV4};

Self {
interval,
leeway_time,
enabled: Some(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port).into()),
enabled: Some(
SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, Self::get_available_port())
.into(),
),
calculate_state_root: true,
}
}

/// Gets an available port by first binding to port 0 -- instructing the OS to
/// find and assign one. Then the listener is dropped when this goes out of
/// scope, freeing the port for the next time this function is called.
fn get_available_port() -> u16 {
use std::net::TcpListener;

TcpListener::bind("127.0.0.1:0")
.expect("Failed to bind to random port")
.local_addr()
.expect("Failed to get local address")
.port()
}
}
Loading
Loading