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
11 changes: 8 additions & 3 deletions integration-tests/lib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ pub fn start_jdc(
template_provider_config: TemplateProviderType,
supported_extensions: Vec<u16>,
required_extensions: Vec<u16>,
jdc_mode: Option<&str>,
) -> (JobDeclaratorClient, SocketAddr) {
use jd_client_sv2::config::{JobDeclaratorClientConfig, PoolConfig, ProtocolConfig, Upstream};
let jdc_address = get_available_address();
Expand Down Expand Up @@ -239,7 +240,7 @@ pub fn start_jdc(
template_provider_config,
upstreams,
jdc_signature,
None,
jdc_mode.map(|s| s.to_string()),
supported_extensions,
required_extensions,
);
Expand All @@ -249,7 +250,10 @@ pub fn start_jdc(
(ret, jdc_address)
}

pub fn start_jds(tp_rpc_connection: &ConnectParams) -> (JobDeclaratorServer, SocketAddr) {
pub fn start_jds(
tp_rpc_connection: &ConnectParams,
full_template_mode_required: bool,
) -> (JobDeclaratorServer, SocketAddr) {
use jd_server::config::{CoreRpc, JobDeclaratorServerConfig};
let authority_public_key = JdServerSecp256k1PublicKey::try_from(
"9auqWEzQDVyd2oe1JVGFLMLHZtCo2FFqZwtKA5gd9xbuEu7PH72".to_string(),
Expand Down Expand Up @@ -277,7 +281,7 @@ pub fn start_jds(tp_rpc_connection: &ConnectParams) -> (JobDeclaratorServer, Soc
user,
password,
);
let config = JobDeclaratorServerConfig::new(
let mut config = JobDeclaratorServerConfig::new(
listen_jd_address.to_string(),
authority_public_key,
authority_secret_key,
Expand All @@ -286,6 +290,7 @@ pub fn start_jds(tp_rpc_connection: &ConnectParams) -> (JobDeclaratorServer, Soc
core_rpc,
std::time::Duration::from_secs(1),
);
config.set_full_template_mode_required(full_template_mode_required);
let job_declarator_server = JobDeclaratorServer::new(config);
let job_declarator_server_clone = job_declarator_server.clone();
tokio::spawn(async move {
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 @@ -46,7 +46,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) = start_pool(sv2_tp_config(tp_addr), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp.rpc_info());
let (_jds, jds_addr) = start_jds(tp.rpc_info(), true);
let ignore_push_solution =
IgnoreMessage::new(MessageDirection::ToUpstream, MESSAGE_TYPE_PUSH_SOLUTION);
let (sniffer, sniffer_addr) = start_sniffer(
Expand All @@ -61,6 +61,7 @@ async fn jdc_propagates_block_with_bitcoin_core_ipc() {
ipc_config(tp.data_dir().clone(), tp.is_signet()),
vec![],
vec![],
None,
);
let (translator, tproxy_addr) =
start_sv2_translator(&[jdc_addr], false, vec![], vec![], None).await;
Expand Down
57 changes: 57 additions & 0 deletions integration-tests/tests/jd_coinbase_only_block_propagation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use integration_tests_sv2::{interceptor::MessageDirection, template_provider::DifficultyLevel, *};
use stratum_apps::stratum_core::{
common_messages_sv2::*, job_declaration_sv2::*, template_distribution_sv2::*,
};

// In CoinbaseOnly mode, block propagation should happen only from JDC to TP.
// PushSolution to JDS should NOT occur since no job was declared.
#[tokio::test]
async fn coinbase_only_block_propagated_from_jdc_not_jds() {
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) = start_pool(sv2_tp_config(tp_addr), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp.rpc_info(), false);
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![],
Some("COINBASEONLY"),
);
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).await;
let (_minerd_process, _minerd_addr) = start_minerd(tproxy_addr, None, None, false).await;

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);

jdc_jds_sniffer.clean_queue(MessageDirection::ToUpstream);
assert!(
jdc_jds_sniffer
.assert_message_not_present(
MessageDirection::ToUpstream,
MESSAGE_TYPE_PUSH_SOLUTION,
std::time::Duration::from_secs(3),
)
.await,
"PushSolution should NOT be sent to JDS in CoinbaseOnly mode"
);
}
40 changes: 40 additions & 0 deletions integration-tests/tests/jd_full_template_mode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use integration_tests_sv2::{interceptor::MessageDirection, template_provider::DifficultyLevel, *};
use stratum_apps::stratum_core::{common_messages_sv2::*, job_declaration_sv2::*};

// JDC in FullTemplate mode (default) should exchange DeclareMiningJob with 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 (_pool, pool_addr) = start_pool(sv2_tp_config(tp_addr), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp.rpc_info(), true);
let (jdc_jds_sniffer, jdc_jds_sniffer_addr) =
start_sniffer("jdc-jds", jds_addr, false, vec![], None);
let (_jdc, jdc_addr) = start_jdc(
&[(pool_addr, jdc_jds_sniffer_addr)],
sv2_tp_config(tp_addr),
vec![],
vec![],
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).await;
let (_minerd_process, _minerd_addr) = start_minerd(tproxy_addr, None, None, false).await;

jdc_jds_sniffer
.wait_for_message_type(
MessageDirection::ToUpstream,
MESSAGE_TYPE_DECLARE_MINING_JOB,
)
.await;
}
22 changes: 15 additions & 7 deletions integration-tests/tests/jd_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ 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) = start_pool(sv2_tp_config(tp_addr), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp.rpc_info());
let (_jds, jds_addr) = start_jds(tp.rpc_info(), true);
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![],
None,
);
sniffer_a
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
Expand All @@ -48,6 +49,7 @@ async fn jds_should_not_panic_if_jdc_shutsdown() {
sv2_tp_config(tp_addr),
vec![],
vec![],
None,
);
sniffer
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
Expand All @@ -64,13 +66,14 @@ async fn jdc_tp_success_setup() {
start_tracing();
let (tp, tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (pool, pool_addr) = start_pool(sv2_tp_config(tp_addr), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp.rpc_info());
let (_jds, jds_addr) = start_jds(tp.rpc_info(), true);
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![],
None,
);
// This is needed because jd-client waits for a downstream connection before it starts
// exchanging messages with the Template Provider.
Expand Down Expand Up @@ -98,7 +101,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) = start_pool(sv2_tp_config(tp_addr_1), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp_1.rpc_info());
let (_jds, jds_addr) = start_jds(tp_1.rpc_info(), true);

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 @@ -135,6 +138,7 @@ async fn jds_receive_solution_while_processing_declared_job_test() {
sv2_tp_config(tp_addr_2),
vec![],
vec![],
None,
);
let (translator, tproxy_addr) =
start_sv2_translator(&[jdc_addr], false, vec![], vec![], None).await;
Expand Down Expand Up @@ -197,7 +201,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) = start_pool(sv2_tp_config(tp_addr_1), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp_1.rpc_info());
let (_jds, jds_addr) = start_jds(tp_1.rpc_info(), true);

