Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
10 changes: 8 additions & 2 deletions integration-tests/lib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ pub fn start_jdc(
supported_extensions: Vec<u16>,
required_extensions: Vec<u16>,
enable_monitoring: bool,
jdc_mode: Option<&str>,
) -> (JobDeclaratorClient, SocketAddr, Option<SocketAddr>) {
use jd_client_sv2::config::{JobDeclaratorClientConfig, PoolConfig, ProtocolConfig, Upstream};
let jdc_address = get_available_address();
Expand Down Expand Up @@ -255,7 +256,7 @@ pub fn start_jdc(
template_provider_config,
upstreams,
jdc_signature,
None,
jdc_mode.map(|s| s.to_string()),
supported_extensions,
required_extensions,
monitoring_address,
Expand All @@ -272,6 +273,7 @@ pub async fn start_pool_with_jds(
supported_extensions: Vec<u16>,
required_extensions: Vec<u16>,
enable_monitoring: bool,
full_template_mode_required: bool,
) -> (PoolSv2, SocketAddr, SocketAddr, Option<SocketAddr>) {
use pool_sv2::config::{AuthorityConfig, ConnectionConfig, JDSPartialConfig, PoolConfig};

Expand Down Expand Up @@ -318,7 +320,11 @@ pub async fn start_pool_with_jds(
required_extensions.clone(),
monitoring_address,
monitoring_cache_refresh_secs,
Some(JDSPartialConfig::new(jds_address)),
Some({
let mut jds_partial = JDSPartialConfig::new(jds_address);
jds_partial.set_full_template_mode_required(full_template_mode_required);
jds_partial
}),
);

let pool = PoolSv2::new(config);
Expand Down
3 changes: 2 additions & 1 deletion integration-tests/tests/bitcoin_core_ipc_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ async fn jdc_propagates_block_with_bitcoin_core_ipc() {
let (tp, _tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let current_block_hash = tp.get_best_block_hash().unwrap();
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let ignore_push_solution =
IgnoreMessage::new(MessageDirection::ToUpstream, MESSAGE_TYPE_PUSH_SOLUTION);
let (sniffer, sniffer_addr) = start_sniffer(
Expand All @@ -71,6 +71,7 @@ async fn jdc_propagates_block_with_bitcoin_core_ipc() {
vec![],
vec![],
false,
None,
);
let (translator, tproxy_addr, _) =
start_sv2_translator(&[jdc_addr], false, vec![], vec![], None, false).await;
Expand Down
67 changes: 67 additions & 0 deletions integration-tests/tests/jd_full_template_mode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use integration_tests_sv2::{interceptor::MessageDirection, template_provider::DifficultyLevel, *};
use stratum_apps::stratum_core::{
common_messages_sv2::*, job_declaration_sv2::*, template_distribution_sv2::*,
};

// JDC in FullTemplate mode (default) exchanges DeclareMiningJob with JDS
// and propagates blocks via both SubmitSolution (to TP) and PushSolution (to JDS)
#[tokio::test]
async fn jd_full_template_mode_declare_mining_job_exchanged() {
start_tracing();
let (tp, tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let current_block_hash = tp.get_best_block_hash().unwrap();
let (_pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let (jdc_jds_sniffer, jdc_jds_sniffer_addr) =
start_sniffer("jdc-jds", jds_addr, false, vec![], None);
let (jdc_tp_sniffer, jdc_tp_sniffer_addr) =
start_sniffer("jdc-tp", tp_addr, false, vec![], None);
let (_jdc, jdc_addr, _) = start_jdc(
&[(pool_addr, jdc_jds_sniffer_addr)],
sv2_tp_config(jdc_tp_sniffer_addr),
vec![],
vec![],
false,
None,
);
jdc_jds_sniffer
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
.await;
jdc_jds_sniffer
.wait_for_message_type(
MessageDirection::ToDownstream,
MESSAGE_TYPE_SETUP_CONNECTION_SUCCESS,
)
.await;

let (_translator, tproxy_addr, _) =
start_sv2_translator(&[jdc_addr], false, vec![], vec![], None, false).await;
let (_minerd, _) = start_minerd(tproxy_addr, None, None, false).await;

// DeclareMiningJob exchanged in both directions
jdc_jds_sniffer
.wait_for_message_type(
MessageDirection::ToUpstream,
MESSAGE_TYPE_DECLARE_MINING_JOB,
)
.await;
jdc_jds_sniffer
.wait_for_message_type(
MessageDirection::ToDownstream,
MESSAGE_TYPE_DECLARE_MINING_JOB_SUCCESS,
)
.await;

// block propagation from JDC to TP
jdc_tp_sniffer
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SUBMIT_SOLUTION)
.await;
let new_block_hash = tp.get_best_block_hash().unwrap();
assert_ne!(current_block_hash, new_block_hash);

// PushSolution sent to JDS in FullTemplate mode
assert!(
jdc_jds_sniffer.has_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_PUSH_SOLUTION),
"PushSolution should be sent to JDS in FullTemplate mode"
);
}
31 changes: 20 additions & 11 deletions integration-tests/tests/jd_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ async fn jds_should_not_panic_if_jdc_shutsdown() {
start_tracing();
let (tp, tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let (sniffer_a, sniffer_addr_a) = start_sniffer("0", jds_addr, false, vec![], None);
let (jdc, jdc_addr, _) = start_jdc(
&[(pool_addr, sniffer_addr_a)],
sv2_tp_config(tp_addr),
vec![],
vec![],
false,
None,
);
sniffer_a
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
Expand All @@ -50,6 +51,7 @@ async fn jds_should_not_panic_if_jdc_shutsdown() {
vec![],
vec![],
false,
None,
);
sniffer
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
Expand All @@ -66,14 +68,15 @@ async fn jdc_tp_success_setup() {
start_tracing();
let (tp, tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let (tp_jdc_sniffer, tp_jdc_sniffer_addr) = start_sniffer("0", tp_addr, false, vec![], None);
let (jdc, jdc_addr, _) = start_jdc(
&[(pool_addr, jds_addr)],
sv2_tp_config(tp_jdc_sniffer_addr),
vec![],
vec![],
false,
None,
);
// This is needed because jd-client waits for a downstream connection before it starts
// exchanging messages with the Template Provider.
Expand All @@ -97,7 +100,7 @@ async fn jds_reject_setup_connection_with_non_job_declaration_protocol() {
start_tracing();
let (tp, _tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (pool, _pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let (sniffer, sniffer_addr) = start_sniffer("mock-jds", jds_addr, false, vec![], None);
let _mock_downstream = MockDownstream::new(
sniffer_addr,
Expand Down Expand Up @@ -138,7 +141,7 @@ async fn jds_reject_setup_connection_without_declare_tx_data_flag() {
start_tracing();
let (tp, _tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (pool, _pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let (sniffer, sniffer_addr) = start_sniffer("mock-jds", jds_addr, false, vec![], None);
let _mock_downstream = MockDownstream::new(
sniffer_addr,
Expand Down Expand Up @@ -179,7 +182,7 @@ async fn jds_reject_declare_mining_job_with_invalid_mining_job_token() {
start_tracing();
let (tp, _tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (pool, _pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let (sniffer, sniffer_addr) = start_sniffer("mock-jds", jds_addr, false, vec![], None);
let send_to_jds = MockDownstream::new(
sniffer_addr,
Expand Down Expand Up @@ -303,7 +306,7 @@ async fn pool_rejects_reused_set_custom_mining_job_token() {
start_tracing();
let (tp, tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;

// First, run the regular JDC flow and capture one valid SetCustomMiningJob.
let (jdc_pool_sniffer, jdc_pool_sniffer_addr) =
Expand All @@ -314,6 +317,7 @@ async fn pool_rejects_reused_set_custom_mining_job_token() {
vec![],
vec![],
false,
None,
);
let (translator, tproxy_addr, _) =
start_sv2_translator(&[jdc_addr], false, vec![], vec![], None, false).await;
Expand Down Expand Up @@ -409,7 +413,7 @@ async fn jds_receive_solution_while_processing_declared_job_test() {
let (tp_1, _tp_addr_1) = start_template_provider(None, DifficultyLevel::Low);
let (tp_2, tp_addr_2) = start_template_provider(None, DifficultyLevel::Low);
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp_1.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp_1.bitcoin_core(), vec![], vec![], false, true).await;

let prev_hash = U256::Owned(vec![
184, 103, 138, 88, 153, 105, 236, 29, 123, 246, 107, 203, 1, 33, 10, 122, 188, 139, 218,
Expand Down Expand Up @@ -447,6 +451,7 @@ async fn jds_receive_solution_while_processing_declared_job_test() {
vec![],
vec![],
false,
None,
);
let (translator, tproxy_addr, _) =
start_sv2_translator(&[jdc_addr], false, vec![], vec![], None, false).await;
Expand Down Expand Up @@ -509,7 +514,7 @@ async fn jds_wont_exit_upon_receiving_unexpected_txids_in_provide_missing_transa
assert!(tp_2.create_mempool_transaction().is_ok());

let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp_1.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp_1.bitcoin_core(), vec![], vec![], false, true).await;

let provide_missing_transaction_success_replace = ReplaceMessage::new(
MessageDirection::ToUpstream,
Expand Down Expand Up @@ -540,6 +545,7 @@ async fn jds_wont_exit_upon_receiving_unexpected_txids_in_provide_missing_transa
vec![],
vec![],
false,
None,
);
let (translator, tproxy_addr, _) =
start_sv2_translator(&[jdc_addr_1], false, vec![], vec![], None, false).await;
Expand Down Expand Up @@ -598,14 +604,15 @@ async fn jdc_group_extended_channels() {
let (tp, tp_addr) = start_template_provider(sv2_interval, DifficultyLevel::Low);
tp.fund_wallet().unwrap();
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;

let (jdc, jdc_addr, _) = start_jdc(
&[(pool_addr, jds_addr)],
sv2_tp_config(tp_addr),
vec![],
vec![],
false,
None,
);

let (sniffer, sniffer_addr) = start_sniffer("sniffer", jdc_addr, false, vec![], None);
Expand Down Expand Up @@ -782,14 +789,15 @@ async fn jdc_group_standard_channels() {
let (tp, tp_addr) = start_template_provider(sv2_interval, DifficultyLevel::Low);
tp.fund_wallet().unwrap();
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;

let (jdc, jdc_addr, _) = start_jdc(
&[(pool_addr, jds_addr)],
sv2_tp_config(tp_addr),
vec![],
vec![],
false,
None,
);

let (sniffer, sniffer_addr) = start_sniffer("sniffer", jdc_addr, false, vec![], None);
Expand Down Expand Up @@ -975,14 +983,15 @@ async fn jdc_require_standard_jobs_set_does_not_group_standard_channels() {
let (tp, tp_addr) = start_template_provider(sv2_interval, DifficultyLevel::Low);
tp.fund_wallet().unwrap();
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], true).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], true, true).await;

let (jdc, jdc_addr, _) = start_jdc(
&[(pool_addr, jds_addr)],
sv2_tp_config(tp_addr),
vec![],
vec![],
false,
None,
);

let (sniffer, sniffer_addr) = start_sniffer("sniffer", jdc_addr, false, vec![], None);
Expand Down
33 changes: 33 additions & 0 deletions integration-tests/tests/jd_mining_modes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use integration_tests_sv2::{interceptor::MessageDirection, template_provider::DifficultyLevel, *};
use stratum_apps::stratum_core::common_messages_sv2::*;

// JDS requires FullTemplate but JDC asks for CoinbaseOnly — SetupConnection rejected
#[tokio::test]
async fn jd_mode_mismatch_setup_connection_fails() {
start_tracing();
let (tp, _tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (_pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let (sniffer, sniffer_addr) = start_sniffer("jdc-jds", jds_addr, false, vec![], None);
let (_jdc, _jdc_addr, _) = start_jdc(
&[(pool_addr, sniffer_addr)],
ipc_config(
tp.bitcoin_core().data_dir().clone(),
tp.bitcoin_core().is_signet(),
None,
),
vec![],
vec![],
false,
Some("COINBASEONLY"),
);
sniffer
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
.await;
sniffer
.wait_for_message_type(
MessageDirection::ToDownstream,
MESSAGE_TYPE_SETUP_CONNECTION_ERROR,
)
.await;
}
3 changes: 2 additions & 1 deletion integration-tests/tests/jd_provide_missing_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ async fn jds_ask_for_missing_transactions() {
let (tp_1, _tp_addr_1) = start_template_provider(None, DifficultyLevel::Low);
let (tp_2, tp_addr_2) = start_template_provider(None, DifficultyLevel::Low);
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp_1.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp_1.bitcoin_core(), vec![], vec![], false, true).await;
let (sniffer, sniffer_addr) = start_sniffer("A", jds_addr, false, vec![], None);
let (jdc, jdc_addr, _) = start_jdc(
&[(pool_addr, sniffer_addr)],
sv2_tp_config(tp_addr_2),
vec![],
vec![],
false,
None,
);
let (translator, tproxy_addr, _) =
start_sv2_translator(&[jdc_addr], false, vec![], vec![], None, false).await;
Expand Down
6 changes: 4 additions & 2 deletions integration-tests/tests/jd_tproxy_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ async fn jd_non_aggregated_tproxy_integration() {
start_tracing();
let (tp, _tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let (jdc_pool_sniffer, jdc_pool_sniffer_addr) =
start_sniffer("0", pool_addr, false, vec![], None);
let (jdc, jdc_addr, _) = start_jdc(
Expand All @@ -19,6 +19,7 @@ async fn jd_non_aggregated_tproxy_integration() {
vec![],
vec![],
false,
None,
);
let (tproxy_jdc_sniffer, tproxy_jdc_sniffer_addr) =
start_sniffer("1", jdc_addr, false, vec![], None);
Expand Down Expand Up @@ -94,7 +95,7 @@ async fn jd_aggregated_tproxy_integration() {
start_tracing();
let (tp, _tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let (jdc_pool_sniffer, jdc_pool_sniffer_addr) =
start_sniffer("0", pool_addr, false, vec![], None);
let (jdc, jdc_addr, _) = start_jdc(
Expand All @@ -107,6 +108,7 @@ async fn jd_aggregated_tproxy_integration() {
vec![],
vec![],
false,
None,
);
let (tproxy_jdc_sniffer, tproxy_jdc_sniffer_addr) =
start_sniffer("1", jdc_addr, false, vec![], None);
Expand Down
3 changes: 2 additions & 1 deletion integration-tests/tests/jdc_block_propagation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async fn propagated_from_jdc_to_tp() {
let (tp, tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let current_block_hash = tp.get_best_block_hash().unwrap();
let (pool, pool_addr, jds_addr, _) =
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false).await;
start_pool_with_jds(tp.bitcoin_core(), vec![], vec![], false, true).await;
let ignore_push_solution =
IgnoreMessage::new(MessageDirection::ToUpstream, MESSAGE_TYPE_PUSH_SOLUTION);
let (jdc_jds_sniffer, jdc_jds_sniffer_addr) = start_sniffer(
Expand All @@ -29,6 +29,7 @@ async fn propagated_from_jdc_to_tp() {
vec![],
vec![],
false,
None,
);
let (translator, tproxy_addr, _) =
start_sv2_translator(&[jdc_addr], false, vec![], vec![], None, false).await;
Expand Down
Loading
Loading