From 76c20cc2ea516c45231b5aee542470c165ab666f Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 20 Jul 2025 18:15:39 +0530 Subject: [PATCH 1/8] add new handlers_sv2 crate with async trait feature --- protocols/v2/handlers-sv2/Cargo.toml | 21 + protocols/v2/handlers-sv2/src/common.rs | 162 ++++++ protocols/v2/handlers-sv2/src/error.rs | 16 + .../v2/handlers-sv2/src/job_declaration.rs | 238 ++++++++ protocols/v2/handlers-sv2/src/lib.rs | 30 + protocols/v2/handlers-sv2/src/mining.rs | 547 ++++++++++++++++++ .../handlers-sv2/src/template_distribution.rs | 213 +++++++ 7 files changed, 1227 insertions(+) create mode 100644 protocols/v2/handlers-sv2/Cargo.toml create mode 100644 protocols/v2/handlers-sv2/src/common.rs create mode 100644 protocols/v2/handlers-sv2/src/error.rs create mode 100644 protocols/v2/handlers-sv2/src/job_declaration.rs create mode 100644 protocols/v2/handlers-sv2/src/lib.rs create mode 100644 protocols/v2/handlers-sv2/src/mining.rs create mode 100644 protocols/v2/handlers-sv2/src/template_distribution.rs diff --git a/protocols/v2/handlers-sv2/Cargo.toml b/protocols/v2/handlers-sv2/Cargo.toml new file mode 100644 index 0000000000..492f8bcc69 --- /dev/null +++ b/protocols/v2/handlers-sv2/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "handlers_sv2" +version = "0.1.0" +authors = ["The Stratum V2 Developers"] +edition = "2018" +readme = "README.md" +description = "Sv2 Message handlers" +documentation = "https://docs.rs/handlers_sv2" +license = "MIT OR Apache-2.0" +repository = "https://github.com/stratum-mining/stratum" +homepage = "https://stratumprotocol.org" +keywords = ["stratum", "mining", "bitcoin", "protocol"] + +[dependencies] +trait-variant = "0.1.2" +parsers_sv2 = { path = "../parsers-sv2", version = "^0.1.0"} +binary_sv2 = { path = "../binary-sv2", version = "^3.0.0" } +common_messages_sv2 = { path = "../subprotocols/common-messages", version = "^5.0.0" } +mining_sv2 = { path = "../subprotocols/mining", version = "^4.0.0" } +template_distribution_sv2 = { path = "../subprotocols/template-distribution", version = "^3.0.0" } +job_declaration_sv2 = { path = "../subprotocols/job-declaration", version = "^4.0.0" } diff --git a/protocols/v2/handlers-sv2/src/common.rs b/protocols/v2/handlers-sv2/src/common.rs new file mode 100644 index 0000000000..b8987b7d7d --- /dev/null +++ b/protocols/v2/handlers-sv2/src/common.rs @@ -0,0 +1,162 @@ +use crate::error::HandlerError as Error; +use common_messages_sv2::{ + ChannelEndpointChanged, Reconnect, SetupConnectionError, SetupConnectionSuccess, *, +}; +use core::convert::TryInto; +use parsers_sv2::CommonMessages; + +pub trait ParseCommonMessagesFromUpstreamSync { + fn handle_common_message(&mut self, message_type: u8, payload: &mut [u8]) -> Result<(), Error> { + let parsed: CommonMessages<'_> = (message_type, payload).try_into()?; + self.dispatch_common_message(parsed) + } + + fn dispatch_common_message(&mut self, message: CommonMessages<'_>) -> Result<(), Error> { + match message { + CommonMessages::SetupConnectionSuccess(msg) => { + self.handle_setup_connection_success(msg) + } + CommonMessages::SetupConnectionError(msg) => self.handle_setup_connection_error(msg), + CommonMessages::ChannelEndpointChanged(msg) => { + self.handle_channel_endpoint_changed(msg) + } + CommonMessages::Reconnect(msg) => self.handle_reconnect(msg), + + CommonMessages::SetupConnection(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_SETUP_CONNECTION)) + } + } + } + + fn handle_setup_connection_success(&mut self, msg: SetupConnectionSuccess) + -> Result<(), Error>; + + fn handle_setup_connection_error(&mut self, msg: SetupConnectionError) -> Result<(), Error>; + + fn handle_channel_endpoint_changed(&mut self, msg: ChannelEndpointChanged) + -> Result<(), Error>; + + fn handle_reconnect(&mut self, msg: Reconnect) -> Result<(), Error>; +} + +#[trait_variant::make(Send)] +pub trait ParseCommonMessagesFromUpstreamAsync { + async fn handle_common_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: Result, _> = (message_type, payload).try_into(); + async move { + let parsed = parsed?; + self.dispatch_common_message(parsed).await + } + } + + async fn dispatch_common_message(&mut self, message: CommonMessages<'_>) -> Result<(), Error> { + async move { + match message { + CommonMessages::SetupConnectionSuccess(msg) => { + self.handle_setup_connection_success(msg).await + } + CommonMessages::SetupConnectionError(msg) => { + self.handle_setup_connection_error(msg).await + } + CommonMessages::ChannelEndpointChanged(msg) => { + self.handle_channel_endpoint_changed(msg).await + } + CommonMessages::Reconnect(msg) => self.handle_reconnect(msg).await, + + CommonMessages::SetupConnection(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_SETUP_CONNECTION)) + } + } + } + } + + async fn handle_setup_connection_success( + &mut self, + msg: SetupConnectionSuccess, + ) -> Result<(), Error>; + + async fn handle_setup_connection_error( + &mut self, + msg: SetupConnectionError, + ) -> Result<(), Error>; + + async fn handle_channel_endpoint_changed( + &mut self, + msg: ChannelEndpointChanged, + ) -> Result<(), Error>; + + async fn handle_reconnect(&mut self, msg: Reconnect) -> Result<(), Error>; +} + +pub trait ParseCommonMessagesFromDownstreamSync +where + Self: Sized, +{ + fn handle_common_message(&mut self, message_type: u8, payload: &mut [u8]) -> Result<(), Error> { + let parsed: CommonMessages<'_> = (message_type, payload).try_into()?; + self.dispatch_common_message(parsed) + } + + fn dispatch_common_message(&mut self, message: CommonMessages<'_>) -> Result<(), Error> { + match message { + CommonMessages::SetupConnectionSuccess(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SETUP_CONNECTION_SUCCESS, + )), + CommonMessages::SetupConnectionError(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SETUP_CONNECTION_ERROR, + )), + CommonMessages::ChannelEndpointChanged(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_CHANNEL_ENDPOINT_CHANGED, + )), + CommonMessages::Reconnect(_) => Err(Error::UnexpectedMessage(MESSAGE_TYPE_RECONNECT)), + + CommonMessages::SetupConnection(msg) => self.handle_setup_connection(msg), + } + } + + fn handle_setup_connection(&mut self, msg: SetupConnection) -> Result<(), Error>; +} + +#[trait_variant::make(Send)] +pub trait ParseCommonMessagesFromDownstreamAsync +where + Self: Sized, +{ + async fn handle_common_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: Result, _> = (message_type, payload).try_into(); + async move { + let parsed = parsed?; + self.dispatch_common_message(parsed).await + } + } + + async fn dispatch_common_message(&mut self, message: CommonMessages<'_>) -> Result<(), Error> { + async move { + match message { + CommonMessages::SetupConnectionSuccess(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SETUP_CONNECTION_SUCCESS, + )), + CommonMessages::SetupConnectionError(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SETUP_CONNECTION_ERROR, + )), + CommonMessages::ChannelEndpointChanged(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_CHANNEL_ENDPOINT_CHANGED, + )), + CommonMessages::Reconnect(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_RECONNECT)) + } + CommonMessages::SetupConnection(msg) => self.handle_setup_connection(msg).await, + } + } + } + + async fn handle_setup_connection(&mut self, msg: SetupConnection) -> Result<(), Error>; +} diff --git a/protocols/v2/handlers-sv2/src/error.rs b/protocols/v2/handlers-sv2/src/error.rs new file mode 100644 index 0000000000..c3cad68f16 --- /dev/null +++ b/protocols/v2/handlers-sv2/src/error.rs @@ -0,0 +1,16 @@ +use parsers_sv2::ParserError; + +#[derive(Debug)] +pub enum HandlerError { + UnexpectedMessage(u8), + ParserError(ParserError), + OpenStandardMiningChannelError, + OpenExtendedMiningChannelError, + ChannelErrorSender, +} + +impl From for HandlerError { + fn from(value: ParserError) -> HandlerError { + HandlerError::ParserError(value) + } +} diff --git a/protocols/v2/handlers-sv2/src/job_declaration.rs b/protocols/v2/handlers-sv2/src/job_declaration.rs new file mode 100644 index 0000000000..6c7d3439b8 --- /dev/null +++ b/protocols/v2/handlers-sv2/src/job_declaration.rs @@ -0,0 +1,238 @@ +use crate::error::HandlerError as Error; +use core::convert::TryInto; +use job_declaration_sv2::{ + MESSAGE_TYPE_ALLOCATE_MINING_JOB_TOKEN, MESSAGE_TYPE_ALLOCATE_MINING_JOB_TOKEN_SUCCESS, + MESSAGE_TYPE_DECLARE_MINING_JOB, MESSAGE_TYPE_DECLARE_MINING_JOB_ERROR, + MESSAGE_TYPE_DECLARE_MINING_JOB_SUCCESS, MESSAGE_TYPE_PROVIDE_MISSING_TRANSACTIONS, + MESSAGE_TYPE_PROVIDE_MISSING_TRANSACTIONS_SUCCESS, MESSAGE_TYPE_PUSH_SOLUTION, *, +}; +use parsers_sv2::JobDeclaration; + +pub trait ParseJobDeclarationMessagesFromUpstreamSync { + fn handle_job_declaration_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: JobDeclaration<'_> = (message_type, payload).try_into()?; + self.dispatch_job_declaration(parsed) + } + + fn dispatch_job_declaration(&mut self, message: JobDeclaration<'_>) -> Result<(), Error> { + match message { + JobDeclaration::AllocateMiningJobTokenSuccess(msg) => { + self.handle_allocate_mining_job_token_success(msg) + } + JobDeclaration::DeclareMiningJobSuccess(msg) => { + self.handle_declare_mining_job_success(msg) + } + JobDeclaration::DeclareMiningJobError(msg) => self.handle_declare_mining_job_error(msg), + JobDeclaration::ProvideMissingTransactions(msg) => { + self.handle_provide_missing_transactions(msg) + } + JobDeclaration::AllocateMiningJobToken(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_ALLOCATE_MINING_JOB_TOKEN, + )), + JobDeclaration::DeclareMiningJob(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_DECLARE_MINING_JOB)) + } + JobDeclaration::ProvideMissingTransactionsSuccess(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_PROVIDE_MISSING_TRANSACTIONS_SUCCESS, + )), + JobDeclaration::PushSolution(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_PUSH_SOLUTION)) + } + } + } + + fn handle_allocate_mining_job_token_success( + &mut self, + msg: AllocateMiningJobTokenSuccess, + ) -> Result<(), Error>; + + fn handle_declare_mining_job_success( + &mut self, + msg: DeclareMiningJobSuccess, + ) -> Result<(), Error>; + + fn handle_declare_mining_job_error(&mut self, msg: DeclareMiningJobError) -> Result<(), Error>; + + fn handle_provide_missing_transactions( + &mut self, + msg: ProvideMissingTransactions, + ) -> Result<(), Error>; +} + +#[trait_variant::make(Send)] +pub trait ParseJobDeclarationMessagesFromUpstreamAsync { + async fn handle_job_declaration_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: Result, _> = (message_type, payload).try_into(); + async move { + let parsed = parsed?; + self.dispatch_job_declaration(parsed).await + } + } + + async fn dispatch_job_declaration(&mut self, message: JobDeclaration<'_>) -> Result<(), Error> { + async move { + match message { + JobDeclaration::AllocateMiningJobTokenSuccess(msg) => { + self.handle_allocate_mining_job_token_success(msg).await + } + JobDeclaration::DeclareMiningJobSuccess(msg) => { + self.handle_declare_mining_job_success(msg).await + } + JobDeclaration::DeclareMiningJobError(msg) => { + self.handle_declare_mining_job_error(msg).await + } + JobDeclaration::ProvideMissingTransactions(msg) => { + self.handle_provide_missing_transactions(msg).await + } + JobDeclaration::AllocateMiningJobToken(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_ALLOCATE_MINING_JOB_TOKEN, + )), + JobDeclaration::DeclareMiningJob(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_DECLARE_MINING_JOB)) + } + JobDeclaration::ProvideMissingTransactionsSuccess(_) => Err( + Error::UnexpectedMessage(MESSAGE_TYPE_PROVIDE_MISSING_TRANSACTIONS_SUCCESS), + ), + JobDeclaration::PushSolution(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_PUSH_SOLUTION)) + } + } + } + } + + async fn handle_allocate_mining_job_token_success( + &mut self, + msg: AllocateMiningJobTokenSuccess, + ) -> Result<(), Error>; + + async fn handle_declare_mining_job_success( + &mut self, + msg: DeclareMiningJobSuccess, + ) -> Result<(), Error>; + + async fn handle_declare_mining_job_error( + &mut self, + msg: DeclareMiningJobError, + ) -> Result<(), Error>; + + async fn handle_provide_missing_transactions( + &mut self, + msg: ProvideMissingTransactions, + ) -> Result<(), Error>; +} + +pub trait ParseJobDeclarationMessagesFromDownstreamSync { + fn handle_job_declaration_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: JobDeclaration<'_> = (message_type, payload).try_into()?; + self.dispatch_job_declaration(parsed) + } + + fn dispatch_job_declaration(&mut self, message: JobDeclaration<'_>) -> Result<(), Error> { + match message { + JobDeclaration::AllocateMiningJobToken(msg) => { + self.handle_allocate_mining_job_token(msg) + } + JobDeclaration::DeclareMiningJob(msg) => self.handle_declare_mining_job(msg), + JobDeclaration::ProvideMissingTransactionsSuccess(msg) => { + self.handle_provide_missing_transactions_success(msg) + } + JobDeclaration::PushSolution(msg) => self.handle_push_solution(msg), + + JobDeclaration::AllocateMiningJobTokenSuccess(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_ALLOCATE_MINING_JOB_TOKEN_SUCCESS, + )), + JobDeclaration::DeclareMiningJobSuccess(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_DECLARE_MINING_JOB_SUCCESS, + )), + JobDeclaration::DeclareMiningJobError(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_DECLARE_MINING_JOB_ERROR, + )), + JobDeclaration::ProvideMissingTransactions(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_PROVIDE_MISSING_TRANSACTIONS, + )), + } + } + + fn handle_allocate_mining_job_token( + &mut self, + msg: AllocateMiningJobToken, + ) -> Result<(), Error>; + + fn handle_declare_mining_job(&mut self, msg: DeclareMiningJob) -> Result<(), Error>; + + fn handle_provide_missing_transactions_success( + &mut self, + msg: ProvideMissingTransactionsSuccess, + ) -> Result<(), Error>; + + fn handle_push_solution(&mut self, msg: PushSolution) -> Result<(), Error>; +} + +#[trait_variant::make(Send)] +pub trait ParseJobDeclarationMessagesFromDownstreamAsync { + async fn handle_job_declaration_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: Result, _> = (message_type, payload).try_into(); + async move { + let parsed = parsed?; + self.dispatch_job_declaration(parsed).await + } + } + + async fn dispatch_job_declaration(&mut self, message: JobDeclaration<'_>) -> Result<(), Error> { + async move { + match message { + JobDeclaration::AllocateMiningJobToken(msg) => { + self.handle_allocate_mining_job_token(msg).await + } + JobDeclaration::DeclareMiningJob(msg) => self.handle_declare_mining_job(msg).await, + JobDeclaration::ProvideMissingTransactionsSuccess(msg) => { + self.handle_provide_missing_transactions_success(msg).await + } + JobDeclaration::PushSolution(msg) => self.handle_push_solution(msg).await, + + JobDeclaration::AllocateMiningJobTokenSuccess(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_ALLOCATE_MINING_JOB_TOKEN_SUCCESS, + )), + JobDeclaration::DeclareMiningJobSuccess(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_DECLARE_MINING_JOB_SUCCESS, + )), + JobDeclaration::DeclareMiningJobError(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_DECLARE_MINING_JOB_ERROR, + )), + JobDeclaration::ProvideMissingTransactions(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_PROVIDE_MISSING_TRANSACTIONS, + )), + } + } + } + + async fn handle_allocate_mining_job_token( + &mut self, + msg: AllocateMiningJobToken, + ) -> Result<(), Error>; + + async fn handle_declare_mining_job(&mut self, msg: DeclareMiningJob) -> Result<(), Error>; + + async fn handle_provide_missing_transactions_success( + &mut self, + msg: ProvideMissingTransactionsSuccess, + ) -> Result<(), Error>; + + async fn handle_push_solution(&mut self, msg: PushSolution) -> Result<(), Error>; +} diff --git a/protocols/v2/handlers-sv2/src/lib.rs b/protocols/v2/handlers-sv2/src/lib.rs new file mode 100644 index 0000000000..61074875b6 --- /dev/null +++ b/protocols/v2/handlers-sv2/src/lib.rs @@ -0,0 +1,30 @@ +mod common; +mod error; +mod job_declaration; +mod mining; +mod template_distribution; + +pub use error::HandlerError; + +pub use common::{ + ParseCommonMessagesFromDownstreamAsync, ParseCommonMessagesFromDownstreamSync, + ParseCommonMessagesFromUpstreamAsync, ParseCommonMessagesFromUpstreamSync, +}; + +pub use mining::{ + ParseMiningMessagesFromDownstreamAsync, ParseMiningMessagesFromDownstreamSync, + ParseMiningMessagesFromUpstreamAsync, ParseMiningMessagesFromUpstreamSync, + SupportedChannelTypes, +}; + +pub use template_distribution::{ + ParseTemplateDistributionMessagesFromClientAsync, + ParseTemplateDistributionMessagesFromClientSync, + ParseTemplateDistributionMessagesFromServerAsync, + ParseTemplateDistributionMessagesFromServerSync, +}; + +pub use job_declaration::{ + ParseJobDeclarationMessagesFromDownstreamAsync, ParseJobDeclarationMessagesFromDownstreamSync, + ParseJobDeclarationMessagesFromUpstreamAsync, ParseJobDeclarationMessagesFromUpstreamSync, +}; diff --git a/protocols/v2/handlers-sv2/src/mining.rs b/protocols/v2/handlers-sv2/src/mining.rs new file mode 100644 index 0000000000..83851ff475 --- /dev/null +++ b/protocols/v2/handlers-sv2/src/mining.rs @@ -0,0 +1,547 @@ +use crate::error::HandlerError as Error; +use binary_sv2::Str0255; +use mining_sv2::{ + CloseChannel, NewExtendedMiningJob, NewMiningJob, OpenExtendedMiningChannel, + OpenExtendedMiningChannelSuccess, OpenMiningChannelError, OpenStandardMiningChannel, + OpenStandardMiningChannelSuccess, SetCustomMiningJob, SetCustomMiningJobError, + SetCustomMiningJobSuccess, SetExtranoncePrefix, SetGroupChannel, SetNewPrevHash, SetTarget, + SubmitSharesError, SubmitSharesExtended, SubmitSharesStandard, SubmitSharesSuccess, + UpdateChannel, UpdateChannelError, +}; +use parsers_sv2::Mining; +use std::convert::TryInto; + +use mining_sv2::*; +use std::fmt::Debug as D; + +#[derive(PartialEq, Eq)] +pub enum SupportedChannelTypes { + Standard, + Extended, + Group, + GroupAndExtended, +} + +pub trait ParseMiningMessagesFromDownstreamSync +where + Self: Sized + D, +{ + fn get_channel_type(&self) -> SupportedChannelTypes; + fn is_work_selection_enabled(&self) -> bool; + + fn is_downstream_authorized(&self, user_identity: &Str0255) -> Result; + + fn handle_mining_message(&mut self, message_type: u8, payload: &mut [u8]) -> Result<(), Error> { + let parsed: Mining = (message_type, payload).try_into()?; + self.dispatch_mining_message(parsed) + } + + fn dispatch_mining_message(&mut self, message: Mining) -> Result<(), Error> { + let (channel_type, work_selection) = + (self.get_channel_type(), self.is_work_selection_enabled()); + + use Mining::*; + match message { + OpenStandardMiningChannel(m) => { + if !self.is_downstream_authorized(&m.user_identity)? { + // Add correct error type + return Err(Error::OpenStandardMiningChannelError); + } + + match channel_type { + SupportedChannelTypes::Standard + | SupportedChannelTypes::Group + | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_standard_mining_channel(m) + } + SupportedChannelTypes::Extended => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_STANDARD_MINING_CHANNEL, + )), + } + } + OpenExtendedMiningChannel(m) => { + if !self.is_downstream_authorized(&m.user_identity)? { + // Add correct Error type + return Err(Error::OpenExtendedMiningChannelError); + } + + match channel_type { + SupportedChannelTypes::Extended | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_extended_mining_channel(m) + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL, + )), + } + } + UpdateChannel(m) => self.handle_update_channel(m), + + SubmitSharesStandard(m) => match channel_type { + SupportedChannelTypes::Standard + | SupportedChannelTypes::Group + | SupportedChannelTypes::GroupAndExtended => self.handle_submit_shares_standard(m), + SupportedChannelTypes::Extended => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SUBMIT_SHARES_STANDARD, + )), + }, + + SubmitSharesExtended(m) => match channel_type { + SupportedChannelTypes::Extended | SupportedChannelTypes::GroupAndExtended => { + self.handle_submit_shares_extended(m) + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SUBMIT_SHARES_EXTENDED, + )), + }, + + SetCustomMiningJob(m) => match (channel_type, work_selection) { + (SupportedChannelTypes::Extended, true) + | (SupportedChannelTypes::GroupAndExtended, true) => { + self.handle_set_custom_mining_job(m) + } + _ => Err(Error::UnexpectedMessage(MESSAGE_TYPE_SET_CUSTOM_MINING_JOB)), + }, + + _ => Err(Error::UnexpectedMessage(0)), + } + } + + fn handle_open_standard_mining_channel( + &mut self, + msg: OpenStandardMiningChannel, + ) -> Result<(), Error>; + + fn handle_open_extended_mining_channel( + &mut self, + msg: OpenExtendedMiningChannel, + ) -> Result<(), Error>; + + fn handle_update_channel(&mut self, msg: UpdateChannel) -> Result<(), Error>; + + fn handle_submit_shares_standard(&mut self, msg: SubmitSharesStandard) -> Result<(), Error>; + + fn handle_submit_shares_extended(&mut self, msg: SubmitSharesExtended) -> Result<(), Error>; + + fn handle_set_custom_mining_job(&mut self, msg: SetCustomMiningJob) -> Result<(), Error>; +} + +#[trait_variant::make(Send)] +pub trait ParseMiningMessagesFromDownstreamAsync +where + Self: Sized + D, +{ + fn get_channel_type(&self) -> SupportedChannelTypes; + fn is_work_selection_enabled(&self) -> bool; + + fn is_downstream_authorized(&self, user_identity: &Str0255) -> Result; + + async fn handle_mining_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: Result = (message_type, payload).try_into(); + async move { + let parsed = parsed?; + self.dispatch_mining_message(parsed).await + } + } + + async fn dispatch_mining_message(&mut self, message: Mining) -> Result<(), Error> { + let (channel_type, work_selection) = + (self.get_channel_type(), self.is_work_selection_enabled()); + + async move { + use Mining::*; + match message { + OpenStandardMiningChannel(m) => { + if !self.is_downstream_authorized(&m.user_identity)? { + // Add correct error type + return Err(Error::OpenStandardMiningChannelError); + } + + match channel_type { + SupportedChannelTypes::Standard + | SupportedChannelTypes::Group + | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_standard_mining_channel(m).await + } + SupportedChannelTypes::Extended => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_STANDARD_MINING_CHANNEL, + )), + } + } + OpenExtendedMiningChannel(m) => { + if !self.is_downstream_authorized(&m.user_identity)? { + // Add correct Error type + return Err(Error::OpenExtendedMiningChannelError); + } + + match channel_type { + SupportedChannelTypes::Extended + | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_extended_mining_channel(m).await + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL, + )), + } + } + UpdateChannel(m) => self.handle_update_channel(m).await, + + SubmitSharesStandard(m) => match channel_type { + SupportedChannelTypes::Standard + | SupportedChannelTypes::Group + | SupportedChannelTypes::GroupAndExtended => { + self.handle_submit_shares_standard(m).await + } + SupportedChannelTypes::Extended => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SUBMIT_SHARES_STANDARD, + )), + }, + + SubmitSharesExtended(m) => match channel_type { + SupportedChannelTypes::Extended | SupportedChannelTypes::GroupAndExtended => { + self.handle_submit_shares_extended(m).await + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SUBMIT_SHARES_EXTENDED, + )), + }, + + SetCustomMiningJob(m) => match (channel_type, work_selection) { + (SupportedChannelTypes::Extended, true) + | (SupportedChannelTypes::GroupAndExtended, true) => { + self.handle_set_custom_mining_job(m).await + } + _ => Err(Error::UnexpectedMessage(MESSAGE_TYPE_SET_CUSTOM_MINING_JOB)), + }, + + _ => Err(Error::UnexpectedMessage(0)), + } + } + } + + async fn handle_open_standard_mining_channel( + &mut self, + msg: OpenStandardMiningChannel, + ) -> Result<(), Error>; + + async fn handle_open_extended_mining_channel( + &mut self, + msg: OpenExtendedMiningChannel, + ) -> Result<(), Error>; + + async fn handle_update_channel(&mut self, msg: UpdateChannel) -> Result<(), Error>; + + async fn handle_submit_shares_standard( + &mut self, + msg: SubmitSharesStandard, + ) -> Result<(), Error>; + + async fn handle_submit_shares_extended( + &mut self, + msg: SubmitSharesExtended, + ) -> Result<(), Error>; + + async fn handle_set_custom_mining_job(&mut self, msg: SetCustomMiningJob) -> Result<(), Error>; +} + +pub trait ParseMiningMessagesFromUpstreamSync +where + Self: Sized + D, +{ + fn get_channel_type(&self) -> SupportedChannelTypes; + fn is_work_selection_enabled(&self) -> bool; + + fn handle_mining_message(&mut self, message_type: u8, payload: &mut [u8]) -> Result<(), Error> { + let parsed: Mining = (message_type, payload).try_into()?; + self.dispatch_mining_message(parsed) + } + + fn dispatch_mining_message(&mut self, message: Mining) -> Result<(), Error> { + let (channel_type, work_selection) = + (self.get_channel_type(), self.is_work_selection_enabled()); + + use Mining::*; + match message { + OpenStandardMiningChannelSuccess(m) => match channel_type { + SupportedChannelTypes::Standard + | SupportedChannelTypes::Group + | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_standard_mining_channel_success(m) + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_STANDARD_MINING_CHANNEL_SUCCESS, + )), + }, + + OpenExtendedMiningChannelSuccess(m) => match channel_type { + SupportedChannelTypes::Extended | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_extended_mining_channel_success(m) + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL_SUCCESS, + )), + }, + + OpenMiningChannelError(m) => self.handle_open_mining_channel_error(m), + UpdateChannelError(m) => self.handle_update_channel_error(m), + CloseChannel(m) => self.handle_close_channel(m), + SetExtranoncePrefix(m) => self.handle_set_extranonce_prefix(m), + SubmitSharesSuccess(m) => self.handle_submit_shares_success(m), + SubmitSharesError(m) => self.handle_submit_shares_error(m), + + NewMiningJob(m) => match channel_type { + SupportedChannelTypes::Standard => self.handle_new_mining_job(m), + _ => Err(Error::UnexpectedMessage(MESSAGE_TYPE_NEW_MINING_JOB)), + }, + + NewExtendedMiningJob(m) => match channel_type { + SupportedChannelTypes::Extended + | SupportedChannelTypes::Group + | SupportedChannelTypes::GroupAndExtended => self.handle_new_extended_mining_job(m), + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_NEW_EXTENDED_MINING_JOB, + )), + }, + + SetNewPrevHash(m) => self.handle_set_new_prev_hash(m), + + SetCustomMiningJobSuccess(m) => match (channel_type, work_selection) { + (SupportedChannelTypes::Extended, true) + | (SupportedChannelTypes::GroupAndExtended, true) => { + self.handle_set_custom_mining_job_success(m) + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SET_CUSTOM_MINING_JOB_SUCCESS, + )), + }, + + SetCustomMiningJobError(m) => match (channel_type, work_selection) { + (SupportedChannelTypes::Extended, true) + | (SupportedChannelTypes::Group, true) + | (SupportedChannelTypes::GroupAndExtended, true) => { + self.handle_set_custom_mining_job_error(m) + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SET_CUSTOM_MINING_JOB_ERROR, + )), + }, + + SetTarget(m) => self.handle_set_target(m), + + SetGroupChannel(m) => match channel_type { + SupportedChannelTypes::Group | SupportedChannelTypes::GroupAndExtended => { + self.handle_set_group_channel(m) + } + _ => Err(Error::UnexpectedMessage(MESSAGE_TYPE_SET_GROUP_CHANNEL)), + }, + + _ => Err(Error::UnexpectedMessage(0)), + } + } + + fn handle_open_standard_mining_channel_success( + &mut self, + msg: OpenStandardMiningChannelSuccess, + ) -> Result<(), Error>; + + fn handle_open_extended_mining_channel_success( + &mut self, + msg: OpenExtendedMiningChannelSuccess, + ) -> Result<(), Error>; + + fn handle_open_mining_channel_error( + &mut self, + msg: OpenMiningChannelError, + ) -> Result<(), Error>; + + fn handle_update_channel_error(&mut self, msg: UpdateChannelError) -> Result<(), Error>; + + fn handle_close_channel(&mut self, msg: CloseChannel) -> Result<(), Error>; + + fn handle_set_extranonce_prefix(&mut self, msg: SetExtranoncePrefix) -> Result<(), Error>; + + fn handle_submit_shares_success(&mut self, msg: SubmitSharesSuccess) -> Result<(), Error>; + + fn handle_submit_shares_error(&mut self, msg: SubmitSharesError) -> Result<(), Error>; + + fn handle_new_mining_job(&mut self, msg: NewMiningJob) -> Result<(), Error>; + + fn handle_new_extended_mining_job(&mut self, msg: NewExtendedMiningJob) -> Result<(), Error>; + + fn handle_set_new_prev_hash(&mut self, msg: SetNewPrevHash) -> Result<(), Error>; + + fn handle_set_custom_mining_job_success( + &mut self, + msg: SetCustomMiningJobSuccess, + ) -> Result<(), Error>; + + fn handle_set_custom_mining_job_error( + &mut self, + msg: SetCustomMiningJobError, + ) -> Result<(), Error>; + + fn handle_set_target(&mut self, msg: SetTarget) -> Result<(), Error>; + + fn handle_set_group_channel(&mut self, msg: SetGroupChannel) -> Result<(), Error>; +} + +#[trait_variant::make(Send)] +pub trait ParseMiningMessagesFromUpstreamAsync +where + Self: Sized + D, +{ + fn get_channel_type(&self) -> SupportedChannelTypes; + fn is_work_selection_enabled(&self) -> bool; + + async fn handle_mining_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: Result = (message_type, payload).try_into(); + async move { + let parsed = parsed?; + self.dispatch_mining_message(parsed).await + } + } + + async fn dispatch_mining_message(&mut self, message: Mining) -> Result<(), Error> { + let (channel_type, work_selection) = + (self.get_channel_type(), self.is_work_selection_enabled()); + + async move { + use Mining::*; + match message { + OpenStandardMiningChannelSuccess(m) => match channel_type { + SupportedChannelTypes::Standard + | SupportedChannelTypes::Group + | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_standard_mining_channel_success(m).await + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_STANDARD_MINING_CHANNEL_SUCCESS, + )), + }, + + OpenExtendedMiningChannelSuccess(m) => match channel_type { + SupportedChannelTypes::Extended | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_extended_mining_channel_success(m).await + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL_SUCCESS, + )), + }, + + OpenMiningChannelError(m) => self.handle_open_mining_channel_error(m).await, + UpdateChannelError(m) => self.handle_update_channel_error(m).await, + CloseChannel(m) => self.handle_close_channel(m).await, + SetExtranoncePrefix(m) => self.handle_set_extranonce_prefix(m).await, + SubmitSharesSuccess(m) => self.handle_submit_shares_success(m).await, + SubmitSharesError(m) => self.handle_submit_shares_error(m).await, + + NewMiningJob(m) => match channel_type { + SupportedChannelTypes::Standard => self.handle_new_mining_job(m).await, + _ => Err(Error::UnexpectedMessage(MESSAGE_TYPE_NEW_MINING_JOB)), + }, + + NewExtendedMiningJob(m) => match channel_type { + SupportedChannelTypes::Extended + | SupportedChannelTypes::Group + | SupportedChannelTypes::GroupAndExtended => { + self.handle_new_extended_mining_job(m).await + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_NEW_EXTENDED_MINING_JOB, + )), + }, + + SetNewPrevHash(m) => self.handle_set_new_prev_hash(m).await, + + SetCustomMiningJobSuccess(m) => match (channel_type, work_selection) { + (SupportedChannelTypes::Extended, true) + | (SupportedChannelTypes::GroupAndExtended, true) => { + self.handle_set_custom_mining_job_success(m).await + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SET_CUSTOM_MINING_JOB_SUCCESS, + )), + }, + + SetCustomMiningJobError(m) => match (channel_type, work_selection) { + (SupportedChannelTypes::Extended, true) + | (SupportedChannelTypes::Group, true) + | (SupportedChannelTypes::GroupAndExtended, true) => { + self.handle_set_custom_mining_job_error(m).await + } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_SET_CUSTOM_MINING_JOB_ERROR, + )), + }, + + SetTarget(m) => self.handle_set_target(m).await, + + SetGroupChannel(m) => match channel_type { + SupportedChannelTypes::Group | SupportedChannelTypes::GroupAndExtended => { + self.handle_set_group_channel(m).await + } + _ => Err(Error::UnexpectedMessage(MESSAGE_TYPE_SET_GROUP_CHANNEL)), + }, + + _ => Err(Error::UnexpectedMessage(0)), + } + } + } + + async fn handle_open_standard_mining_channel_success( + &mut self, + msg: OpenStandardMiningChannelSuccess, + ) -> Result<(), Error>; + + async fn handle_open_extended_mining_channel_success( + &mut self, + msg: OpenExtendedMiningChannelSuccess, + ) -> Result<(), Error>; + + async fn handle_open_mining_channel_error( + &mut self, + msg: OpenMiningChannelError, + ) -> Result<(), Error>; + + async fn handle_update_channel_error(&mut self, msg: UpdateChannelError) -> Result<(), Error>; + + async fn handle_close_channel(&mut self, msg: CloseChannel) -> Result<(), Error>; + + async fn handle_set_extranonce_prefix(&mut self, msg: SetExtranoncePrefix) + -> Result<(), Error>; + + async fn handle_submit_shares_success(&mut self, msg: SubmitSharesSuccess) + -> Result<(), Error>; + + async fn handle_submit_shares_error(&mut self, msg: SubmitSharesError) -> Result<(), Error>; + + async fn handle_new_mining_job(&mut self, msg: NewMiningJob) -> Result<(), Error>; + + async fn handle_new_extended_mining_job( + &mut self, + msg: NewExtendedMiningJob, + ) -> Result<(), Error>; + + async fn handle_set_new_prev_hash(&mut self, msg: SetNewPrevHash) -> Result<(), Error>; + + async fn handle_set_custom_mining_job_success( + &mut self, + msg: SetCustomMiningJobSuccess, + ) -> Result<(), Error>; + + async fn handle_set_custom_mining_job_error( + &mut self, + msg: SetCustomMiningJobError, + ) -> Result<(), Error>; + + async fn handle_set_target(&mut self, msg: SetTarget) -> Result<(), Error>; + + async fn handle_set_group_channel(&mut self, msg: SetGroupChannel) -> Result<(), Error>; +} diff --git a/protocols/v2/handlers-sv2/src/template_distribution.rs b/protocols/v2/handlers-sv2/src/template_distribution.rs new file mode 100644 index 0000000000..f81e807297 --- /dev/null +++ b/protocols/v2/handlers-sv2/src/template_distribution.rs @@ -0,0 +1,213 @@ +use crate::error::HandlerError as Error; +use parsers_sv2::TemplateDistribution; +use template_distribution_sv2::{ + CoinbaseOutputConstraints, NewTemplate, RequestTransactionData, RequestTransactionDataError, + RequestTransactionDataSuccess, SetNewPrevHash, SubmitSolution, +}; + +use core::convert::TryInto; +use template_distribution_sv2::*; + +pub trait ParseTemplateDistributionMessagesFromServerSync { + fn handle_template_distribution_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: TemplateDistribution<'_> = (message_type, payload).try_into()?; + self.dispatch_template_distribution(parsed) + } + + fn dispatch_template_distribution( + &mut self, + message: TemplateDistribution<'_>, + ) -> Result<(), Error> { + match message { + TemplateDistribution::NewTemplate(m) => self.handle_new_template(m), + TemplateDistribution::SetNewPrevHash(m) => self.handle_set_new_prev_hash(m), + TemplateDistribution::RequestTransactionDataSuccess(m) => { + self.handle_request_tx_data_success(m) + } + TemplateDistribution::RequestTransactionDataError(m) => { + self.handle_request_tx_data_error(m) + } + + TemplateDistribution::CoinbaseOutputConstraints(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_COINBASE_OUTPUT_CONSTRAINTS, + )), + TemplateDistribution::RequestTransactionData(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_REQUEST_TRANSACTION_DATA, + )), + TemplateDistribution::SubmitSolution(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_SUBMIT_SOLUTION)) + } + } + } + fn handle_new_template(&mut self, msg: NewTemplate) -> Result<(), Error>; + + fn handle_set_new_prev_hash(&mut self, msg: SetNewPrevHash) -> Result<(), Error>; + + fn handle_request_tx_data_success( + &mut self, + msg: RequestTransactionDataSuccess, + ) -> Result<(), Error>; + + fn handle_request_tx_data_error( + &mut self, + msg: RequestTransactionDataError, + ) -> Result<(), Error>; +} + +#[trait_variant::make(Send)] +pub trait ParseTemplateDistributionMessagesFromServerAsync { + async fn handle_template_distribution_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: Result, _> = (message_type, payload).try_into(); + async move { + let parsed = parsed?; + self.dispatch_template_distribution(parsed).await + } + } + + async fn dispatch_template_distribution( + &mut self, + message: TemplateDistribution<'_>, + ) -> Result<(), Error> { + async move { + match message { + TemplateDistribution::NewTemplate(m) => self.handle_new_template(m).await, + TemplateDistribution::SetNewPrevHash(m) => self.handle_set_new_prev_hash(m).await, + TemplateDistribution::RequestTransactionDataSuccess(m) => { + self.handle_request_tx_data_success(m).await + } + TemplateDistribution::RequestTransactionDataError(m) => { + self.handle_request_tx_data_error(m).await + } + + TemplateDistribution::CoinbaseOutputConstraints(_) => Err( + Error::UnexpectedMessage(MESSAGE_TYPE_COINBASE_OUTPUT_CONSTRAINTS), + ), + TemplateDistribution::RequestTransactionData(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_REQUEST_TRANSACTION_DATA, + )), + TemplateDistribution::SubmitSolution(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_SUBMIT_SOLUTION)) + } + } + } + } + async fn handle_new_template(&mut self, msg: NewTemplate) -> Result<(), Error>; + + async fn handle_set_new_prev_hash(&mut self, msg: SetNewPrevHash) -> Result<(), Error>; + + async fn handle_request_tx_data_success( + &mut self, + msg: RequestTransactionDataSuccess, + ) -> Result<(), Error>; + + async fn handle_request_tx_data_error( + &mut self, + msg: RequestTransactionDataError, + ) -> Result<(), Error>; +} + +pub trait ParseTemplateDistributionMessagesFromClientSync { + fn handle_template_distribution_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: TemplateDistribution<'_> = (message_type, payload).try_into()?; + self.dispatch_template_distribution(parsed) + } + + fn dispatch_template_distribution( + &mut self, + message: TemplateDistribution<'_>, + ) -> Result<(), Error> { + match message { + TemplateDistribution::CoinbaseOutputConstraints(m) => { + self.handle_coinbase_output_constraints(m) + } + TemplateDistribution::RequestTransactionData(m) => self.handle_request_tx_data(m), + TemplateDistribution::SubmitSolution(m) => self.handle_submit_solution(m), + + TemplateDistribution::NewTemplate(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_NEW_TEMPLATE)) + } + TemplateDistribution::SetNewPrevHash(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_SET_NEW_PREV_HASH)) + } + TemplateDistribution::RequestTransactionDataSuccess(_) => Err( + Error::UnexpectedMessage(MESSAGE_TYPE_REQUEST_TRANSACTION_DATA_SUCCESS), + ), + TemplateDistribution::RequestTransactionDataError(_) => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_REQUEST_TRANSACTION_DATA_ERROR, + )), + } + } + + fn handle_coinbase_output_constraints( + &mut self, + msg: CoinbaseOutputConstraints, + ) -> Result<(), Error>; + + fn handle_request_tx_data(&mut self, msg: RequestTransactionData) -> Result<(), Error>; + fn handle_submit_solution(&mut self, msg: SubmitSolution) -> Result<(), Error>; +} + +#[trait_variant::make(Send)] +pub trait ParseTemplateDistributionMessagesFromClientAsync { + async fn handle_template_distribution_message( + &mut self, + message_type: u8, + payload: &mut [u8], + ) -> Result<(), Error> { + let parsed: Result, _> = (message_type, payload).try_into(); + async move { + let parsed = parsed?; + self.dispatch_template_distribution(parsed).await + } + } + + async fn dispatch_template_distribution( + &mut self, + message: TemplateDistribution<'_>, + ) -> Result<(), Error> { + async move { + match message { + TemplateDistribution::CoinbaseOutputConstraints(m) => { + self.handle_coinbase_output_constraints(m).await + } + TemplateDistribution::RequestTransactionData(m) => { + self.handle_request_tx_data(m).await + } + TemplateDistribution::SubmitSolution(m) => self.handle_submit_solution(m).await, + + TemplateDistribution::NewTemplate(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_NEW_TEMPLATE)) + } + TemplateDistribution::SetNewPrevHash(_) => { + Err(Error::UnexpectedMessage(MESSAGE_TYPE_SET_NEW_PREV_HASH)) + } + TemplateDistribution::RequestTransactionDataSuccess(_) => Err( + Error::UnexpectedMessage(MESSAGE_TYPE_REQUEST_TRANSACTION_DATA_SUCCESS), + ), + TemplateDistribution::RequestTransactionDataError(_) => Err( + Error::UnexpectedMessage(MESSAGE_TYPE_REQUEST_TRANSACTION_DATA_ERROR), + ), + } + } + } + + async fn handle_coinbase_output_constraints( + &mut self, + msg: CoinbaseOutputConstraints, + ) -> Result<(), Error>; + + async fn handle_request_tx_data(&mut self, msg: RequestTransactionData) -> Result<(), Error>; + async fn handle_submit_solution(&mut self, msg: SubmitSolution) -> Result<(), Error>; +} From 645db2fe9bd1dd2a175c8234c0015e15d8a5a7fc Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 20 Jul 2025 18:16:18 +0530 Subject: [PATCH 2/8] update protocol crates for new handler crate --- protocols/Cargo.toml | 3 ++- protocols/v2/roles-logic-sv2/Cargo.toml | 1 + protocols/v2/roles-logic-sv2/src/lib.rs | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/protocols/Cargo.toml b/protocols/Cargo.toml index 3380c8827c..2b4c8727e5 100644 --- a/protocols/Cargo.toml +++ b/protocols/Cargo.toml @@ -17,7 +17,8 @@ members = [ "v2/sv2-ffi", "v2/roles-logic-sv2", "v2/channels-sv2", - "v2/parsers-sv2", + "v2/parsers-sv2", + "v2/handlers-sv2", ] [profile.dev] diff --git a/protocols/v2/roles-logic-sv2/Cargo.toml b/protocols/v2/roles-logic-sv2/Cargo.toml index 15826acc37..b03ecc2276 100644 --- a/protocols/v2/roles-logic-sv2/Cargo.toml +++ b/protocols/v2/roles-logic-sv2/Cargo.toml @@ -16,6 +16,7 @@ keywords = ["stratum", "mining", "bitcoin", "protocol"] bitcoin = { version = "0.32.5" } channels_sv2 = { path = "../channels-sv2", version = "^0.1.0" } parsers_sv2 = { path = "../parsers-sv2", version = "^0.1.0" } +handlers_sv2 = { path = "../handlers-sv2", version = "^0.1.0" } common_messages_sv2 = { path = "../../../protocols/v2/subprotocols/common-messages", version = "^5.0.0" } mining_sv2 = { path = "../../../protocols/v2/subprotocols/mining", version = "^4.0.0" } template_distribution_sv2 = { path = "../../../protocols/v2/subprotocols/template-distribution", version = "^3.0.0" } diff --git a/protocols/v2/roles-logic-sv2/src/lib.rs b/protocols/v2/roles-logic-sv2/src/lib.rs index 9d12f3975d..99968d6edb 100644 --- a/protocols/v2/roles-logic-sv2/src/lib.rs +++ b/protocols/v2/roles-logic-sv2/src/lib.rs @@ -28,6 +28,7 @@ pub use channels_sv2; pub use codec_sv2; pub use common_messages_sv2; pub use errors::Error; +pub use handlers_sv2; pub use job_declaration_sv2; pub use mining_sv2; pub use parsers_sv2; From fcff781d3fe6f9cb0f5cf21576322ca40ac6e169 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sun, 20 Jul 2025 18:32:08 +0530 Subject: [PATCH 3/8] update the corresponding lock files all dependent workspaces --- common/Cargo.lock | 27 ++++++++++++++++++++++++++- roles/Cargo.lock | 25 +++++++++++++++++++++++++ test/integration-tests/Cargo.lock | 25 +++++++++++++++++++++++++ utils/Cargo.lock | 25 +++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 1 deletion(-) diff --git a/common/Cargo.lock b/common/Cargo.lock index 93c2609315..613baeac84 100644 --- a/common/Cargo.lock +++ b/common/Cargo.lock @@ -562,6 +562,19 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "handlers_sv2" +version = "0.1.0" +dependencies = [ + "binary_sv2", + "common_messages_sv2", + "job_declaration_sv2", + "mining_sv2", + "parsers_sv2", + "template_distribution_sv2", + "trait-variant", +] + [[package]] name = "hashbrown" version = "0.15.4" @@ -956,6 +969,7 @@ dependencies = [ "channels_sv2", "codec_sv2", "common_messages_sv2", + "handlers_sv2", "hex-conservative 0.3.0", "job_declaration_sv2", "mining_sv2", @@ -1013,7 +1027,7 @@ version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" dependencies = [ - "bitcoin_hashes 0.13.0", + "bitcoin_hashes 0.14.0", "secp256k1-sys 0.10.1", ] @@ -1254,6 +1268,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "trait-variant" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "typenum" version = "1.18.0" diff --git a/roles/Cargo.lock b/roles/Cargo.lock index 287a081fb8..e42b2a82a0 100644 --- a/roles/Cargo.lock +++ b/roles/Cargo.lock @@ -1186,6 +1186,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "handlers_sv2" +version = "0.1.0" +dependencies = [ + "binary_sv2", + "common_messages_sv2", + "job_declaration_sv2", + "mining_sv2", + "parsers_sv2", + "template_distribution_sv2", + "trait-variant", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -2209,6 +2222,7 @@ dependencies = [ "channels_sv2", "codec_sv2", "common_messages_sv2", + "handlers_sv2", "hex-conservative 0.3.0", "job_declaration_sv2", "mining_sv2", @@ -2763,6 +2777,17 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "trait-variant" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "translator_sv2" version = "1.0.0" diff --git a/test/integration-tests/Cargo.lock b/test/integration-tests/Cargo.lock index 49cd487d44..89aaa42a25 100644 --- a/test/integration-tests/Cargo.lock +++ b/test/integration-tests/Cargo.lock @@ -1040,6 +1040,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "handlers_sv2" +version = "0.1.0" +dependencies = [ + "binary_sv2", + "common_messages_sv2", + "job_declaration_sv2", + "mining_sv2", + "parsers_sv2", + "template_distribution_sv2", + "trait-variant", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -2036,6 +2049,7 @@ dependencies = [ "channels_sv2", "codec_sv2", "common_messages_sv2", + "handlers_sv2", "hex-conservative 0.3.0", "job_declaration_sv2", "mining_sv2", @@ -2616,6 +2630,17 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "trait-variant" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "translator_sv2" version = "1.0.0" diff --git a/utils/Cargo.lock b/utils/Cargo.lock index 88519c07bb..23c26c7012 100644 --- a/utils/Cargo.lock +++ b/utils/Cargo.lock @@ -575,6 +575,19 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" +[[package]] +name = "handlers_sv2" +version = "0.1.0" +dependencies = [ + "binary_sv2", + "common_messages_sv2", + "job_declaration_sv2", + "mining_sv2", + "parsers_sv2", + "template_distribution_sv2", + "trait-variant", +] + [[package]] name = "hashbrown" version = "0.7.2" @@ -1038,6 +1051,7 @@ dependencies = [ "channels_sv2", "codec_sv2", "common_messages_sv2", + "handlers_sv2", "hex-conservative 0.3.0", "job_declaration_sv2", "mining_sv2", @@ -1294,6 +1308,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "trait-variant" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "typenum" version = "1.18.0" From 4c60e19dd6688c053cf67d7b24505e01d16de095 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Tue, 22 Jul 2025 10:27:30 +0530 Subject: [PATCH 4/8] feat: add `External` variant to `HandlerError` for user-defined errors Previously, `HandlerError` only supported a fixed set of internal error types. This made it difficult for downstream users implementing library traits to propagate their own custom error types. This commit introduces a new `External(Box)` variant to allow wrapping arbitrary error values. This enables implementors to return non-library errors without requiring changes to the core `HandlerError` enum. --- protocols/v2/handlers-sv2/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/v2/handlers-sv2/src/error.rs b/protocols/v2/handlers-sv2/src/error.rs index c3cad68f16..cae18d750d 100644 --- a/protocols/v2/handlers-sv2/src/error.rs +++ b/protocols/v2/handlers-sv2/src/error.rs @@ -6,7 +6,7 @@ pub enum HandlerError { ParserError(ParserError), OpenStandardMiningChannelError, OpenExtendedMiningChannelError, - ChannelErrorSender, + External(Box), } impl From for HandlerError { From 357b8da761d01aea2e9239298d70c3872d69be11 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Wed, 30 Jul 2025 18:59:03 +0530 Subject: [PATCH 5/8] remove unused generics --- protocols/v2/handlers-sv2/src/mining.rs | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/protocols/v2/handlers-sv2/src/mining.rs b/protocols/v2/handlers-sv2/src/mining.rs index 83851ff475..4c18e5876d 100644 --- a/protocols/v2/handlers-sv2/src/mining.rs +++ b/protocols/v2/handlers-sv2/src/mining.rs @@ -12,7 +12,6 @@ use parsers_sv2::Mining; use std::convert::TryInto; use mining_sv2::*; -use std::fmt::Debug as D; #[derive(PartialEq, Eq)] pub enum SupportedChannelTypes { @@ -22,10 +21,7 @@ pub enum SupportedChannelTypes { GroupAndExtended, } -pub trait ParseMiningMessagesFromDownstreamSync -where - Self: Sized + D, -{ +pub trait ParseMiningMessagesFromDownstreamSync { fn get_channel_type(&self) -> SupportedChannelTypes; fn is_work_selection_enabled(&self) -> bool; @@ -126,10 +122,7 @@ where } #[trait_variant::make(Send)] -pub trait ParseMiningMessagesFromDownstreamAsync -where - Self: Sized + D, -{ +pub trait ParseMiningMessagesFromDownstreamAsync { fn get_channel_type(&self) -> SupportedChannelTypes; fn is_work_selection_enabled(&self) -> bool; @@ -247,10 +240,7 @@ where async fn handle_set_custom_mining_job(&mut self, msg: SetCustomMiningJob) -> Result<(), Error>; } -pub trait ParseMiningMessagesFromUpstreamSync -where - Self: Sized + D, -{ +pub trait ParseMiningMessagesFromUpstreamSync { fn get_channel_type(&self) -> SupportedChannelTypes; fn is_work_selection_enabled(&self) -> bool; @@ -389,10 +379,7 @@ where } #[trait_variant::make(Send)] -pub trait ParseMiningMessagesFromUpstreamAsync -where - Self: Sized + D, -{ +pub trait ParseMiningMessagesFromUpstreamAsync { fn get_channel_type(&self) -> SupportedChannelTypes; fn is_work_selection_enabled(&self) -> bool; From 52626ca4818a6ac6573df0d1d7c1f20e9e9783f0 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Wed, 30 Jul 2025 19:04:19 +0530 Subject: [PATCH 6/8] remove downstream authorization from handlers and let downstream decide how to go about authorization of a connection --- protocols/v2/handlers-sv2/src/error.rs | 2 - protocols/v2/handlers-sv2/src/mining.rs | 95 +++++++++---------------- 2 files changed, 32 insertions(+), 65 deletions(-) diff --git a/protocols/v2/handlers-sv2/src/error.rs b/protocols/v2/handlers-sv2/src/error.rs index cae18d750d..d2fdb13b4a 100644 --- a/protocols/v2/handlers-sv2/src/error.rs +++ b/protocols/v2/handlers-sv2/src/error.rs @@ -4,8 +4,6 @@ use parsers_sv2::ParserError; pub enum HandlerError { UnexpectedMessage(u8), ParserError(ParserError), - OpenStandardMiningChannelError, - OpenExtendedMiningChannelError, External(Box), } diff --git a/protocols/v2/handlers-sv2/src/mining.rs b/protocols/v2/handlers-sv2/src/mining.rs index 4c18e5876d..78eb150b65 100644 --- a/protocols/v2/handlers-sv2/src/mining.rs +++ b/protocols/v2/handlers-sv2/src/mining.rs @@ -38,38 +38,24 @@ pub trait ParseMiningMessagesFromDownstreamSync { use Mining::*; match message { - OpenStandardMiningChannel(m) => { - if !self.is_downstream_authorized(&m.user_identity)? { - // Add correct error type - return Err(Error::OpenStandardMiningChannelError); - } - - match channel_type { - SupportedChannelTypes::Standard - | SupportedChannelTypes::Group - | SupportedChannelTypes::GroupAndExtended => { - self.handle_open_standard_mining_channel(m) - } - SupportedChannelTypes::Extended => Err(Error::UnexpectedMessage( - MESSAGE_TYPE_OPEN_STANDARD_MINING_CHANNEL, - )), - } - } - OpenExtendedMiningChannel(m) => { - if !self.is_downstream_authorized(&m.user_identity)? { - // Add correct Error type - return Err(Error::OpenExtendedMiningChannelError); + OpenStandardMiningChannel(m) => match channel_type { + SupportedChannelTypes::Standard + | SupportedChannelTypes::Group + | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_standard_mining_channel(m) } - - match channel_type { - SupportedChannelTypes::Extended | SupportedChannelTypes::GroupAndExtended => { - self.handle_open_extended_mining_channel(m) - } - _ => Err(Error::UnexpectedMessage( - MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL, - )), + SupportedChannelTypes::Extended => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_STANDARD_MINING_CHANNEL, + )), + }, + OpenExtendedMiningChannel(m) => match channel_type { + SupportedChannelTypes::Extended | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_extended_mining_channel(m) } - } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL, + )), + }, UpdateChannel(m) => self.handle_update_channel(m), SubmitSharesStandard(m) => match channel_type { @@ -126,8 +112,6 @@ pub trait ParseMiningMessagesFromDownstreamAsync { fn get_channel_type(&self) -> SupportedChannelTypes; fn is_work_selection_enabled(&self) -> bool; - fn is_downstream_authorized(&self, user_identity: &Str0255) -> Result; - async fn handle_mining_message( &mut self, message_type: u8, @@ -147,39 +131,24 @@ pub trait ParseMiningMessagesFromDownstreamAsync { async move { use Mining::*; match message { - OpenStandardMiningChannel(m) => { - if !self.is_downstream_authorized(&m.user_identity)? { - // Add correct error type - return Err(Error::OpenStandardMiningChannelError); - } - - match channel_type { - SupportedChannelTypes::Standard - | SupportedChannelTypes::Group - | SupportedChannelTypes::GroupAndExtended => { - self.handle_open_standard_mining_channel(m).await - } - SupportedChannelTypes::Extended => Err(Error::UnexpectedMessage( - MESSAGE_TYPE_OPEN_STANDARD_MINING_CHANNEL, - )), - } - } - OpenExtendedMiningChannel(m) => { - if !self.is_downstream_authorized(&m.user_identity)? { - // Add correct Error type - return Err(Error::OpenExtendedMiningChannelError); + OpenStandardMiningChannel(m) => match channel_type { + SupportedChannelTypes::Standard + | SupportedChannelTypes::Group + | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_standard_mining_channel(m).await } - - match channel_type { - SupportedChannelTypes::Extended - | SupportedChannelTypes::GroupAndExtended => { - self.handle_open_extended_mining_channel(m).await - } - _ => Err(Error::UnexpectedMessage( - MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL, - )), + SupportedChannelTypes::Extended => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_STANDARD_MINING_CHANNEL, + )), + }, + OpenExtendedMiningChannel(m) => match channel_type { + SupportedChannelTypes::Extended | SupportedChannelTypes::GroupAndExtended => { + self.handle_open_extended_mining_channel(m).await } - } + _ => Err(Error::UnexpectedMessage( + MESSAGE_TYPE_OPEN_EXTENDED_MINING_CHANNEL, + )), + }, UpdateChannel(m) => self.handle_update_channel(m).await, SubmitSharesStandard(m) => match channel_type { From 3505a730244131c505d03dae2ff42920fad7ad92 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Wed, 30 Jul 2025 19:18:04 +0530 Subject: [PATCH 7/8] follow client server analogy, and start traits with Handle and not parse --- protocols/v2/handlers-sv2/src/common.rs | 14 ++++--------- .../v2/handlers-sv2/src/job_declaration.rs | 8 +++---- protocols/v2/handlers-sv2/src/lib.rs | 21 +++++++++---------- protocols/v2/handlers-sv2/src/mining.rs | 8 +++---- .../handlers-sv2/src/template_distribution.rs | 8 +++---- 5 files changed, 26 insertions(+), 33 deletions(-) diff --git a/protocols/v2/handlers-sv2/src/common.rs b/protocols/v2/handlers-sv2/src/common.rs index b8987b7d7d..b45a685734 100644 --- a/protocols/v2/handlers-sv2/src/common.rs +++ b/protocols/v2/handlers-sv2/src/common.rs @@ -5,7 +5,7 @@ use common_messages_sv2::{ use core::convert::TryInto; use parsers_sv2::CommonMessages; -pub trait ParseCommonMessagesFromUpstreamSync { +pub trait HandleCommonMessagesFromServerSync { fn handle_common_message(&mut self, message_type: u8, payload: &mut [u8]) -> Result<(), Error> { let parsed: CommonMessages<'_> = (message_type, payload).try_into()?; self.dispatch_common_message(parsed) @@ -40,7 +40,7 @@ pub trait ParseCommonMessagesFromUpstreamSync { } #[trait_variant::make(Send)] -pub trait ParseCommonMessagesFromUpstreamAsync { +pub trait HandleCommonMessagesFromServerAsync { async fn handle_common_message( &mut self, message_type: u8, @@ -92,10 +92,7 @@ pub trait ParseCommonMessagesFromUpstreamAsync { async fn handle_reconnect(&mut self, msg: Reconnect) -> Result<(), Error>; } -pub trait ParseCommonMessagesFromDownstreamSync -where - Self: Sized, -{ +pub trait HandleCommonMessagesFromClientSync { fn handle_common_message(&mut self, message_type: u8, payload: &mut [u8]) -> Result<(), Error> { let parsed: CommonMessages<'_> = (message_type, payload).try_into()?; self.dispatch_common_message(parsed) @@ -122,10 +119,7 @@ where } #[trait_variant::make(Send)] -pub trait ParseCommonMessagesFromDownstreamAsync -where - Self: Sized, -{ +pub trait HandleCommonMessagesFromClientAsync { async fn handle_common_message( &mut self, message_type: u8, diff --git a/protocols/v2/handlers-sv2/src/job_declaration.rs b/protocols/v2/handlers-sv2/src/job_declaration.rs index 6c7d3439b8..d92dd547a7 100644 --- a/protocols/v2/handlers-sv2/src/job_declaration.rs +++ b/protocols/v2/handlers-sv2/src/job_declaration.rs @@ -8,7 +8,7 @@ use job_declaration_sv2::{ }; use parsers_sv2::JobDeclaration; -pub trait ParseJobDeclarationMessagesFromUpstreamSync { +pub trait HandleJobDeclarationMessagesFromServerSync { fn handle_job_declaration_message( &mut self, message_type: u8, @@ -64,7 +64,7 @@ pub trait ParseJobDeclarationMessagesFromUpstreamSync { } #[trait_variant::make(Send)] -pub trait ParseJobDeclarationMessagesFromUpstreamAsync { +pub trait HandleJobDeclarationMessagesFromServerAsync { async fn handle_job_declaration_message( &mut self, message_type: u8, @@ -129,7 +129,7 @@ pub trait ParseJobDeclarationMessagesFromUpstreamAsync { ) -> Result<(), Error>; } -pub trait ParseJobDeclarationMessagesFromDownstreamSync { +pub trait HandleJobDeclarationMessagesFromClientSync { fn handle_job_declaration_message( &mut self, message_type: u8, @@ -181,7 +181,7 @@ pub trait ParseJobDeclarationMessagesFromDownstreamSync { } #[trait_variant::make(Send)] -pub trait ParseJobDeclarationMessagesFromDownstreamAsync { +pub trait HandleJobDeclarationMessagesFromClientAsync { async fn handle_job_declaration_message( &mut self, message_type: u8, diff --git a/protocols/v2/handlers-sv2/src/lib.rs b/protocols/v2/handlers-sv2/src/lib.rs index 61074875b6..1c602fbe2a 100644 --- a/protocols/v2/handlers-sv2/src/lib.rs +++ b/protocols/v2/handlers-sv2/src/lib.rs @@ -7,24 +7,23 @@ mod template_distribution; pub use error::HandlerError; pub use common::{ - ParseCommonMessagesFromDownstreamAsync, ParseCommonMessagesFromDownstreamSync, - ParseCommonMessagesFromUpstreamAsync, ParseCommonMessagesFromUpstreamSync, + HandleCommonMessagesFromClientAsync, HandleCommonMessagesFromClientSync, + HandleCommonMessagesFromServerAsync, HandleCommonMessagesFromServerSync, }; pub use mining::{ - ParseMiningMessagesFromDownstreamAsync, ParseMiningMessagesFromDownstreamSync, - ParseMiningMessagesFromUpstreamAsync, ParseMiningMessagesFromUpstreamSync, - SupportedChannelTypes, + HandleMiningMessagesFromClientAsync, HandleMiningMessagesFromClientSync, + HandleMiningMessagesFromServerAsync, HandleMiningMessagesFromServerSync, SupportedChannelTypes, }; pub use template_distribution::{ - ParseTemplateDistributionMessagesFromClientAsync, - ParseTemplateDistributionMessagesFromClientSync, - ParseTemplateDistributionMessagesFromServerAsync, - ParseTemplateDistributionMessagesFromServerSync, + HandleTemplateDistributionMessagesFromClientAsync, + HandleTemplateDistributionMessagesFromClientSync, + HandleTemplateDistributionMessagesFromServerAsync, + HandleTemplateDistributionMessagesFromServerSync, }; pub use job_declaration::{ - ParseJobDeclarationMessagesFromDownstreamAsync, ParseJobDeclarationMessagesFromDownstreamSync, - ParseJobDeclarationMessagesFromUpstreamAsync, ParseJobDeclarationMessagesFromUpstreamSync, + HandleJobDeclarationMessagesFromClientAsync, HandleJobDeclarationMessagesFromClientSync, + HandleJobDeclarationMessagesFromServerAsync, HandleJobDeclarationMessagesFromServerSync, }; diff --git a/protocols/v2/handlers-sv2/src/mining.rs b/protocols/v2/handlers-sv2/src/mining.rs index 78eb150b65..669d3760f7 100644 --- a/protocols/v2/handlers-sv2/src/mining.rs +++ b/protocols/v2/handlers-sv2/src/mining.rs @@ -21,7 +21,7 @@ pub enum SupportedChannelTypes { GroupAndExtended, } -pub trait ParseMiningMessagesFromDownstreamSync { +pub trait HandleMiningMessagesFromClientSync { fn get_channel_type(&self) -> SupportedChannelTypes; fn is_work_selection_enabled(&self) -> bool; @@ -108,7 +108,7 @@ pub trait ParseMiningMessagesFromDownstreamSync { } #[trait_variant::make(Send)] -pub trait ParseMiningMessagesFromDownstreamAsync { +pub trait HandleMiningMessagesFromClientAsync { fn get_channel_type(&self) -> SupportedChannelTypes; fn is_work_selection_enabled(&self) -> bool; @@ -209,7 +209,7 @@ pub trait ParseMiningMessagesFromDownstreamAsync { async fn handle_set_custom_mining_job(&mut self, msg: SetCustomMiningJob) -> Result<(), Error>; } -pub trait ParseMiningMessagesFromUpstreamSync { +pub trait HandleMiningMessagesFromServerSync { fn get_channel_type(&self) -> SupportedChannelTypes; fn is_work_selection_enabled(&self) -> bool; @@ -348,7 +348,7 @@ pub trait ParseMiningMessagesFromUpstreamSync { } #[trait_variant::make(Send)] -pub trait ParseMiningMessagesFromUpstreamAsync { +pub trait HandleMiningMessagesFromServerAsync { fn get_channel_type(&self) -> SupportedChannelTypes; fn is_work_selection_enabled(&self) -> bool; diff --git a/protocols/v2/handlers-sv2/src/template_distribution.rs b/protocols/v2/handlers-sv2/src/template_distribution.rs index f81e807297..14708cd2ff 100644 --- a/protocols/v2/handlers-sv2/src/template_distribution.rs +++ b/protocols/v2/handlers-sv2/src/template_distribution.rs @@ -8,7 +8,7 @@ use template_distribution_sv2::{ use core::convert::TryInto; use template_distribution_sv2::*; -pub trait ParseTemplateDistributionMessagesFromServerSync { +pub trait HandleTemplateDistributionMessagesFromServerSync { fn handle_template_distribution_message( &mut self, message_type: u8, @@ -59,7 +59,7 @@ pub trait ParseTemplateDistributionMessagesFromServerSync { } #[trait_variant::make(Send)] -pub trait ParseTemplateDistributionMessagesFromServerAsync { +pub trait HandleTemplateDistributionMessagesFromServerAsync { async fn handle_template_distribution_message( &mut self, message_type: u8, @@ -114,7 +114,7 @@ pub trait ParseTemplateDistributionMessagesFromServerAsync { ) -> Result<(), Error>; } -pub trait ParseTemplateDistributionMessagesFromClientSync { +pub trait HandleTemplateDistributionMessagesFromClientSync { fn handle_template_distribution_message( &mut self, message_type: u8, @@ -160,7 +160,7 @@ pub trait ParseTemplateDistributionMessagesFromClientSync { } #[trait_variant::make(Send)] -pub trait ParseTemplateDistributionMessagesFromClientAsync { +pub trait HandleTemplateDistributionMessagesFromClientAsync { async fn handle_template_distribution_message( &mut self, message_type: u8, From e0a5ff4b87dc8045437e88027b46d8e606dbfd57 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 31 Jul 2025 16:43:15 +0530 Subject: [PATCH 8/8] add close channel method Handle Mining message client side --- protocols/v2/handlers-sv2/src/mining.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/protocols/v2/handlers-sv2/src/mining.rs b/protocols/v2/handlers-sv2/src/mining.rs index 669d3760f7..0dd742f67b 100644 --- a/protocols/v2/handlers-sv2/src/mining.rs +++ b/protocols/v2/handlers-sv2/src/mining.rs @@ -83,11 +83,14 @@ pub trait HandleMiningMessagesFromClientSync { } _ => Err(Error::UnexpectedMessage(MESSAGE_TYPE_SET_CUSTOM_MINING_JOB)), }, + CloseChannel(m) => self.handle_close_channel(m), _ => Err(Error::UnexpectedMessage(0)), } } + fn handle_close_channel(&mut self, msg: CloseChannel) -> Result<(), Error>; + fn handle_open_standard_mining_channel( &mut self, msg: OpenStandardMiningChannel, @@ -178,12 +181,15 @@ pub trait HandleMiningMessagesFromClientAsync { } _ => Err(Error::UnexpectedMessage(MESSAGE_TYPE_SET_CUSTOM_MINING_JOB)), }, + CloseChannel(m) => self.handle_close_channel(m).await, _ => Err(Error::UnexpectedMessage(0)), } } } + async fn handle_close_channel(&mut self, msg: CloseChannel) -> Result<(), Error>; + async fn handle_open_standard_mining_channel( &mut self, msg: OpenStandardMiningChannel, @@ -445,7 +451,6 @@ pub trait HandleMiningMessagesFromServerAsync { } _ => Err(Error::UnexpectedMessage(MESSAGE_TYPE_SET_GROUP_CHANNEL)), }, - _ => Err(Error::UnexpectedMessage(0)), } }