Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs roles_logic_sv2 #1263

Merged
merged 18 commits into from
Jan 16, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
handlers docs
GitGab19 authored and plebhash committed Jan 16, 2025

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
commit 1427a72e2785f08e662d230d2679c1c814951d05
88 changes: 78 additions & 10 deletions protocols/v2/roles-logic-sv2/src/handlers/common.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
//! # Common Handlers
//!
//! This module defines traits and implementations for handling common Stratum V2 messages exchanged
//! between upstream and downstream nodes.
//!
//! ## Core Traits
//!
//! - `ParseUpstreamCommonMessages`: Implemented by downstream nodes to handle common messages
//! received from upstream nodes, such as setup connection results or channel endpoint changes.
//! - `ParseDownstreamCommonMessages`: Implemented by upstream nodes to process setup connection
//! messages received from downstream nodes.
//!
//! ## Message Handling
//!
//! Handlers in this module are responsible for:
//! - Parsing and deserializing common messages.
//! - Dispatching deserialized messages to appropriate handler functions based on message type, such
//! as `SetupConnection` or `ChannelEndpointChanged`.
//! - Ensuring robust error handling for unexpected or malformed messages.
//!
//! ## Return Type
//!
//! Functions return `Result<SendTo, Error>`, where `SendTo` specifies the next action for the
//! message: whether to forward it, respond to it, or ignore it.
//!
//! ## Structure
//!
//! This module includes:
//! - Traits for upstream and downstream message parsing and handling.
//! - Functions to process common message types while maintaining clear separation of concerns.
//! - Error handling mechanisms to address edge cases and ensure reliable communication within
//! Stratum V2 networks.
use super::SendTo_;
use crate::{
common_properties::CommonDownstreamData,
@@ -41,6 +74,7 @@ where
routing_logic,
)
}

/// Takes a message and it calls the appropriate handler function
///
/// Arguments:
@@ -86,19 +120,43 @@ where
}
}

/// Called by `Self::handle_message_common` when the `SetupConnectionSuccess` message is
/// received from the upstream node.
/// Handles a `SetupConnectionSuccess` message.
///
/// This method processes a `SetupConnectionSuccess` message and handles it
/// by delegating to the appropriate handler.
///
/// # Arguments
/// - `message`: The `SetupConnectionSuccess` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_setup_connection_success(
&mut self,
m: SetupConnectionSuccess,
) -> Result<SendTo, Error>;

/// Called by `Self::handle_message_common` when the `SetupConnectionError` message is received
/// from the upstream node.
/// Handles a `SetupConnectionError` message.
///
/// This method processes a `SetupConnectionError` message and handles it
/// by delegating to the appropriate handler.
///
/// # Arguments
/// - `message`: The `SetupConnectionError` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_setup_connection_error(&mut self, m: SetupConnectionError) -> Result<SendTo, Error>;

/// Called by `Self::handle_message_common` when the `ChannelEndpointChanged` message is
/// received from the upstream node.
/// Handles a `ChannelEndpointChanged` message.
///
/// This method processes a `ChannelEndpointChanged` message and handles it
/// by delegating to the appropriate handler.
///
/// # Arguments
/// - `message`: The `ChannelEndpointChanged` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_channel_endpoint_changed(
&mut self,
m: ChannelEndpointChanged,
@@ -129,6 +187,7 @@ where
Err(e) => Err(e),
}
}

/// It takes a message type and a payload, and if the message is a serialized setup connection
/// message, it calls the `on_setup_connection` function on the routing logic, and then calls
/// the `handle_setup_connection` function on the router
@@ -150,8 +209,8 @@ where
}

/// It takes a message do setup connection message, it calls
/// the `on_setup_connection` function on the routing logic, and then calls the
/// `handle_setup_connection` function on the router
/// the `on_setup_connection` function on the routing logic, and then calls
/// the `handle_setup_connection` function on the router
fn handle_message_common_deserilized(
self_: Arc<Mutex<Self>>,
message: Result<CommonMessages<'_>, Error>,
@@ -192,8 +251,17 @@ where
}
}

