diff --git a/roles/Cargo.lock b/roles/Cargo.lock index 2e9ee5b98..f86606280 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -1355,6 +1355,7 @@ dependencies = [ "bitcoind", "flate2", "key-utils", + "mining_device", "minreq", "once_cell", "pool_sv2", diff --git a/roles/tests-integration/Cargo.toml b/roles/tests-integration/Cargo.toml index a1d17847f..b10daf0dd 100644 --- a/roles/tests-integration/Cargo.toml +++ b/roles/tests-integration/Cargo.toml @@ -12,6 +12,10 @@ tar = "0.4.41" pool_sv2 = { version = "0.1.0", path = "../pool" } key-utils = { version = "1.0.0", path = "../../utils/key-utils" } tokio = { version = "1.16.1", features = ["full"] } +mining_device = { version = "0.1.1", path = "../test-utils/mining-device" } [lib] path = "tests/common/mod.rs" + +[features] +mining_device_reject_auth = ["pool_sv2/MG_reject_auth", "mining_device/abort_mining"] diff --git a/roles/tests-integration/tests/common/mod.rs b/roles/tests-integration/tests/common/mod.rs index 1691021f3..7bf8d7273 100644 --- a/roles/tests-integration/tests/common/mod.rs +++ b/roles/tests-integration/tests/common/mod.rs @@ -287,3 +287,13 @@ pub async fn start_template_provider_and_pool() -> Result<(PoolSv2, u16, Templat template_provider_port, )) } + +pub struct TestMiningDevice; + +impl TestMiningDevice { + pub async fn start(pool_address: SocketAddr) -> Result<(), pool_sv2::error::PoolError> { + mining_device::connect(pool_address.to_string(), None, None, None, 0) + .await + .map_err(|e| e.into()) + } +} diff --git a/roles/tests-integration/tests/pool_integration.rs b/roles/tests-integration/tests/pool_integration.rs index 4e9fc123a..f73cf7751 100644 --- a/roles/tests-integration/tests/pool_integration.rs +++ b/roles/tests-integration/tests/pool_integration.rs @@ -1,5 +1,7 @@ use std::str::FromStr; +use common::is_port_open; + mod common; #[tokio::test] @@ -29,3 +31,47 @@ async fn pool_bad_coinbase_output() { assert_eq!(state, pool_sv2::PoolState::Initial); template_provider.stop(); } + +#[cfg(feature = "mining_device_reject_auth")] +#[tokio::test] +async fn pool_remove_downstream_after_bad_auth() { + let (template_provider, template_provider_port) = common::start_template_provider().await; + let test_pool = common::TestPoolSv2::new( + None, + None, + Some( + std::net::SocketAddr::from_str(&format!("127.0.0.1:{}", template_provider_port)) + .unwrap(), + ), + ); + let pool = test_pool.pool.clone(); + let state = pool.state().await.safe_lock(|s| s.clone()).unwrap(); + assert_eq!(state, pool_sv2::PoolState::Initial); + let _pool = pool.clone(); + tokio::task::spawn(async move { + let _ = _pool.start().await; + }); + tokio::time::sleep(std::time::Duration::from_secs(1)).await; + // Wait for the pool to start. + let pool_port = test_pool.port; + let pool_listening_address = + std::net::SocketAddr::from_str(&format!("127.0.0.1:{}", pool_port)).unwrap(); + loop { + if is_port_open(pool_listening_address) { + break; + } + } + let state = pool.state().await.safe_lock(|s| s.clone()).unwrap(); + assert_eq!( + state, + pool_sv2::PoolState::Running(pool_sv2::DroppedDownstreams::new()) + ); + assert!(common::TestMiningDevice::start(pool_listening_address) + .await + .is_err()); + let state = pool.state().await.safe_lock(|s| s.clone()).unwrap(); + let mut dropped_downstreams = pool_sv2::DroppedDownstreams::new(); + dropped_downstreams.push(1); + assert_eq!(state, pool_sv2::PoolState::Running(dropped_downstreams)); + template_provider.stop(); +}