diff --git a/sv2/channels-sv2/src/client/extended.rs b/sv2/channels-sv2/src/client/extended.rs index bee34ba35c..cd3c62c2a5 100644 --- a/sv2/channels-sv2/src/client/extended.rs +++ b/sv2/channels-sv2/src/client/extended.rs @@ -223,6 +223,12 @@ impl<'a> ExtendedChannel<'a> { .on_share_acknowledgement(new_submits_accepted_count, new_shares_sum); } + /// Updates share accounting based on a [`SubmitSharesError`] message from the upstream + /// server. Delegates to [`ShareAccounting::on_share_rejection`]. + pub fn on_share_rejection(&mut self) { + self.share_accounting.on_share_rejection(); + } + /// Handles a [`NewExtendedMiningJob`] message received from upstream. /// /// The message could be either directed at this channel, or at a group channel it belongs to. diff --git a/sv2/channels-sv2/src/client/share_accounting.rs b/sv2/channels-sv2/src/client/share_accounting.rs index 5948540718..ed762eefee 100644 --- a/sv2/channels-sv2/src/client/share_accounting.rs +++ b/sv2/channels-sv2/src/client/share_accounting.rs @@ -45,12 +45,14 @@ pub enum ShareValidationError { /// Used only on Mining Clients. Share accounting is split into two phases: /// /// **Validation phase** (updated by [`validate_share`] via [`track_validated_share`]): +/// - total validated shares (shares that passed local validation) /// - hashes of seen shares (for duplicate detection) /// - last received share's sequence number /// - highest difficulty seen in validated shares /// /// **Acceptance phase** (updated by the application layer via [`on_share_acknowledgement`]): -/// - total accepted shares (confirmed by upstream [`SubmitSharesSuccess`]) +/// - total acknowledged shares (confirmed by upstream [`SubmitSharesSuccess`]) +/// - total rejected shares (reported by upstream [`SubmitSharesError`]) /// - cumulative work from accepted shares /// - number of blocks found /// @@ -58,10 +60,13 @@ pub enum ShareValidationError { /// [`track_validated_share`]: ShareAccounting::track_validated_share /// [`on_share_acknowledgement`]: ShareAccounting::on_share_acknowledgement /// [`SubmitSharesSuccess`]: mining_sv2::SubmitSharesSuccess +/// [`SubmitSharesError`]: mining_sv2::SubmitSharesError #[derive(Clone, Debug)] pub struct ShareAccounting { last_share_sequence_number: u32, - shares_accepted: u32, + acknowledged_shares: u32, + validated_shares: u32, + rejected_shares: u32, share_work_sum: f64, seen_shares: HashSet, best_diff: f64, @@ -79,7 +84,9 @@ impl ShareAccounting { pub fn new() -> Self { Self { last_share_sequence_number: 0, - shares_accepted: 0, + acknowledged_shares: 0, + validated_shares: 0, + rejected_shares: 0, share_work_sum: 0.0, seen_shares: HashSet::new(), best_diff: 0.0, @@ -99,10 +106,18 @@ impl ShareAccounting { new_submits_accepted_count: u32, new_shares_sum: f64, ) { - self.shares_accepted += new_submits_accepted_count; + self.acknowledged_shares += new_submits_accepted_count; self.share_work_sum += new_shares_sum; } + /// Updates rejection accounting based on a [`SubmitSharesError`] message from the upstream + /// server. + /// + /// One call corresponds to one rejected share. + pub fn on_share_rejection(&mut self) { + self.rejected_shares += 1; + } + /// Records a share that passed local validation. /// /// Adds the hash to the seen set for duplicate detection and updates the last sequence @@ -111,6 +126,7 @@ impl ShareAccounting { /// called when the upstream server confirms via [`SubmitSharesSuccess`]. pub fn track_validated_share(&mut self, share_sequence_number: u32, share_hash: Hash) { self.last_share_sequence_number = share_sequence_number; + self.validated_shares += 1; self.seen_shares.insert(share_hash); } @@ -127,9 +143,19 @@ impl ShareAccounting { self.last_share_sequence_number } - /// Returns the total number of shares accepted. - pub fn get_shares_accepted(&self) -> u32 { - self.shares_accepted + /// Returns the total number of shares acknowledged by upstream. + pub fn get_acknowledged_shares(&self) -> u32 { + self.acknowledged_shares + } + + /// Returns the total number of locally validated shares. + pub fn get_validated_shares(&self) -> u32 { + self.validated_shares + } + + /// Returns the total number of shares rejected by upstream. + pub fn get_rejected_shares(&self) -> u32 { + self.rejected_shares } /// Returns the cumulative work of all accepted shares. diff --git a/sv2/channels-sv2/src/client/standard.rs b/sv2/channels-sv2/src/client/standard.rs index 8bce59d330..7e403ec746 100644 --- a/sv2/channels-sv2/src/client/standard.rs +++ b/sv2/channels-sv2/src/client/standard.rs @@ -179,6 +179,12 @@ impl<'a> StandardChannel<'a> { .on_share_acknowledgement(new_submits_accepted_count, new_shares_sum); } + /// Updates share accounting based on a [`SubmitSharesError`] message from the upstream + /// server. Delegates to [`ShareAccounting::on_share_rejection`]. + pub fn on_share_rejection(&mut self) { + self.share_accounting.on_share_rejection(); + } + /// Handles a new group channel job by converting it into a standard job /// and activating it in this channel's context. ///