Skip to content

Commit e60c6b2

Browse files
authored
Merge pull request #1486 from jbesraa/2025-02-12/jdc-fallback-test
JDC Fallback test
2 parents a972282 + 03011f2 commit e60c6b2

File tree

11 files changed

+102
-335
lines changed

11 files changed

+102
-335
lines changed

roles/test-utils/mining-device-sv1/src/client.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,8 @@ impl Client {
244244
if let Ok(incoming) = recv_incoming.clone().recv().await {
245245
Self::parse_message(client.clone(), Ok(incoming)).await;
246246
} else {
247-
warn!("Error reading from socket via `recv_incoming` channel")
247+
warn!("Error reading from socket via `recv_incoming` channel");
248+
break;
248249
}
249250
}
250251
}

roles/tests-integration/lib/mod.rs

+23-15
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub async fn start_pool(template_provider_address: Option<SocketAddr>) -> (PoolS
9494
assert!(pool_clone.start().await.is_ok());
9595
});
9696
// Wait a bit to let the pool exchange initial messages with the TP
97-
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
97+
sleep(1).await;
9898
(pool, listening_address)
9999
}
100100

@@ -107,9 +107,8 @@ pub fn start_template_provider(sv2_interval: Option<u32>) -> (TemplateProvider,
107107
}
108108

