@@ -40,6 +40,7 @@ use tokio::{
40
40
sync:: { broadcast, mpsc} ,
41
41
} ;
42
42
use tracing:: { debug, error, info, warn} ;
43
+ use v1:: IsServer ;
43
44
44
45
/// SV1 server that handles connections from SV1 miners.
45
46
///
@@ -281,11 +282,21 @@ impl Sv1Server {
281
282
d. vardiff. insert( downstream_id, vardiff) ;
282
283
}
283
284
} ) ;
284
- info!( "Downstream {} registered successfully" , downstream_id) ;
285
+ info!( "Downstream {} registered successfully (channel will be opened after first message) " , downstream_id) ;
285
286
286
- self
287
- . open_extended_mining_channel( downstream. clone( ) )
288
- . await ?;
287
+ // Start downstream tasks immediately, but defer channel opening until first message
288
+ let status_sender = StatusSender :: Downstream {
289
+ downstream_id,
290
+ tx: status_sender. clone( ) ,
291
+ } ;
292
+
293
+ Downstream :: run_downstream_tasks(
294
+ downstream,
295
+ notify_shutdown. clone( ) ,
296
+ shutdown_complete_tx. clone( ) ,
297
+ status_sender,
298
+ task_manager. clone( ) ,
299
+ ) ;
289
300
}
290
301
Err ( e) => {
291
302
warn!( "Failed to accept new connection: {:?}" , e) ;
@@ -303,10 +314,6 @@ impl Sv1Server {
303
314
res = Self :: handle_upstream_message(
304
315
Arc :: clone( & self ) ,
305
316
first_target. clone( ) ,
306
- notify_shutdown. clone( ) ,
307
- shutdown_complete_tx_main_clone. clone( ) ,
308
- status_sender. clone( ) ,
309
- task_manager. clone( )
310
317
) => {
311
318
if let Err ( e) = res {
312
319
handle_error( & sv1_status_sender, e) . await ;
@@ -340,8 +347,21 @@ impl Sv1Server {
340
347
. await
341
348
. map_err ( TproxyError :: ChannelErrorReceiver ) ?;
342
349
343
- let DownstreamMessages :: SubmitShares ( message) = downstream_message;
350
+ match downstream_message {
351
+ DownstreamMessages :: SubmitShares ( message) => {
352
+ return self . handle_submit_shares ( message) . await ;
353
+ }
354
+ DownstreamMessages :: OpenChannel ( downstream_id) => {
355
+ return self . handle_open_channel_request ( downstream_id) . await ;
356
+ }
357
+ }
358
+ }
344
359
360
+ /// Handles share submission messages from downstream.
361
+ async fn handle_submit_shares (
362
+ self : & Arc < Self > ,
363
+ message : crate :: sv1:: downstream:: SubmitShareWithChannelId ,
364
+ ) -> Result < ( ) , TproxyError > {
345
365
// Increment vardiff counter for this downstream (only if vardiff is enabled)
346
366
if self . config . downstream_difficulty_config . enable_vardiff {
347
367
self . sv1_server_data . safe_lock ( |v| {
@@ -382,6 +402,28 @@ impl Sv1Server {
382
402
Ok ( ( ) )
383
403
}
384
404
405
+ /// Handles channel opening requests from downstream when they send their first message.
406
+ async fn handle_open_channel_request (
407
+ self : & Arc < Self > ,
408
+ downstream_id : u32 ,
409
+ ) -> Result < ( ) , TproxyError > {
410
+ info ! ( "SV1 Server: Opening extended mining channel for downstream {} after receiving first message" , downstream_id) ;
411
+
412
+ let downstreams = self
413
+ . sv1_server_data
414
+ . super_safe_lock ( |v| v. downstreams . clone ( ) ) ;
415
+ if let Some ( downstream) = Self :: get_downstream ( downstream_id, downstreams) {
416
+ self . open_extended_mining_channel ( downstream) . await ?;
417
+ } else {
418
+ error ! (
419
+ "Downstream {} not found when trying to open channel" ,
420
+ downstream_id
421
+ ) ;
422
+ }
423
+
424
+ Ok ( ( ) )
425
+ }
426
+
385
427
/// Handles messages received from the upstream SV2 server via the channel manager.
386
428
///
387
429
/// This method processes various SV2 messages including:
@@ -403,10 +445,6 @@ impl Sv1Server {
403
445
pub async fn handle_upstream_message (
404
446
self : Arc < Self > ,
405
447
first_target : Target ,
406
- notify_shutdown : broadcast:: Sender < ShutdownMessage > ,
407
- shutdown_complete_tx : mpsc:: Sender < ( ) > ,
408
- status_sender : Sender < Status > ,
409
- task_manager : Arc < TaskManager > ,
410
448
) -> Result < ( ) , TproxyError > {
411
449
let message = self
412
450
. sv1_server_channel_state
@@ -435,18 +473,42 @@ impl Sv1Server {
435
473
d. set_upstream_target ( initial_target. clone ( ) ) ;
436
474
} ) ?;
437
475
438
- let status_sender = StatusSender :: Downstream {
439
- downstream_id,
440
- tx : status_sender. clone ( ) ,
441
- } ;
442
-
443
- Downstream :: run_downstream_tasks (
444
- downstream,
445
- notify_shutdown,
446
- shutdown_complete_tx,
447
- status_sender,
448
- task_manager,
449
- ) ;
476
+ // Process all queued messages now that channel is established
477
+ if let Ok ( queued_messages) = downstream. downstream_data . safe_lock ( |d| {
478
+ let messages = d. queued_sv1_handshake_messages . clone ( ) ;
479
+ d. queued_sv1_handshake_messages . clear ( ) ;
480
+ messages
481
+ } ) {
482
+ if !queued_messages. is_empty ( ) {
483
+ info ! (
484
+ "Processing {} queued Sv1 messages for downstream {}" ,
485
+ queued_messages. len( ) ,
486
+ downstream_id
487
+ ) ;
488
+
489
+ // Set flag to indicate we're processing queued responses
490
+ downstream. downstream_data . super_safe_lock ( |data| {
491
+ data. processing_queued_sv1_handshake_responses
492
+ . store ( true , std:: sync:: atomic:: Ordering :: SeqCst ) ;
493
+ } ) ;
494
+
495
+ for message in queued_messages {
496
+ if let Ok ( Some ( response_msg) ) = downstream
497
+ . downstream_data
498
+ . super_safe_lock ( |data| data. handle_message ( message) )
499
+ {
500
+ self . sv1_server_channel_state
501
+ . sv1_server_to_downstream_sender
502
+ . send ( (
503
+ m. channel_id ,
504
+ Some ( downstream_id) ,
505
+ response_msg. into ( ) ,
506
+ ) )
507
+ . map_err ( |_| TproxyError :: ChannelErrorSender ) ?;
508
+ }
509
+ }
510
+ }
511
+ }
450
512
451
513
let set_difficulty = build_sv1_set_difficulty_from_sv2_target ( first_target)
452
514
. map_err ( |_| {
0 commit comments