/// Called by `Self::handle_message_common` when a setup connection message is received from the
/// downstream node.
/// Handles a `SetupConnection` message.
///
/// This method processes a `SetupConnection` message and handles it
/// by delegating to the appropriate handler in the routing logic.
///
/// # Arguments
/// - `message`: The `SetupConnection` message.
/// - `result`: The result of the `on_setup_connection` call, if available.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_setup_connection(
&mut self,
m: SetupConnection,
192 changes: 181 additions & 11 deletions protocols/v2/roles-logic-sv2/src/handlers/job_declaration.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
//! # Job Declaration Handlers
//!
//! This module defines traits and functions for handling job declaration messages within the
//! Stratum V2 protocol. The job declaration process is integral to managing mining tasks and
//! transactions between server and client components.
//!
//! ## Core Traits
//!
//! - `ParseServerJobDeclarationMessages`: This trait is implemented by downstream nodes to process
//! job declaration messages received from upstream nodes. The trait includes methods for handling
//! job-related events such as mining job token allocation, job declaration successes or errors,
//! and transaction identification or provisioning.
//! - `ParseClientJobDeclarationMessages`: This trait is implemented by upstream nodes to manage job
//! declaration messages received from downstream nodes. It facilitates the handling of job
//! declarations, mining job token allocation, and transaction solutions submitted by downstream
//! nodes.
//!
//! ## Message Handling
//!
//! The handlers are responsible for the following tasks:
//! - Parsing and deserializing job declaration messages into appropriate types.
//! - Dispatching the deserialized messages to specific handler functions based on their type, such
//! as handling job token allocation, job declaration success or error responses, and transaction
//! data management.
//!
//! ## Return Type
//!
//! The functions return a `Result<SendTo, Error>`. The `SendTo` type determines the next action for
//! the message: whether the message should be relayed, responded to, or ignored. If an error occurs
//! during processing, the `Error` type is returned.
//!
//! ## Structure
//!
//! This module contains:
//! - Traits for processing job declaration messages, covering both server-side and client-side
//! handling.
//! - Functions designed to parse, deserialize, and process messages related to job declarations,
//! with robust error handling.
//! - Error handling mechanisms to address unexpected messages and ensure safe processing,
//! particularly in the context of shared state.
use crate::{parsers::JobDeclaration, utils::Mutex};
use std::sync::Arc;
pub type SendTo = SendTo_<JobDeclaration<'static>, ()>;
@@ -7,12 +48,25 @@ use core::convert::TryInto;
use job_declaration_sv2::*;
use tracing::{debug, error, info, trace};

/// A trait implemented by a downstream to handle SV2 job declaration messages.
/// A trait for parsing and handling SV2 job declaration messages sent by a server.
///
/// This trait is designed to be implemented by downstream components that need to handle
/// various job declaration messages from an upstream SV2 server, such as job allocation,
/// declaration success, and error messages.
pub trait ParseServerJobDeclarationMessages
where
Self: Sized,
{
/// Used to parse job declaration message and route to the message's respected handler function
/// Routes an incoming job declaration message to the appropriate handler function.
///
/// # Parameters
/// - `self_`: An `Arc<Mutex<Self>>` instance to ensure thread-safe access to the implementor.
/// - `message_type`: The type identifier of the incoming message.
/// - `payload`: A mutable slice containing the message payload.
///
/// # Returns
/// - `Ok(SendTo)`: Indicates the message was successfully handled.
/// - `Err(Error)`: Indicates an error occurred during message parsing or handling.
fn handle_message_job_declaration(
self_: Arc<Mutex<Self>>,
message_type: u8,
@@ -21,6 +75,16 @@ where
Self::handle_message_job_declaration_deserialized(self_, (message_type, payload).try_into())
}

/// Routes a deserialized job declaration message to the appropriate handler function.
///
/// # Parameters
/// - `self_`: An `Arc<Mutex<Self>>` instance to ensure thread-safe access to the implementor.
/// - `message`: A `Result<JobDeclaration, Error>` containing either the parsed message or an
/// error.
///
/// # Returns
/// - `Ok(SendTo)`: Indicates the message was successfully handled.
/// - `Err(Error)`: Indicates an error occurred during message parsing or handling.
fn handle_message_job_declaration_deserialized(
self_: Arc<Mutex<Self>>,
message: Result<JobDeclaration<'_>, Error>,
@@ -81,44 +145,95 @@ where
Err(e) => Err(e),
}
}
/// When upstream send AllocateMiningJobTokenSuccess self should use the received token to
/// negotiate the next job

/// Handles an `AllocateMiningJobTokenSuccess` message.
///
/// "[`job_declaration_sv2::AllocateMiningJobToken`]"
/// This method processes a message indicating a successful job token allocation.
///
/// # Arguments
/// - `message`: The `AllocateMiningJobTokenSuccess` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_allocate_mining_job_token_success(
&mut self,
message: AllocateMiningJobTokenSuccess,
) -> Result<SendTo, Error>;

// When upstream send DeclareMiningJobSuccess if the token is different from the one negotiated
// self must use the new token to refer to the committed job
/// Handles a `DeclareMiningJobSuccess` message.
///
/// This method processes a message indicating a successful mining job declaration.
///
/// # Arguments
/// - `message`: The `DeclareMiningJobSuccess` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_declare_mining_job_success(
&mut self,
message: DeclareMiningJobSuccess,
) -> Result<SendTo, Error>;

// TODO: comment
/// Handles a `DeclareMiningJobError` message.
///
/// This method processes a message indicating an error in the mining job declaration process.
///
/// # Arguments
/// - `message`: The `DeclareMiningJobError` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_declare_mining_job_error(
&mut self,
message: DeclareMiningJobError,
) -> Result<SendTo, Error>;

// TODO: comment
/// Handles an `IdentifyTransactions` message.
///
/// This method processes a message that provides transaction identification data.
///
/// # Arguments
/// - `message`: The `IdentifyTransactions` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_identify_transactions(
&mut self,
message: IdentifyTransactions,
) -> Result<SendTo, Error>;

// TODO: comment
/// Handles a `ProvideMissingTransactions` message.
///
/// This method processes a message that supplies missing transaction data.
///
/// # Arguments
/// - `message`: The `ProvideMissingTransactions` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_provide_missing_transactions(
&mut self,
message: ProvideMissingTransactions,
) -> Result<SendTo, Error>;
}