let provide_missing_transaction_success_replace = ReplaceMessage::new(
MessageDirection::ToUpstream,
Expand Down Expand Up @@ -227,6 +231,7 @@ async fn jds_wont_exit_upon_receiving_unexpected_txids_in_provide_missing_transa
sv2_tp_config(tp_addr_2),
vec![],
vec![],
None,
);
let (translator, tproxy_addr) =
start_sv2_translator(&[jdc_addr_1], false, vec![], vec![], None).await;
Expand Down Expand Up @@ -285,13 +290,14 @@ 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) = start_pool(sv2_tp_config(tp_addr), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp.rpc_info());
let (_jds, jds_addr) = start_jds(tp.rpc_info(), true);

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

let (sniffer, sniffer_addr) = start_sniffer("sniffer", jdc_addr, false, vec![], None);
Expand Down Expand Up @@ -468,13 +474,14 @@ 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) = start_pool(sv2_tp_config(tp_addr), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp.rpc_info());
let (_jds, jds_addr) = start_jds(tp.rpc_info(), true);

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

let (sniffer, sniffer_addr) = start_sniffer("sniffer", jdc_addr, false, vec![], None);
Expand Down Expand Up @@ -660,13 +667,14 @@ 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) = start_pool(sv2_tp_config(tp_addr), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp.rpc_info());
let (_jds, jds_addr) = start_jds(tp.rpc_info(), true);

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

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

// JDS requires FullTemplate but JDC asks for CoinbaseOnly
#[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) = start_pool(sv2_tp_config(tp_addr), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp.rpc_info(), true);
let (sniffer, sniffer_addr) = start_sniffer("jdc-jds", jds_addr, false, vec![], None);
let (_jdc, _jdc_addr) = start_jdc(
&[(pool_addr, sniffer_addr)],
sv2_tp_config(tp_addr),
vec![],
vec![],
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;
}

// JDS allows CoinbaseOnly and JDC asks for CoinbaseOnly
// DeclareMiningJob should NOT be exchanged
#[tokio::test]
async fn jd_coinbase_only_mode_no_declare_mining_job() {
start_tracing();
let (tp, tp_addr) = start_template_provider(None, DifficultyLevel::Low);
let (_pool, pool_addr) = start_pool(sv2_tp_config(tp_addr), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp.rpc_info(), false);
let (jdc_jds_sniffer, jdc_jds_sniffer_addr) =
start_sniffer("jdc-jds", jds_addr, false, vec![], None);
let (jdc_pool_sniffer, jdc_pool_sniffer_addr) =
start_sniffer("jdc-pool", pool_addr, false, vec![], None);
let (_jdc, jdc_addr) = start_jdc(
&[(jdc_pool_sniffer_addr, jdc_jds_sniffer_addr)],
sv2_tp_config(tp_addr),
vec![],
vec![],
Some("COINBASEONLY"),
);
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).await;
let (_minerd_process, _minerd_addr) = start_minerd(tproxy_addr, None, None, false).await;

jdc_pool_sniffer
.wait_for_message_type(MessageDirection::ToUpstream, MESSAGE_TYPE_SETUP_CONNECTION)
.await;
jdc_pool_sniffer
.wait_for_message_type(
MessageDirection::ToDownstream,
MESSAGE_TYPE_SETUP_CONNECTION_SUCCESS,
)
.await;
jdc_pool_sniffer
.wait_for_message_type(
MessageDirection::ToUpstream,
MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL,
)
.await;
jdc_pool_sniffer
.wait_for_message_type(
MessageDirection::ToDownstream,
MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL_SUCCESS,
)
.await;

jdc_jds_sniffer.clean_queue(MessageDirection::ToUpstream);
assert!(
jdc_jds_sniffer
.assert_message_not_present(
MessageDirection::ToUpstream,
MESSAGE_TYPE_DECLARE_MINING_JOB,
std::time::Duration::from_secs(5),
)
.await,
"DeclareMiningJob should NOT be sent to JDS in CoinbaseOnly mode"
);
}
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,13 +7,14 @@ 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) = start_pool(sv2_tp_config(tp_addr_1), vec![], vec![]).await;
let (_jds, jds_addr) = start_jds(tp_1.rpc_info());
let (_jds, jds_addr) = start_jds(tp_1.rpc_info(), true);
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![],
None,
);
let (translator, tproxy_addr) =
start_sv2_translator(&[jdc_addr], false, vec![], vec![], None).await;
Expand Down
Loading
Loading