From 860d198661152e8ae3f48b181c273697e5ea5773 Mon Sep 17 00:00:00 2001 From: jbesraa Date: Tue, 5 Nov 2024 17:31:33 +0200 Subject: [PATCH] Rewrite docs in `common_messages_sv2` .. As part of the effort to improve Stratum V2 protocols docs, this commit aims to improves and make the documentation more comprehensive and accessible for contributors and end users alike. --- .../src/channel_endpoint_changed.rs | 16 +- .../subprotocols/common-messages/src/lib.rs | 17 +- .../common-messages/src/setup_connection.rs | 146 ++++++++++++------ 3 files changed, 123 insertions(+), 56 deletions(-) diff --git a/protocols/v2/subprotocols/common-messages/src/channel_endpoint_changed.rs b/protocols/v2/subprotocols/common-messages/src/channel_endpoint_changed.rs index dd28091c95..795a6c4491 100644 --- a/protocols/v2/subprotocols/common-messages/src/channel_endpoint_changed.rs +++ b/protocols/v2/subprotocols/common-messages/src/channel_endpoint_changed.rs @@ -6,16 +6,18 @@ use binary_sv2::{Deserialize, Serialize}; #[cfg(not(feature = "with_serde"))] use core::convert::TryInto; -/// ## ChannelEndpointChanged (Server -> Client) -/// When a channel’s upstream or downstream endpoint changes and that channel had previously -/// sent messages with [channel_msg] bitset of unknown extension_type, the intermediate proxy -/// MUST send a [`ChannelEndpointChanged`] message. Upon receipt thereof, any extension state -/// (including version negotiation and the presence of support for a given extension) MUST be -/// reset and version/presence negotiation must begin again. +/// Message used by an upstream role for announcing a mining channel endpoint change. +/// +/// This message should be sent when a mining channel’s upstream or downstream endpoint changes and +/// that channel had previously exchanged message(s) with `channel_msg` bitset of unknown +/// `extension_type`. +/// +/// When a downstream receives such a message, any extension state (including version and extension +/// support) must be reset and renegotiated. #[repr(C)] #[derive(Serialize, Deserialize, Debug, Copy, Clone, PartialEq, Eq)] pub struct ChannelEndpointChanged { - /// The channel which has changed endpoint. + /// Unique identifier of the channel that has changed its endpoint. pub channel_id: u32, } #[cfg(feature = "with_serde")] diff --git a/protocols/v2/subprotocols/common-messages/src/lib.rs b/protocols/v2/subprotocols/common-messages/src/lib.rs index cc0df87a2b..5f494d5f5e 100644 --- a/protocols/v2/subprotocols/common-messages/src/lib.rs +++ b/protocols/v2/subprotocols/common-messages/src/lib.rs @@ -1,7 +1,16 @@ +//! # Stratum V2 Common Messages Crate. +//! +//! This crate defines a set of shared messages used across all Stratum V2 subprotocols. +//! +//! ## Build Options +//! This crate can be built with the following features: +//! - `std`: Enables support for standard library features. +//! - `serde`: Enables support for serialization and deserialization using Serde. +//! - `//! quickcheck`: Enables support for property-based testing using QuickCheck. +//! +//! For further information about the messages, please refer to [Stratum V2 +//! documentation - Common Messages](https://stratumprotocol.org/specification/03-Protocol-Overview/#36-common-protocol-messages). #![cfg_attr(feature = "no_std", no_std)] - -//! Common messages for [stratum v2][Sv2] -//! The following protocol messages are common across all of the sv2 (sub)protocols. extern crate alloc; mod channel_endpoint_changed; mod setup_connection; @@ -23,10 +32,12 @@ pub use setup_connection::{CSetupConnection, CSetupConnectionError}; #[cfg(not(feature = "with_serde"))] #[no_mangle] +/// A C-compatible function that exports the [`ChannelEndpointChanged`] struct. pub extern "C" fn _c_export_channel_endpoint_changed(_a: ChannelEndpointChanged) {} #[cfg(not(feature = "with_serde"))] #[no_mangle] +/// A C-compatible function that exports the `SetupConnection` struct. pub extern "C" fn _c_export_setup_conn_succ(_a: SetupConnectionSuccess) {} #[cfg(feature = "prop_test")] diff --git a/protocols/v2/subprotocols/common-messages/src/setup_connection.rs b/protocols/v2/subprotocols/common-messages/src/setup_connection.rs index 7bf3308325..ddf542e4ba 100644 --- a/protocols/v2/subprotocols/common-messages/src/setup_connection.rs +++ b/protocols/v2/subprotocols/common-messages/src/setup_connection.rs @@ -16,46 +16,61 @@ use core::convert::TryInto; #[cfg(feature = "with_serde")] use serde_repr::*; -/// ## SetupConnection (Client -> Server) -/// Initiates the connection. This MUST be the first message sent by the client on the newly -/// opened connection. Server MUST respond with either a [`SetupConnectionSuccess`] or -/// [`SetupConnectionError`] message. Clients that are not configured to provide telemetry data to -/// the upstream node SHOULD set device_id to 0-length strings. However, they MUST always set -/// vendor to a string describing the manufacturer/developer and firmware version and SHOULD -/// always set hardware_version to a string describing, at least, the particular hardware/software -/// package in use. +/// Used by downstream to initiate a Stratum V2 connection with an upstream role. +/// +/// This is usually the first message sent by a downstream role on a newly opened connection, +/// after completing the handshake process. +/// +/// Downstreams that do not wish to provide telemetry data to the upstream role **should** set +/// [`SetupConnection::device_id`] to an empty string. However, they **must** set +/// [`SetupConnection::vendor`] to a string describing the manufacturer/developer and firmware +/// version and **should** set [`SetupConnection::hardware_version`] to a string describing, at +/// least, the particular hardware/software package in use. +/// +/// A valid response to this message from the upstream role can either be [`SetupConnectionSuccess`] +/// or [`SetupConnectionError`] message. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct SetupConnection<'decoder> { - /// [`Protocol`] + /// Protocol to be used for the connection. pub protocol: Protocol, - /// The minimum protocol version the client supports (currently must be 2). + /// The minimum protocol version supported. + /// + /// Currently must be set to 2. pub min_version: u16, - /// The maximum protocol version the client supports (currently must be 2). + /// The maximum protocol version supported. + /// + /// Currently must be set to 2. pub max_version: u16, - /// Flags indicating optional protocol features the client supports. Each - /// protocol from [`SetupConnection.protocol`] field has its own values/flags. + /// Flags indicating optional protocol features supported by the downstream. + /// + /// Each [`SetupConnection::protocol`] value has it's own flags. pub flags: u32, - /// ASCII text indicating the hostname or IP address. + /// ASCII representation of the connection hostname or IP address. #[cfg_attr(feature = "with_serde", serde(borrow))] pub endpoint_host: Str0255<'decoder>, - /// Connecting port value + /// Connection port value. pub endpoint_port: u16, - //-- DEVICE INFORMATION --// + /// Device vendor name. #[cfg_attr(feature = "with_serde", serde(borrow))] pub vendor: Str0255<'decoder>, + /// Device hardware version. #[cfg_attr(feature = "with_serde", serde(borrow))] pub hardware_version: Str0255<'decoder>, + /// Device firmware version. #[cfg_attr(feature = "with_serde", serde(borrow))] pub firmware: Str0255<'decoder>, + /// Device identifier. #[cfg_attr(feature = "with_serde", serde(borrow))] pub device_id: Str0255<'decoder>, } impl<'decoder> SetupConnection<'decoder> { + /// Set the flag to indicate that the downstream requires a standard job pub fn set_requires_standard_job(&mut self) { self.flags |= 0b_0000_0000_0000_0000_0000_0000_0000_0001; } + /// Set the flag to indicate that the downstream requires an asynchronous job negotiation pub fn set_async_job_nogotiation(&mut self) { self.flags |= 0b_0000_0000_0000_0000_0000_0000_0000_0001; } @@ -128,7 +143,10 @@ impl<'decoder> SetupConnection<'decoder> { } } - /// Check if passed versions support self versions if yes return the biggest version available + /// Check whether received versions are supported. + /// + /// If the versions are not supported, return `None` otherwise return the biggest version + /// available pub fn get_version(&self, min_version: u16, max_version: u16) -> Option { if self.min_version > max_version || min_version > self.max_version { None @@ -137,22 +155,28 @@ impl<'decoder> SetupConnection<'decoder> { } } + /// Checks whether passed flags indicate that the downstream requires standard job. pub fn requires_standard_job(&self) -> bool { has_requires_std_job(self.flags) } } +/// Helper function to check if `REQUIRES_STANDARD_JOBS` bit flag present. pub fn has_requires_std_job(flags: u32) -> bool { let flags = flags.reverse_bits(); let flag = flags >> 31; flag != 0 } + +/// Helper function to check if `REQUIRES_VERSION_ROLLING` bit flag present. pub fn has_version_rolling(flags: u32) -> bool { let flags = flags.reverse_bits(); let flags = flags << 1; let flag = flags >> 31; flag != 0 } + +/// Helper function to check if `REQUIRES_WORK_SELECTION` bit flag present. pub fn has_work_selection(flags: u32) -> bool { let flags = flags.reverse_bits(); let flags = flags << 2; @@ -160,19 +184,36 @@ pub fn has_work_selection(flags: u32) -> bool { flag != 0 } +/// C representation of [`SetupConnection`] #[repr(C)] #[cfg(not(feature = "with_serde"))] #[derive(Debug, Clone)] pub struct CSetupConnection { + /// Protocol to be used for the connection. pub protocol: Protocol, + /// The minimum protocol version supported. + /// + /// Currently must be set to 2. pub min_version: u16, + /// The maximum protocol version supported. + /// + /// Currently must be set to 2. pub max_version: u16, + /// Flags indicating optional protocol features supported by the downstream. + /// + /// Each [`SetupConnection::protocol`] value has it's own flags. pub flags: u32, + /// ASCII representation of the connection hostname or IP address. pub endpoint_host: CVec, + /// Connection port value. pub endpoint_port: u16, + /// Device vendor name. pub vendor: CVec, + /// Device hardware version. pub hardware_version: CVec, + /// Device firmware version. pub firmware: CVec, + /// Device identifier. pub device_id: CVec, } @@ -180,6 +221,7 @@ pub struct CSetupConnection { impl<'a> CSetupConnection { #[cfg(not(feature = "with_serde"))] #[allow(clippy::wrong_self_convention)] + /// Convert C representation to Rust representation pub fn to_rust_rep_mut(&'a mut self) -> Result, Error> { let endpoint_host: Str0255 = self.endpoint_host.as_mut_slice().try_into()?; let vendor: Str0255 = self.vendor.as_mut_slice().try_into()?; @@ -237,42 +279,51 @@ impl<'a> From> for CSetupConnection { } } -/// ## SetupConnection.Success (Server -> Client) -/// Response to [`SetupConnection`] message if the server accepts the connection. The client is -/// required to verify the set of feature flags that the server supports and act accordingly. +/// Message used by an upstream role to accept a connection setup request from a downstream role. +/// +/// This message is sent in response to a [`SetupConnection`] message. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Copy)] #[repr(C)] pub struct SetupConnectionSuccess { - /// Selected version proposed by the connecting node that the upstream - /// node supports. This version will be used on the connection for the rest - /// of its life. + /// Selected version based on the [`SetupConnection::min_version`] and + /// [`SetupConnection::max_version`] sent by the downstream role. + /// + /// This version will be used on the connection for the rest of its life. pub used_version: u16, - /// Flags indicating optional protocol features the server supports. Each - /// protocol from [`Protocol`] field has its own values/flags. + /// Flags indicating optional protocol features supported by the upstream. + /// + /// The downstream is required to verify this set of flags and act accordingly. + /// + /// Each [`SetupConnection::protocol`] field has its own values/flags. pub flags: u32, } -/// ## SetupConnection.Error (Server -> Client) -/// When protocol version negotiation fails (or there is another reason why the upstream node -/// cannot setup the connection) the server sends this message with a particular error code prior -/// to closing the connection. -/// In order to allow a client to determine the set of available features for a given server (e.g. -/// for proxies which dynamically switch between different pools and need to be aware of supported -/// options), clients SHOULD send a SetupConnection message with all flags set and examine the -/// (potentially) resulting [`SetupConnectionError`] message’s flags field. The Server MUST provide -/// the full set of flags which it does not support in each [`SetupConnectionError`] message and -/// MUST consistently support the same set of flags across all servers on the same hostname and -/// port number. If flags is 0, the error is a result of some condition aside from unsupported -/// flags. +/// Message used by an upstream role to reject a connection setup request from a downstream role. +/// +/// This message is sent in response to a [`SetupConnection`] message. +/// +/// The connection setup process could fail because of protocol version negotiation. In order +/// to allow a downstream to determine the set of available features for a given upstream (e.g. for +/// proxies which dynamically switch between different pools and need to be aware of supported +/// options), downstream should send a [`SetupConnection`] message with all flags set and examine +/// the (potentially) resulting [`SetupConnectionError`] message’s flags field. +/// +/// The upstream must provide the full set of flags which it does not support in each +/// [`SetupConnectionError`] message and must consistently support the same set of flags across all +/// servers on the same hostname and port number. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] pub struct SetupConnectionError<'decoder> { - /// Flags indicating features causing an error. + /// Unsupported feature flags. + /// + /// In case `error_code` is `unsupported-feature-flags`, this field is used to indicate which + /// flag is causing an error, otherwise it will be set to 0. pub flags: u32, - /// Human-readable error code(s). See Error Codes section, [link]. - /// ### Possible error codes: - /// * ‘unsupported-feature-flags’ - /// * ‘unsupported-protocol’ - /// * ‘protocol-version-mismatch’ + /// Reason for setup connection error. + /// + /// Possible error codes: + /// - unsupported-feature-flags + /// - unsupported-protocol + /// - protocol-version-mismatch #[cfg_attr(feature = "with_serde", serde(borrow))] pub error_code: Str0255<'decoder>, } @@ -280,6 +331,7 @@ pub struct SetupConnectionError<'decoder> { #[repr(C)] #[cfg(not(feature = "with_serde"))] #[derive(Debug, Clone)] +/// C representation of [`SetupConnectionError`] pub struct CSetupConnectionError { flags: u32, error_code: CVec, @@ -289,6 +341,7 @@ pub struct CSetupConnectionError { impl<'a> CSetupConnectionError { #[cfg(not(feature = "with_serde"))] #[allow(clippy::wrong_self_convention)] + /// Convert C representation to Rust representation pub fn to_rust_rep_mut(&'a mut self) -> Result, Error> { let error_code: Str0255 = self.error_code.as_mut_slice().try_into()?; @@ -322,16 +375,17 @@ impl<'a> From> for CSetupConnectionError { } } -/// MiningProtocol = [`SV2_MINING_PROTOCOL_DISCRIMINANT`], -/// JobDeclarationProtocol = [`SV2_JOB_DECLARATION_PROTOCOL_DISCRIMINANT`], -/// TemplateDistributionProtocol = [`SV2_TEMPLATE_DISTR_PROTOCOL_DISCRIMINANT`], +/// This enum has a list of the different Stratum V2 subprotocols. #[cfg_attr(feature = "with_serde", derive(Serialize_repr, Deserialize_repr))] #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] #[allow(clippy::enum_variant_names)] pub enum Protocol { + /// Mining protocol. MiningProtocol = SV2_MINING_PROTOCOL_DISCRIMINANT, + /// Job declaration protocol. JobDeclarationProtocol = SV2_JOB_DECLARATION_PROTOCOL_DISCRIMINANT, + /// Template distribution protocol. TemplateDistributionProtocol = SV2_TEMPLATE_DISTR_PROTOCOL_DISCRIMINANT, }