/// The `ParseClientJobDeclarationMessages` trait is responsible for handling job declaration
/// messages sent by clients to upstream nodes. The methods process messages like job declarations,
/// solutions, and transaction success indicators, ensuring proper routing and handling.
pub trait ParseClientJobDeclarationMessages
where
Self: Sized,
{
/// Routes an incoming job declaration message to the appropriate handler function.
///
/// # Parameters
/// - `self_`: An `Arc<Mutex<Self>>` instance to ensure thread-safe access to the implementor.
/// - `message_type`: The type identifier of the incoming message.
/// - `payload`: A mutable slice containing the message payload.
///
/// # Returns
/// - `Ok(SendTo)`: Indicates the message was successfully handled.
/// - `Err(Error)`: Indicates an error occurred during message parsing or handling.
fn handle_message_job_declaration(
self_: Arc<Mutex<Self>>,
message_type: u8,
@@ -127,6 +242,16 @@ where
Self::handle_message_job_declaration_deserialized(self_, (message_type, payload).try_into())
}

/// Routes a deserialized job declaration message to the appropriate handler function.
///
/// # Parameters
/// - `self_`: An `Arc<Mutex<Self>>` instance to ensure thread-safe access to the implementor.
/// - `message`: A `Result<JobDeclaration, Error>` containing either the parsed message or an
/// error.
///
/// # Returns
/// - `Ok(SendTo)`: Indicates the message was successfully handled.
/// - `Err(Error)`: Indicates an error occurred during message parsing or handling.
fn handle_message_job_declaration_deserialized(
self_: Arc<Mutex<Self>>,
message: Result<JobDeclaration<'_>, Error>,
@@ -176,27 +301,72 @@ where
.safe_lock(|x| x.handle_submit_solution(message))
.map_err(|e| crate::Error::PoisonLock(e.to_string()))?
}

Ok(_) => todo!(),
Err(e) => Err(e),
}
}

/// Handles an `AllocateMiningJobToken` message.
///
/// This method processes a message that allocates a mining job token.
///
/// # Arguments
/// - `message`: The `AllocateMiningJobToken` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_allocate_mining_job_token(
&mut self,
message: AllocateMiningJobToken,
) -> Result<SendTo, Error>;

/// Handles a `DeclareMiningJob` message.
///
/// This method processes a message that declares a new mining job.
///
/// # Arguments
/// - `message`: The `DeclareMiningJob` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_declare_mining_job(&mut self, message: DeclareMiningJob) -> Result<SendTo, Error>;

/// Handles an `IdentifyTransactionsSuccess` message.
///
/// This method processes a message that confirms the identification of transactions.
///
/// # Arguments
/// - `message`: The `IdentifyTransactionsSuccess` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_identify_transactions_success(
&mut self,
message: IdentifyTransactionsSuccess,
) -> Result<SendTo, Error>;

/// Handles a `ProvideMissingTransactionsSuccess` message.
///
/// This method processes a message that confirms the receipt of missing transactions.
///
/// # Arguments
/// - `message`: The `ProvideMissingTransactionsSuccess` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_provide_missing_transactions_success(
&mut self,
message: ProvideMissingTransactionsSuccess,
) -> Result<SendTo, Error>;

/// Handles a `SubmitSolution` message.
///
/// This method processes a message that submits a solution for the mining job.
///
/// # Arguments
/// - `message`: The `SubmitSolutionJd` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_submit_solution(&mut self, message: SubmitSolutionJd) -> Result<SendTo, Error>;
}
301 changes: 290 additions & 11 deletions protocols/v2/roles-logic-sv2/src/handlers/mining.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,41 @@
//! # Mining Handlers
//!
//! This module defines traits and functions for handling mining-related messages within the Stratum
//! V2 protocol.
//!
//! ## Core Traits
//!
//! - `ParseUpstreamMiningMessages`: Implemented by downstream nodes to process mining messages
//! received from upstream nodes. This trait provides methods for handling mining events like new
//! mining jobs, share submissions, extranonce prefix updates, and channel status updates.
//! - `ParseDownstreamMiningMessages`: Implemented by upstream nodes to manage mining messages
//! received from downstream nodes. This trait includes methods for managing tasks such as
//! submitting shares, opening mining channels, and handling mining job responses.
//!
//! ## Message Handling
//!
//! Handlers in this module are responsible for:
//! - Parsing and deserializing mining-related messages into the appropriate types.
//! - Dispatching the deserialized messages to specific handler functions based on message type,
//! such as handling new mining jobs, share submissions, and extranonce updates.
//! - Ensuring the integrity and validity of received messages, while interacting with downstream
//! mining systems to ensure proper communication and task execution.
//!
//! ## Return Type
//!
//! Functions return `Result<SendTo<Down>, Error>`, where `SendTo<Down>` specifies the next action
//! for the message: whether it should be sent to the downstream node, an error response should be
//! generated, or the message should be ignored.
//!
//! ## Structure
//!
//! This module includes:
//! - Traits for processing mining-related messages for both upstream and downstream communication.
//! - Functions to parse, deserialize, and process messages related to mining, ensuring robust error
//! handling for unexpected conditions.
//! - Support for managing mining channels, extranonce prefixes, and share submissions, while
//! handling edge cases and ensuring the correctness of the mining process.
use crate::{common_properties::RequestIdMapper, errors::Error, parsers::Mining};
use core::convert::TryInto;
use mining_sv2::{
@@ -24,27 +62,40 @@ use tracing::{debug, error, info, trace};

pub type SendTo<Remote> = SendTo_<Mining<'static>, Remote>;

/// Represents supported channel types in a mining connection.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SupportedChannelTypes {
Standard,
Extended,
Group,
// Non header only connection can support both group and extended channels.
/// Represents a connection that supports both group and extended channels.
GroupAndExtended,
}

