1
1
mod common;
2
2
3
- use std:: convert:: TryInto ;
4
-
5
3
use common:: { InterceptMessage , MessageDirection } ;
6
4
use 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 ,
8
7
} ;
9
8
use roles_logic_sv2:: {
10
9
common_messages_sv2:: { Protocol , SetupConnection , SetupConnectionError } ,
11
- parsers:: { CommonMessages , PoolMessages , TemplateDistribution } ,
10
+ parsers:: { AnyMessage , CommonMessages , Mining , PoolMessages , TemplateDistribution } ,
12
11
} ;
12
+ use std:: convert:: TryInto ;
13
13
14
14
// This test starts a Template Provider and a Pool, and checks if they exchange the correct
15
15
// messages upon connection.
@@ -20,7 +20,7 @@ async fn success_pool_template_provider_connection() {
20
20
let sniffer_addr = common:: get_available_address ( ) ;
21
21
let tp_addr = common:: get_available_address ( ) ;
22
22
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 ;
24
24
let sniffer_identifier =
25
25
"success_pool_template_provider_connection tp_pool sniffer" . to_string ( ) ;
26
26
let sniffer_check_on_drop = true ;
@@ -64,12 +64,113 @@ async fn success_pool_template_provider_connection() {
64
64
assert_tp_message ! ( sniffer. next_message_from_upstream( ) , SetNewPrevHash ) ;
65
65
}
66
66
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
+
67
168
#[ tokio:: test]
68
169
async fn test_sniffer_interrupter ( ) {
69
170
let sniffer_addr = common:: get_available_address ( ) ;
70
171
let tp_addr = common:: get_available_address ( ) ;
71
172
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 ;
73
174
use const_sv2:: MESSAGE_TYPE_SETUP_CONNECTION_SUCCESS ;
74
175
let message =
75
176
PoolMessages :: Common ( CommonMessages :: SetupConnectionError ( SetupConnectionError {
0 commit comments