109109
pub async fn start_jdc(
110-
pool_address: SocketAddr,
110+
pool: &[(SocketAddr, SocketAddr)], // (pool_address, jds_address)
111111
tp_address: SocketAddr,
112-
jds_address: SocketAddr,
113112
) -> (JobDeclaratorClient, SocketAddr) {
114113
use jd_client::config::{
115114
JobDeclaratorClientConfig, PoolConfig, ProtocolConfig, TPConfig, Upstream,
@@ -127,7 +126,6 @@ pub async fn start_jdc(
127126
"mkDLTBBRxdBv998612qipDYoTK3YUrqLe8uWw7gu3iXbSrn2n".to_string(),
128127
)
129128
.unwrap();
130-
let cert_validity_sec = 3600;
131129
let coinbase_outputs = vec![CoinbaseOutput::new(
132130
"P2WPKH".to_string(),
133131
"036adc3bdf21e6f9a0f0fb0066bf517e5b7909ed1563d6958a10993849a7554075".to_string(),
@@ -137,12 +135,17 @@ pub async fn start_jdc(
137135
)
138136
.unwrap();
139137
let pool_signature = "Stratum v2 SRI Pool".to_string();
140-
let upstreams = vec![Upstream::new(
141-
authority_pubkey,
142-
pool_address.to_string(),
143-
jds_address.to_string(),
144-
pool_signature,
145-
)];
138+
let upstreams = pool
139+
.iter()
140+
.map(|(pool_addr, jds_addr)| {
141+
Upstream::new(
142+
authority_pubkey,
143+
pool_addr.to_string(),
144+
jds_addr.to_string(),
145+
pool_signature.clone(),
146+
)
147+
})
148+
.collect();
146149
let pool_config = PoolConfig::new(authority_public_key, authority_secret_key);
147150
let tp_config = TPConfig::new(1000, tp_address.to_string(), None);
148151
let protocol_config = ProtocolConfig::new(
@@ -158,12 +161,12 @@ pub async fn start_jdc(
158161
pool_config,
159162
tp_config,
160163
upstreams,
161-
std::time::Duration::from_secs(cert_validity_sec),
164+
std::time::Duration::from_secs(1),
162165
);
163166
let ret = jd_client::JobDeclaratorClient::new(jd_client_proxy);
164167
let ret_clone = ret.clone();
165168
tokio::spawn(async move { ret_clone.start().await });
166-
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
169+
sleep(2).await;
167170
(ret, jdc_address)
168171
}
169172

@@ -211,7 +214,7 @@ pub async fn start_jds(tp_rpc_connection: &ConnectParams) -> (JobDeclaratorServe
211214
tokio::spawn(async move {
212215
job_declarator_server_clone.start().await.unwrap();
213216
});
214-
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
217+
sleep(2).await;
215218
(job_declarator_server, listen_jd_address)
216219
} else {
217220
panic!("Failed to get TP cookie values");
@@ -262,7 +265,7 @@ pub async fn start_sv2_translator(upstream: SocketAddr) -> (TranslatorSv2, Socke
262265
tokio::spawn(async move {
263266
clone_translator_v2.start().await;
264267
});
265-
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
268+
sleep(1).await;
266269
(translator_v2, listening_address)
267270
}
268271

@@ -311,7 +314,7 @@ pub async fn start_mining_device_sv1(
311314
mining_device_sv1::client::Client::connect(80, upstream_addr, single_submit, custom_target)
312315
.await;
313316
});
314-
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
317+
sleep(3).await;
315318
}
316319

317320
pub async fn start_mining_device_sv2(
@@ -363,3 +366,8 @@ pub async fn start_mining_sv2_proxy(upstream: SocketAddr) -> SocketAddr {
363366
});
364367
mining_proxy_listening_address
365368
}
369+
370+
#[inline]
371+
pub async fn sleep(seconds: u64) {
372+
tokio::time::sleep(std::time::Duration::from_secs(seconds)).await;
373+
}

roles/tests-integration/tests/jd_integration.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ async fn jds_should_not_panic_if_jdc_shutsdown() {
2525
let (tp, tp_addr) = start_template_provider(None);
2626
let (_pool, pool_addr) = start_pool(Some(tp_addr)).await;
2727
let (_jds, jds_addr) = start_jds(tp.rpc_info()).await;
28-
let (jdc, jdc_addr) = start_jdc(pool_addr, tp_addr, jds_addr).await;
28+
let (jdc, jdc_addr) = start_jdc(&[(pool_addr, jds_addr)], tp_addr).await;
2929
jdc.shutdown();
3030
// wait for shutdown to complete
3131
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
3232
assert!(tokio::net::TcpListener::bind(jdc_addr).await.is_ok());
3333
let (sniffer, sniffer_addr) = start_sniffer("0".to_string(), jds_addr, false, None).await;
34-
let (_jdc_1, _jdc_addr_1) = start_jdc(pool_addr, tp_addr, sniffer_addr).await;
34+
let (_jdc_1, _jdc_addr_1) = start_jdc(&[(pool_addr, sniffer_addr)], tp_addr).await;
3535
assert_common_message!(sniffer.next_message_from_downstream(), SetupConnection);
3636
}
3737

@@ -47,7 +47,7 @@ async fn jdc_tp_success_setup() {
4747
let (_jds, jds_addr) = start_jds(tp.rpc_info()).await;
4848
let (tp_jdc_sniffer, tp_jdc_sniffer_addr) =
4949
start_sniffer("0".to_string(), tp_addr, false, None).await;
50-
let (_jdc, jdc_addr) = start_jdc(pool_addr, tp_jdc_sniffer_addr, jds_addr).await;
50+
let (_jdc, jdc_addr) = start_jdc(&[(pool_addr, jds_addr)], tp_jdc_sniffer_addr).await;
5151
// This is needed because jd-client waits for a downstream connection before it starts
5252
// exchanging messages with the Template Provider.
5353
start_sv2_translator(jdc_addr).await;
@@ -84,7 +84,7 @@ async fn jdc_does_not_stackoverflow_when_no_token() {
8484
Some(block_from_message.into()),
8585
)
8686
.await;
87-
let (_jdc, jdc_addr) = start_jdc(pool_addr, tp_addr, jds_jdc_sniffer_addr).await;
87+
let (_jdc, jdc_addr) = start_jdc(&[(pool_addr, jds_jdc_sniffer_addr)], tp_addr).await;
8888
let _ = start_sv2_translator(jdc_addr).await;
8989
jds_jdc_sniffer
9090
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use const_sv2::{MESSAGE_TYPE_SETUP_CONNECTION, MESSAGE_TYPE_SUBMIT_SHARES_SUCCESS};
2+
use integration_tests_sv2::*;
3+
use roles_logic_sv2::{
4+
mining_sv2::SubmitSharesError,
5+
parsers::{AnyMessage, Mining},
6+
};
7+
use sniffer::{MessageDirection, ReplaceMessage};
8+
use std::convert::TryInto;
9+
10+
// Tests whether JDC will switch to a new pool after receiving a `SubmitSharesError` message from
11+
// the currently connected pool.
12+
#[tokio::test]
13+
async fn test_jdc_pool_fallback_after_submit_rejection() {
14+
start_tracing();
15+
let (tp, tp_addr) = start_template_provider(None);
16+
let (_pool_1, pool_addr_1) = start_pool(Some(tp_addr)).await;
17+
// Sniffer between JDC and first pool
18+
let (sniffer_1, sniffer_addr_1) = start_sniffer(
19+
"0".to_string(),
20+
pool_addr_1,
21+
false,
22+
Some(
23+
// Should trigger Fallback process in JDC
24+
ReplaceMessage::new(
25+
MessageDirection::ToDownstream,
26+
MESSAGE_TYPE_SUBMIT_SHARES_SUCCESS,
27+
AnyMessage::Mining(Mining::SubmitSharesError(SubmitSharesError {
28+
channel_id: 0,
29+
sequence_number: 0,
30+
error_code: "invalid-nonce".to_string().into_bytes().try_into().unwrap(),
31+
})),
32+
)
33+
.into(),
34+
),
35+
)
36+
.await;
37+
let (_pool_2, pool_addr_2) = start_pool(Some(tp_addr)).await;
38+
// Sniffer between JDC and second pool
39+
let (sniffer_2, sniffer_addr_2) =
40+
start_sniffer("1".to_string(), pool_addr_2, false, None).await;
41+
let (_jds_1, jds_addr_1) = start_jds(tp.rpc_info()).await;
42+
// Sniffer between JDC and first JDS
43+
let (sniffer_3, sniffer_addr_3) = start_sniffer("2".to_string(), jds_addr_1, false, None).await;
44+
let (_jds_2, jds_addr_2) = start_jds(tp.rpc_info()).await;
45+
// Sniffer between JDC and second JDS
46+
let (sniffer_4, sniffer_addr_4) = start_sniffer("3".to_string(), jds_addr_2, false, None).await;
47+
let (_jdc, jdc_addr) = start_jdc(
48+
&[
49+
(sniffer_addr_1, sniffer_addr_3),
50+
(sniffer_addr_2, sniffer_addr_4),
51+
],
52+
tp_addr,
53+
)
54+
.await;
55+
// Assert that JDC has connected to the first (Pool,JDS) pair
56+
sniffer_1
57+
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
58+
.await;
59+
sniffer_3
60+
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
61+
.await;
62+
let (_translator, sv2_translator_addr) = start_sv2_translator(jdc_addr).await;
63+
let _ = start_mining_device_sv1(sv2_translator_addr, true, None).await;
64+
// Assert that JDC switched to the second (Pool,JDS) pair
65+
sniffer_2
66+
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
67+
.await;
68+
sniffer_4
69+
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
70+
.await;
71+
}

roles/tests-integration/tests/translator_integration.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ async fn translation_proxy_and_jd() {
6565
let (jdc_pool_sniffer, jdc_pool_sniffer_addr) =
6666
start_sniffer("0".to_string(), pool_addr, false, None).await;
6767
let (_jds, jds_addr) = start_jds(tp.rpc_info()).await;
68-
let (_jdc, jdc_addr) = start_jdc(jdc_pool_sniffer_addr, tp_addr, jds_addr).await;
68+
let (_jdc, jdc_addr) = start_jdc(&[(jdc_pool_sniffer_addr, jds_addr)], tp_addr).await;
6969
let (_translator, tproxy_addr) = start_sv2_translator(jdc_addr).await;
7070
let _mining_device = start_mining_device_sv1(tproxy_addr, true, None).await;
7171
jdc_pool_sniffer

scripts/message-generator-tests.sh

+1-6
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,8 @@
33
search_dir="test/message-generator/test/"
44

55
for entry in `ls $search_dir`; do
6-
if [ "$entry" = "interop-jdc-change-upstream" ]; then
7-
echo "Skipping $entry"
8-
continue
9-
fi
10-
116
echo $entry
12-
$search_dir$entry/$entry.sh
7+
$search_dir$entry/$entry.sh
138
done
149

1510
cd roles

test/config/interop-jd-change-upstream/jdc-config.toml

-49
This file was deleted.

test/config/interop-jd-change-upstream/jds-config.toml

-20
This file was deleted.

test/config/interop-jd-change-upstream/proxy-config.toml

-13
This file was deleted.

0 commit comments

Comments
 (0)