/// Connection-wide downtream's messages parser implemented by an upstream.
/// Trait for parsing downstream mining messages in a Stratum V2 connection.
///
/// This trait defines methods for parsing and routing downstream messages
/// related to mining operations.
pub trait ParseDownstreamMiningMessages<
Up: IsMiningUpstream<Self, Selector> + D,
Selector: DownstreamMiningSelector<Self> + D,
Router: MiningRouter<Self, Up, Selector>,
> where
Self: IsMiningDownstream + Sized + D,
{
/// Returns the type of channel supported by the downstream connection.
fn get_channel_type(&self) -> SupportedChannelTypes;

/// Used to parse and route SV2 mining messages from the downstream based on `message_type` and
/// `payload`
/// Handles a mining message from the downstream, given its type and payload.
///
/// # Arguments
/// - `self_mutex`: The `Arc<Mutex<Self>>` representing the downstream entity.
/// - `message_type`: The type of the mining message.
/// - `payload`: The raw payload of the message.
/// - `routing_logic`: The logic for routing the message to the appropriate upstream entity.
///
/// # Returns
/// - `Result<SendTo<Up>, Error>`: The result of processing the message.
fn handle_message_mining(
self_mutex: Arc<Mutex<Self>>,
message_type: u8,
@@ -64,7 +115,15 @@ pub trait ParseDownstreamMiningMessages<
}
}

/// Used to route SV2 mining messages from the downstream
/// Deserializes and processes a mining message from the downstream.
///
/// # Arguments
/// - `self_mutex`: The `Arc<Mutex<Self>>` representing the downstream entity.
/// - `message`: The mining message to be processed.
/// - `routing_logic`: The logic for routing the message to the appropriate upstream entity.
///
/// # Returns
/// - `Result<SendTo<Up>, Error>`: The result of processing the message.
fn handle_message_mining_deserialized(
self_mutex: Arc<Mutex<Self>>,
message: Result<Mining<'_>, Error>,
@@ -265,59 +324,151 @@ pub trait ParseDownstreamMiningMessages<
}
}

/// Checks if work selection is enabled for the downstream connection.
///
/// # Returns
/// - `bool`: `true` if work selection is enabled, `false` otherwise.
fn is_work_selection_enabled(&self) -> bool;

/// returns None if the user is authorized and Open
/// Checks if the downstream user is authorized.
///
/// # Arguments
/// - `_self_mutex`: The `Arc<Mutex<Self>>` representing the downstream entity.
/// - `_user_identity`: The user's identity to be checked.
///
/// # Returns
/// - `Result<bool, Error>`: `true` if the user is authorized, `false` otherwise.
fn is_downstream_authorized(
_self_mutex: Arc<Mutex<Self>>,
_user_identity: &binary_sv2::Str0255,
) -> Result<bool, Error> {
Ok(true)
}

/// Handles an `OpenStandardMiningChannel` message.
///
/// This method processes an `OpenStandardMiningChannel` message and initiates the
/// appropriate response.
///
/// # Arguments
/// - `m`: The `OpenStandardMiningChannel` message.
/// - `up`: An optional upstream entity to which the message is forwarded.
///
/// # Returns
/// - `Result<SendTo<Up>, Error>`: The result of processing the message.
fn handle_open_standard_mining_channel(
&mut self,
m: OpenStandardMiningChannel,
up: Option<Arc<Mutex<Up>>>,
) -> Result<SendTo<Up>, Error>;

/// Handles an `OpenExtendedMiningChannel` message.
///
/// This method processes an `OpenExtendedMiningChannel` message and initiates the
/// appropriate response.
///
/// # Arguments
/// - `m`: The `OpenExtendedMiningChannel` message.
///
/// # Returns
/// - `Result<SendTo<Up>, Error>`: The result of processing the message.
fn handle_open_extended_mining_channel(
&mut self,
m: OpenExtendedMiningChannel,
) -> Result<SendTo<Up>, Error>;

/// Handles an `UpdateChannel` message.
///
/// This method processes an `UpdateChannel` message and updates the channel settings.
///
/// # Arguments
/// - `m`: The `UpdateChannel` message.
///
/// # Returns
/// - `Result<SendTo<Up>, Error>`: The result of processing the message.
fn handle_update_channel(&mut self, m: UpdateChannel) -> Result<SendTo<Up>, Error>;

/// Handles a `SubmitSharesStandard` message.
///
/// This method processes a `SubmitSharesStandard` message and validates the submitted shares.
///
/// # Arguments
/// - `m`: The `SubmitSharesStandard` message.
///
/// # Returns
/// - `Result<SendTo<Up>, Error>`: The result of processing the message.
fn handle_submit_shares_standard(
&mut self,
m: SubmitSharesStandard,
) -> Result<SendTo<Up>, Error>;

