@@ -22,14 +22,24 @@ use std::{
2222use stratum_apps:: {
2323 stratum_core:: {
2424 binary_sv2:: Str0255 ,
25+ channels_sv2:: client,
2526 common_messages_sv2:: { Protocol , SetupConnection } ,
26- mining_sv2:: { CloseChannel , OpenExtendedMiningChannel , OpenStandardMiningChannel } ,
27- parsers_sv2:: Mining ,
27+ job_declaration_sv2:: PushSolution ,
28+ mining_sv2:: {
29+ CloseChannel , OpenExtendedMiningChannel , OpenStandardMiningChannel ,
30+ SubmitSharesExtended ,
31+ } ,
32+ parsers_sv2:: { JobDeclaration , Mining } ,
2833 } ,
2934 utils:: types:: { ChannelId , DownstreamId , Hashrate , JobId } ,
3035} ;
36+ use tracing:: { debug, info} ;
3137
32- use crate :: { config:: ConfigJDCMode , error:: JDCError } ;
38+ use crate :: {
39+ channel_manager:: { downstream_message_handler:: RouteMessageTo , ChannelManagerData } ,
40+ config:: ConfigJDCMode ,
41+ error:: JDCError ,
42+ } ;
3343
3444/// Represents a message that can trigger shutdown of various system components.
3545#[ derive( Debug , Clone ) ]
@@ -303,3 +313,72 @@ impl From<(DownstreamId, ChannelId, JobId)> for DownstreamChannelJobId {
303313 }
304314 }
305315}
316+
317+ pub fn validate_share (
318+ mut upstream_message : SubmitSharesExtended < ' static > ,
319+ channel_manager_data : & mut ChannelManagerData ,
320+ messages : & mut Vec < RouteMessageTo > ,
321+ ) {
322+ let Some ( upstream_channel) = channel_manager_data. upstream_channel . as_mut ( ) else {
323+ return ;
324+ } ;
325+ let Some ( prev_hash) = channel_manager_data. last_new_prev_hash . as_ref ( ) else {
326+ return ;
327+ } ;
328+
329+ match upstream_channel. validate_share ( upstream_message. clone ( ) ) {
330+ Ok ( client:: share_accounting:: ShareValidationResult :: Valid ( share_hash) ) => {
331+ upstream_message. sequence_number = channel_manager_data
332+ . sequence_number_factory
333+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
334+
335+ info ! (
336+ "Flushed cached extended share: valid | ch={}, seq={}, hash={} ✅" ,
337+ upstream_message. channel_id, upstream_message. sequence_number, share_hash
338+ ) ;
339+
340+ messages. push ( Mining :: SubmitSharesExtended ( upstream_message. into_static ( ) ) . into ( ) ) ;
341+ }
342+
343+ Ok ( client:: share_accounting:: ShareValidationResult :: BlockFound ( share_hash) ) => {
344+ upstream_message. sequence_number = channel_manager_data
345+ . sequence_number_factory
346+ . fetch_add ( 1 , Ordering :: Relaxed ) ;
347+
348+ info ! ( "💰 Block Found (cached extended)!!! 💰 {share_hash}" ) ;
349+
350+ let mut channel_extranonce = upstream_channel. get_extranonce_prefix ( ) . to_vec ( ) ;
351+ channel_extranonce. extend_from_slice ( & upstream_message. extranonce . to_vec ( ) ) ;
352+
353+ let push_solution = PushSolution {
354+ extranonce : channel_extranonce. try_into ( ) . expect ( "extranonce" ) ,
355+ ntime : upstream_message. ntime ,
356+ nonce : upstream_message. nonce ,
357+ version : upstream_message. version ,
358+ nbits : prev_hash. n_bits ,
359+ prev_hash : prev_hash. prev_hash . clone ( ) ,
360+ } ;
361+
362+ messages. push ( JobDeclaration :: PushSolution ( push_solution) . into ( ) ) ;
363+ messages. push ( Mining :: SubmitSharesExtended ( upstream_message. into_static ( ) ) . into ( ) ) ;
364+ }
365+
366+ Err ( err) => {
367+ let code = match err {
368+ client:: share_accounting:: ShareValidationError :: Invalid => "invalid-share" ,
369+ client:: share_accounting:: ShareValidationError :: Stale => "stale-share" ,
370+ client:: share_accounting:: ShareValidationError :: InvalidJobId => "invalid-job-id" ,
371+ client:: share_accounting:: ShareValidationError :: DoesNotMeetTarget => {
372+ "difficulty-too-low"
373+ }
374+ client:: share_accounting:: ShareValidationError :: DuplicateShare => "duplicate-share" ,
375+ _ => unreachable ! ( ) ,
376+ } ;
377+
378+ debug ! (
379+ "❌ Cached extended share rejected: ch={}, seq={}, error={}" ,
380+ upstream_message. channel_id, upstream_message. sequence_number, code
381+ ) ;
382+ }
383+ }
384+ }
0 commit comments