11mod common;
22
3- use std:: convert:: TryInto ;
4-
53use common:: { InterceptMessage , MessageDirection } ;
64use const_sv2:: {
7- MESSAGE_TYPE_NEW_TEMPLATE , MESSAGE_TYPE_SETUP_CONNECTION_ERROR , MESSAGE_TYPE_SET_NEW_PREV_HASH ,
5+ MESSAGE_TYPE_NEW_EXTENDED_MINING_JOB , MESSAGE_TYPE_NEW_TEMPLATE ,
6+ MESSAGE_TYPE_SETUP_CONNECTION_ERROR ,
87} ;
98use roles_logic_sv2:: {
109 common_messages_sv2:: { Protocol , SetupConnection , SetupConnectionError } ,
11- parsers:: { CommonMessages , PoolMessages , TemplateDistribution } ,
10+ parsers:: { AnyMessage , CommonMessages , Mining , PoolMessages , TemplateDistribution } ,
1211} ;
12+ use std:: convert:: TryInto ;
1313
1414// This test starts a Template Provider and a Pool, and checks if they exchange the correct
1515// messages upon connection.
@@ -20,7 +20,7 @@ async fn success_pool_template_provider_connection() {
2020 let sniffer_addr = common:: get_available_address ( ) ;
2121 let tp_addr = common:: get_available_address ( ) ;
2222 let pool_addr = common:: get_available_address ( ) ;
23- let _tp = common:: start_template_provider ( tp_addr. port ( ) ) . await ;
23+ let _tp = common:: start_template_provider ( tp_addr. port ( ) , None ) . await ;
2424 let sniffer_identifier =
2525 "success_pool_template_provider_connection tp_pool sniffer" . to_string ( ) ;
2626 let sniffer_check_on_drop = true ;
@@ -64,12 +64,113 @@ async fn success_pool_template_provider_connection() {
6464 assert_tp_message ! ( sniffer. next_message_from_upstream( ) , SetNewPrevHash ) ;
6565}
6666
67+ // This test starts a Template Provider, a Pool, and a Translator Proxy, and verifies the
68+ // correctness of the exchanged messages during connection and operation.
69+ //
70+ // Two Sniffers are used:
71+ // - Between the Template Provider and the Pool.
72+ // - Between the Pool and the Translator Proxy.
73+ //
74+ // The test ensures that:
75+ // - The Template Provider sends valid `SetNewPrevHash` and `NewTemplate` messages.
76+ // - The `minntime` field in the second `NewExtendedMiningJob` message sent to the Translator Proxy
77+ // matches the `header_timestamp` from the `SetNewPrevHash` message, addressing a bug that
78+ // occurred with non-future jobs.
79+ //
80+ // Related issue: https://github.com/stratum-mining/stratum/issues/1324
81+ #[ tokio:: test]
82+ async fn header_timestamp_value_assertion_in_new_extended_mining_job ( ) {
83+ let tp_pool_sniffer_addr = common:: get_available_address ( ) ;
84+ let pool_translator_sniffer_addr = common:: get_available_address ( ) ;
85+ let tp_addr = common:: get_available_address ( ) ;
86+ let pool_addr = common:: get_available_address ( ) ;
87+ let sv2_interval = Some ( 5 ) ;
88+ let _tp = common:: start_template_provider ( tp_addr. port ( ) , sv2_interval) . await ;
89+ let tp_pool_sniffer_identifier =
90+ "header_timestamp_value_assertion_in_new_extended_mining_job tp_pool sniffer" . to_string ( ) ;
91+ let tp_pool_sniffer = common:: start_sniffer (
92+ tp_pool_sniffer_identifier,
93+ tp_pool_sniffer_addr,
94+ tp_addr,
95+ false ,
96+ None ,
97+ )
98+ . await ;
99+ let _ = common:: start_pool ( Some ( pool_addr) , Some ( tp_pool_sniffer_addr) ) . await ;
100+ let pool_translator_sniffer_identifier =
101+ "header_timestamp_value_assertion_in_new_extended_mining_job pool_translator sniffer"
102+ . to_string ( ) ;
103+ let pool_translator_sniffer = common:: start_sniffer (
104+ pool_translator_sniffer_identifier,
105+ pool_translator_sniffer_addr,
106+ pool_addr,
107+ false ,
108+ None ,
109+ )
110+ . await ;
111+ let _tproxy_addr = common:: start_sv2_translator ( pool_translator_sniffer_addr) . await ;
112+ assert_common_message ! (
113+ & tp_pool_sniffer. next_message_from_upstream( ) ,
114+ SetupConnectionSuccess
115+ ) ;
116+ // Wait for a NewTemplate message from the Template Provider
117+ tp_pool_sniffer
118+ . wait_for_message_type ( MessageDirection :: ToDownstream , MESSAGE_TYPE_NEW_TEMPLATE )
119+ . await ;
120+ assert_tp_message ! ( & tp_pool_sniffer. next_message_from_upstream( ) , NewTemplate ) ;
121+ // Extract header timestamp from SetNewPrevHash message
122+ let header_timestamp_to_check = match tp_pool_sniffer. next_message_from_upstream ( ) {
123+ Some ( ( _, AnyMessage :: TemplateDistribution ( TemplateDistribution :: SetNewPrevHash ( msg) ) ) ) => {
124+ msg. header_timestamp
125+ }
126+ _ => panic ! ( "SetNewPrevHash not found!" ) ,
127+ } ;
128+ // Assertions of messages between Pool and Translator Proxy (these are not necessary for the
129+ // test itself, but they are used to pop from the sniffer's message queue)
130+ assert_common_message ! (
131+ & pool_translator_sniffer. next_message_from_upstream( ) ,
132+ SetupConnectionSuccess
133+ ) ;
134+ assert_mining_message ! (
135+ & pool_translator_sniffer. next_message_from_upstream( ) ,
136+ OpenExtendedMiningChannelSuccess
137+ ) ;
138+ assert_mining_message ! (
139+ & pool_translator_sniffer. next_message_from_upstream( ) ,
140+ NewExtendedMiningJob
141+ ) ;
142+ assert_mining_message ! (
143+ & pool_translator_sniffer. next_message_from_upstream( ) ,
144+ SetNewPrevHash
145+ ) ;
146+ // Wait for a second NewExtendedMiningJob message
147+ pool_translator_sniffer
148+ . wait_for_message_type (
149+ MessageDirection :: ToDownstream ,
150+ MESSAGE_TYPE_NEW_EXTENDED_MINING_JOB ,
151+ )
152+ . await ;
153+ // Extract min_ntime from the second NewExtendedMiningJob message
154+ let second_job_ntime = match pool_translator_sniffer. next_message_from_upstream ( ) {
155+ Some ( ( _, AnyMessage :: Mining ( Mining :: NewExtendedMiningJob ( job) ) ) ) => {
156+ job. min_ntime . into_inner ( )
157+ }
158+ _ => panic ! ( "Second NewExtendedMiningJob not found!" ) ,
159+ } ;
160+ // Assert that min_ntime matches header_timestamp
161+ assert_eq ! (
162+ second_job_ntime,
163+ Some ( header_timestamp_to_check) ,
164+ "The `minntime` field of the second NewExtendedMiningJob does not match the `header_timestamp`!"
165+ ) ;
166+ }
167+
67168#[ tokio:: test]
68169async fn test_sniffer_interrupter ( ) {
69170 let sniffer_addr = common:: get_available_address ( ) ;
70171 let tp_addr = common:: get_available_address ( ) ;
71172 let pool_addr = common:: get_available_address ( ) ;
72- let _tp = common:: start_template_provider ( tp_addr. port ( ) ) . await ;
173+ let _tp = common:: start_template_provider ( tp_addr. port ( ) , None ) . await ;
73174 use const_sv2:: MESSAGE_TYPE_SETUP_CONNECTION_SUCCESS ;
74175 let message =
75176 PoolMessages :: Common ( CommonMessages :: SetupConnectionError ( SetupConnectionError {
0 commit comments