/// Handles a `SubmitSharesExtended` message.
///
/// This method processes a `SubmitSharesExtended` message and validates the submitted shares.
///
/// # Arguments
/// - `m`: The `SubmitSharesExtended` message.
///
/// # Returns
/// - `Result<SendTo<Up>, Error>`: The result of processing the message.
fn handle_submit_shares_extended(
&mut self,
m: SubmitSharesExtended,
) -> Result<SendTo<Up>, Error>;

/// Handles a `SetCustomMiningJob` message.
///
/// This method processes a `SetCustomMiningJob` message and applies the custom mining job
/// settings.
///
/// # Arguments
/// - `m`: The `SetCustomMiningJob` message.
///
/// # Returns
/// - `Result<SendTo<Up>, Error>`: The result of processing the message.
fn handle_set_custom_mining_job(&mut self, m: SetCustomMiningJob) -> Result<SendTo<Up>, Error>;
}
/// Connection-wide upstream's messages parser implemented by a downstream.

/// A trait defining the parser for upstream mining messages used by a downstream.
///
/// This trait provides the functionality to handle and route various types of mining messages
/// from the upstream based on the message type and payload.
pub trait ParseUpstreamMiningMessages<
Down: IsMiningDownstream + D,
Selector: DownstreamMiningSelector<Down> + D,
Router: MiningRouter<Down, Self, Selector>,
> where
Self: IsMiningUpstream<Down, Selector> + Sized + D,
{
/// Retrieves the type of the channel supported by this upstream parser.
///
/// # Returns
/// - `SupportedChannelTypes`: The supported channel type for this upstream.
fn get_channel_type(&self) -> SupportedChannelTypes;

/// Retrieves an optional RequestIdMapper, used to manage request IDs across connections.
///
/// # Returns
/// - `Option<Arc<Mutex<RequestIdMapper>>>`: An optional RequestIdMapper for request ID
/// modification.
fn get_request_id_mapper(&mut self) -> Option<Arc<Mutex<RequestIdMapper>>> {
None
}

/// Used to parse and route SV2 mining messages from the upstream based on `message_type` and
/// `payload` The implementor of DownstreamMining needs to pass a RequestIdMapper if needing
/// to change the req id. Proxies likely would want to update a downstream req id to a new
/// one as req id must be connection-wide unique
/// Parses and routes SV2 mining messages from the upstream based on the message type and
/// payload. The implementor of DownstreamMining needs to pass a RequestIdMapper if changing
/// the request ID. Proxies typically need this to ensure the request ID is unique across
/// the connection.
///
/// # Arguments
/// - `self_mutex`: The `Arc<Mutex<Self>>` representing the downstream entity.
/// - `message_type`: The type of the incoming message.
/// - `payload`: The payload containing the message data.
/// - `routing_logic`: The logic to handle the routing of the message based on the type.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message, either sending a
/// response or an error.
fn handle_message_mining(
self_mutex: Arc<Mutex<Self>>,
message_type: u8,
@@ -334,6 +485,17 @@ pub trait ParseUpstreamMiningMessages<
}
}

/// Handles the deserialized mining message from the upstream, processing it according to the
/// routing logic.
///
/// # Arguments
/// - `self_mutex`: The `Arc<Mutex<Self>>` representing the downstream entity.
/// - `message`: The deserialized mining message, wrapped in a Result for error handling.
/// - `routing_logic`: The logic used to route the message based on the type.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message, either sending a
/// response or an error.
fn handle_message_mining_deserialized(
self_mutex: Arc<Mutex<Self>>,
message: Result<Mining, Error>,
@@ -673,64 +835,181 @@ pub trait ParseUpstreamMiningMessages<
}
}

/// Determines whether work selection is enabled for this upstream.
///
/// # Returns
/// - `bool`: A boolean indicating if work selection is enabled.
fn is_work_selection_enabled(&self) -> bool;

/// Handles a successful response for opening a standard mining channel.
///
/// # Arguments
/// - `m`: The `OpenStandardMiningChannelSuccess` message.
/// - `remote`: An optional reference to the downstream, wrapped in an `Arc<Mutex>`.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_open_standard_mining_channel_success(
&mut self,
m: OpenStandardMiningChannelSuccess,
remote: Option<Arc<Mutex<Down>>>,
) -> Result<SendTo<Down>, Error>;

/// Handles a successful response for opening an extended mining channel.
///
/// # Arguments
/// - `m`: The `OpenExtendedMiningChannelSuccess` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_open_extended_mining_channel_success(
&mut self,
m: OpenExtendedMiningChannelSuccess,
) -> Result<SendTo<Down>, Error>;

/// Handles an error when opening a mining channel.
///
/// # Arguments
/// - `m`: The `OpenMiningChannelError` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the error.
fn handle_open_mining_channel_error(
&mut self,
m: OpenMiningChannelError,
) -> Result<SendTo<Down>, Error>;

/// Handles an error when updating a mining channel.
///
/// # Arguments
/// - `m`: The `UpdateChannelError` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the error.
fn handle_update_channel_error(&mut self, m: UpdateChannelError)
-> Result<SendTo<Down>, Error>;

/// Handles a request to close a mining channel.
///
/// # Arguments
/// - `m`: The `CloseChannel` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_close_channel(&mut self, m: CloseChannel) -> Result<SendTo<Down>, Error>;

/// Handles a request to set the extranonce prefix for mining.
///
/// # Arguments
/// - `m`: The `SetExtranoncePrefix` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_set_extranonce_prefix(
&mut self,
m: SetExtranoncePrefix,
) -> Result<SendTo<Down>, Error>;

/// Handles a successful submission of shares.
///
/// # Arguments
/// - `m`: The `SubmitSharesSuccess` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_submit_shares_success(
&mut self,
m: SubmitSharesSuccess,
) -> Result<SendTo<Down>, Error>;

/// Handles an error when submitting shares.
///
/// # Arguments
/// - `m`: The `SubmitSharesError` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the error.
fn handle_submit_shares_error(&mut self, m: SubmitSharesError) -> Result<SendTo<Down>, Error>;

/// Handles a new mining job.
///
/// # Arguments
/// - `m`: The `NewMiningJob` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_new_mining_job(&mut self, m: NewMiningJob) -> Result<SendTo<Down>, Error>;

/// Handles a new extended mining job.
///
/// # Arguments
/// - `m`: The `NewExtendedMiningJob` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_new_extended_mining_job(
&mut self,
m: NewExtendedMiningJob,
) -> Result<SendTo<Down>, Error>;

/// Handles a request to set the new previous hash.
///
/// # Arguments
/// - `m`: The `SetNewPrevHash` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_set_new_prev_hash(&mut self, m: SetNewPrevHash) -> Result<SendTo<Down>, Error>;

/// Handles a successful response for setting a custom mining job.
///
/// # Arguments
/// - `m`: The `SetCustomMiningJobSuccess` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_set_custom_mining_job_success(
&mut self,
m: SetCustomMiningJobSuccess,
) -> Result<SendTo<Down>, Error>;

/// Handles an error when setting a custom mining job.
///
/// # Arguments
/// - `m`: The `SetCustomMiningJobError` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the error.
fn handle_set_custom_mining_job_error(
&mut self,
m: SetCustomMiningJobError,
) -> Result<SendTo<Down>, Error>;

/// Handles a request to set the target for mining.
///
/// # Arguments
/// - `m`: The `SetTarget` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_set_target(&mut self, m: SetTarget) -> Result<SendTo<Down>, Error>;

/// Handles a request to reconnect the mining connection.
///
/// # Arguments
/// - `m`: The `Reconnect` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_reconnect(&mut self, m: Reconnect) -> Result<SendTo<Down>, Error>;

/// Handles a request to set the group channel for mining.
///
/// # Arguments
/// - `_m`: The `SetGroupChannel` message.
///
/// # Returns
/// - `Result<SendTo<Down>, Error>`: The result of processing the message.
fn handle_set_group_channel(&mut self, _m: SetGroupChannel) -> Result<SendTo<Down>, Error> {
Ok(SendTo::None(None))
}
89 changes: 40 additions & 49 deletions protocols/v2/roles-logic-sv2/src/handlers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,76 +1,65 @@
//! Handlers are divided per (sub)protocol and per Downstream/Upstream.
//! Each (sup)protocol defines a handler for both the Upstream node and the Downstream node
//! Handlers are a trait called `Parse[Downstream/Upstream][(sub)protocol]`
//! (eg. `ParseDownstreamCommonMessages`).
//! # Handlers Overview
//!
//! When implemented, the handler makes the `handle_message_[(sub)protoco](..)` (e.g.
//! `handle_message_common(..)`) function available.
//! This module centralizes the logic for processing and routing Stratum V2 protocol messages,
//! defining traits and utilities to handle messages for both Downstream and Upstream roles.
//!
//! The trait requires the implementer to define one function for each message type that a role
//! defined by the (sub)protocol and the Upstream/Downstream state could receive.
//! ## Purpose
//!
//! This function will always take a mutable ref to `self`, a message payload + message type, and
//! the routing logic.
//! Using `parsers` in `crate::parser`, the payload and message type are parsed in an actual SV2
//! message.
//! Routing logic is used in order to select the correct Downstream/Upstream to which the message
//! must be relayed/sent.
//! Routing logic is used to update the request id when needed.
//! After that, the specific function for the message type (implemented by the implementer) is
//! called with the SV2 message and the remote that must receive the message.
//! - Standardize the handling of protocol-specific messages.
//! - Enable efficient routing, transformation, and relaying of messages between nodes.
//! - Support modularity and scalability across Stratum V2 subprotocols.
//!
//! A `Result<SendTo_, Error>` is returned and it is the duty of the implementer to send the
//! message.
//! ## Structure
//!
//! The module is organized by subprotocol and role, with handler traits for:
//! - `ParseDownstream[Protocol]`: Handles messages from Downstream nodes.
//! - `ParseUpstream[Protocol]`: Handles messages from Upstream nodes.
//!
//! Supported subprotocols include:
//! - `common`: Shared messages across protocols.
//! - `job_declaration`: Job-related messages.
//! - `mining`: Mining-specific messages.
//! - `template_distribution`: Template distribution messages.
//!
//! ## Return Values
//!
//! Handlers return `Result<SendTo_, Error>`, where:
//! - `SendTo_` specifies the action (relay, respond, or no action).
//! - `Error` indicates processing issues.
pub mod common;
pub mod job_declaration;
pub mod mining;
pub mod template_distribution;

use crate::utils::Mutex;
use std::sync::Arc;

#[derive(Debug)]
/// Message is a serializable entity that rapresent the meanings of communication between Remote(s)
/// SendTo_ is used to add context to Message, it say what we need to do with that Message.
/// Represents a serializable entity used for communication between Remotes.
/// The `SendTo_` enum adds context to the message, specifying the intended action.
pub enum SendTo_<Message, Remote> {
/// Used by proxies when Message must be relayed downstream or upstream and we want to specify
/// to which particular downstream or upstream we want to relay the message.
///
/// When the message that we need to relay is the same message that we received should be used
/// RelaySameMessageToRemote in order to save an allocation.
/// Relay a new message to a specific remote.
RelayNewMessageToRemote(Arc<Mutex<Remote>>, Message),
/// Used by proxies when Message must be relayed downstream or upstream and we want to specify
/// to which particular downstream or upstream we want to relay the message.
///
/// Is used when we need to relay the same message the we received in order to save an
/// allocation.
/// Relay the same received message to a specific remote to avoid extra allocations.
RelaySameMessageToRemote(Arc<Mutex<Remote>>),
/// Used by proxies when Message must be relayed downstream or upstream and we do not want to
/// specify specify to which particular downstream or upstream we want to relay the
/// message.
/// Relay a new message without specifying a specific remote.
///
/// This is used in proxies that do and Sv1 to Sv2 translation. The upstream is connected via
/// an extended channel that means that
/// This is common in proxies that translate between SV1 and SV2 protocols, where messages are
/// often broadcasted via extended channels.
RelayNewMessage(Message),
/// Used proxies clients and servers to directly respond to a received message.
/// Directly respond to a received message.
Respond(Message),
/// Relay multiple messages to various destinations.
Multiple(Vec<SendTo_<Message, Remote>>),
/// Used by proxies, clients, and servers, when Message do not have to be used in any of the
/// above way. If Message is still needed to be used in a non conventional way we use
/// SendTo::None(Some(message)) If we just want to discard it we can use SendTo::None(None)
/// Indicates that no immediate action is required for the message.
///
/// SendTo::None(Some(m)) could be used for example when we do not need to send the message,
/// but we still need it for successive handling/transformation.
/// One of these cases are proxies that are connected to upstream via an extended channel (like
/// the Sv1 <-> Sv2 translator). This because extended channel messages are always general
/// for all the downstream, where standard channel message can be specific for a particular
/// downstream. Another case is when 2 roles are implemented in the same software, like a
/// pool that is both TP client and a Mining server, messages received by the TP client
/// must be sent to the Mining Server than transformed in Mining messages and sent to the
/// downstream.
/// This variant allows for cases where the message is still needed for later processing
/// (e.g., transformations or when two roles are implemented in the same software).
None(Option<Message>),
}

impl<SubProtocol, Remote> SendTo_<SubProtocol, Remote> {
/// Extracts the message, if available.
pub fn into_message(self) -> Option<SubProtocol> {
match self {
Self::RelayNewMessageToRemote(_, m) => Some(m),
@@ -81,6 +70,8 @@ impl<SubProtocol, Remote> SendTo_<SubProtocol, Remote> {
Self::None(m) => m,
}
}

/// Extracts the remote, if available.
pub fn into_remote(self) -> Option<Arc<Mutex<Remote>>> {
match self {
Self::RelayNewMessageToRemote(r, _) => Some(r),
170 changes: 170 additions & 0 deletions protocols/v2/roles-logic-sv2/src/handlers/template_distribution.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,40 @@
//! # Template Distribution Handlers
//!
//! This module defines traits and functions for handling template distribution messages within the
//! Stratum V2 protocol.
//!
//! ## Core Traits
//!
//! - `ParseServerTemplateDistributionMessages`: Implemented by downstream nodes to process template
//! distribution messages received from upstream nodes. This trait includes methods for handling
//! template-related events like new templates, previous hash updates, and transaction data
//! requests.
//! - `ParseClientTemplateDistributionMessages`: Implemented by upstream nodes to manage template
//! distribution messages received from downstream nodes. This trait handles coinbase output size,
//! transaction data requests, and solution submissions.
//!
//! ## Message Handling
//!
//! Handlers are responsible for:
//! - Parsing and deserializing template distribution messages into appropriate types.
//! - Dispatching the deserialized messages to specific handler functions based on message type,
//! such as handling new templates, transaction data requests, and coinbase output data.
//!
//! ## Return Type
//!
//! Functions return `Result<SendTo, Error>`, where `SendTo` determines the next action for the
//! message: whether it should be relayed, responded to, or ignored.
//!
//! ## Structure
//!
//! This module includes:
//! - Traits for processing template distribution messages, including server-side and client-side
//! handling.
//! - Functions to parse, deserialize, and process messages related to template distribution,
//! ensuring robust error handling.
//! - Error handling mechanisms to address unexpected messages and ensure safe processing,
//! especially in the context of shared state.
use super::SendTo_;
use crate::{errors::Error, parsers::TemplateDistribution, utils::Mutex};
use template_distribution_sv2::{
@@ -11,10 +48,28 @@ use core::convert::TryInto;
use std::sync::Arc;
use tracing::{debug, error, info, trace};

/// Trait for handling template distribution messages received from upstream nodes (server side).
/// Includes functions to handle messages such as new templates, previous hash updates, and
/// transaction data requests.
pub trait ParseServerTemplateDistributionMessages
where
Self: Sized,
{
/// Handles incoming template distribution messages.
///
/// This function is responsible for parsing and dispatching the appropriate handler based on
/// the message type. It first deserializes the payload and then routes it to the
/// corresponding handler function.
///
/// # Arguments
/// - `self_`: An `Arc<Mutex<Self>>` representing the instance of the object implementing this
/// trait.
/// - `message_type`: The type of the incoming message.
/// - `payload`: The raw payload data of the message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message, where `SendTo` indicates
/// the next step in message handling.
fn handle_message_template_distribution(
self_: Arc<Mutex<Self>>,
message_type: u8,
@@ -25,6 +80,19 @@ where
(message_type, payload).try_into(),
)
}

/// Handles deserialized template distribution messages.
///
/// This function takes the deserialized message and processes it according to the specific
/// message type, invoking the appropriate handler function.
///
/// # Arguments
/// - `self_`: An `Arc<Mutex<Self>>` representing the instance of the object implementing this
/// trait.
/// - `message`: The deserialized `TemplateDistribution` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_message_template_distribution_desrialized(
self_: Arc<Mutex<Self>>,
message: Result<TemplateDistribution<'_>, Error>,
@@ -80,22 +148,82 @@ where
Err(e) => Err(e),
}
}

/// Handles a `NewTemplate` message.
///
/// This method processes the `NewTemplate` message, which contains information about a newly
/// generated template.
///
/// # Arguments
/// - `m`: The `NewTemplate` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_new_template(&mut self, m: NewTemplate) -> Result<SendTo, Error>;

/// Handles a `SetNewPrevHash` message.
///
/// This method processes the `SetNewPrevHash` message, which updates the previous hash for a
/// template.
///
/// # Arguments
/// - `m`: The `SetNewPrevHash` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_set_new_prev_hash(&mut self, m: SetNewPrevHash) -> Result<SendTo, Error>;

/// Handles a `RequestTransactionDataSuccess` message.
///
/// This method processes the success response for a requested transaction data message.
///
/// # Arguments
/// - `m`: The `RequestTransactionDataSuccess` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_request_tx_data_success(
&mut self,
m: RequestTransactionDataSuccess,
) -> Result<SendTo, Error>;

/// Handles a `RequestTransactionDataError` message.
///
/// This method processes an error response for a requested transaction data message.
///
/// # Arguments
/// - `m`: The `RequestTransactionDataError` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_request_tx_data_error(
&mut self,
m: RequestTransactionDataError,
) -> Result<SendTo, Error>;
}

/// Trait for handling template distribution messages received from downstream nodes (client side).
/// Includes functions to handle messages such as coinbase output data size, transaction data
/// requests, and solution submissions.
pub trait ParseClientTemplateDistributionMessages
where
Self: Sized,
{
/// Handles incoming template distribution messages.
///
/// This function is responsible for parsing and dispatching the appropriate handler based on
/// the message type. It first deserializes the payload and then routes it to the
/// corresponding handler function.
///
/// # Arguments
/// - `self_`: An `Arc<Mutex<Self>>` representing the instance of the object implementing this
/// trait.
/// - `message_type`: The type of the incoming message.
/// - `payload`: The raw payload data of the message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message, where `SendTo` indicates
/// the next step in message handling.
fn handle_message_template_distribution(
self_: Arc<Mutex<Self>>,
message_type: u8,
@@ -107,6 +235,18 @@ where
)
}

/// Handles deserialized template distribution messages.
///
/// This function takes the deserialized message and processes it according to the specific
/// message type, invoking the appropriate handler function.
///
/// # Arguments
/// - `self_`: An `Arc<Mutex<Self>>` representing the instance of the object implementing this
/// trait.
/// - `message`: The deserialized `TemplateDistribution` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_message_template_distribution_desrialized(
self_: Arc<Mutex<Self>>,
message: Result<TemplateDistribution<'_>, Error>,
@@ -137,8 +277,38 @@ where
Err(e) => Err(e),
}
}

/// Handles a `CoinbaseOutputDataSize` message.
///
/// This method processes a message that includes the coinbase output data size.
///
/// # Arguments
/// - `m`: The `CoinbaseOutputDataSize` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_coinbase_out_data_size(&mut self, m: CoinbaseOutputDataSize)
-> Result<SendTo, Error>;

/// Handles a `RequestTransactionData` message.
///
/// This method processes a message requesting transaction data.
///
/// # Arguments
/// - `m`: The `RequestTransactionData` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_request_tx_data(&mut self, m: RequestTransactionData) -> Result<SendTo, Error>;

/// Handles a `SubmitSolution` message.
///
/// This method processes a solution submission message.
///
/// # Arguments
/// - `m`: The `SubmitSolution` message.
///
/// # Returns
/// - `Result<SendTo, Error>`: The result of processing the message.
fn handle_request_submit_solution(&mut self, m: SubmitSolution) -> Result<SendTo, Error>;
}