Skip to content

Commit

Permalink
Rewrite mining subprotocol docs
Browse files Browse the repository at this point in the history
  • Loading branch information
jbesraa committed Dec 12, 2024
1 parent 4595c13 commit 904a9c9
Show file tree
Hide file tree
Showing 12 changed files with 392 additions and 404 deletions.
15 changes: 5 additions & 10 deletions protocols/v2/subprotocols/mining/src/close_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,15 @@ use binary_sv2::{Deserialize, Serialize, Str0255};
#[cfg(not(feature = "with_serde"))]
use core::convert::TryInto;

/// # CloseChannel (Client -> Server, Server -> Client)
/// Message used by a downstream to close a mining channel.
///
/// Client sends this message when it ends its operation. The server MUST stop sending messages
/// for the channel. A proxy MUST send this message on behalf of all opened channels from a
/// downstream connection in case of downstream connection closure.
/// If you are sending this message through a proxy on behalf of multiple downstreams, you must send
/// it for each open channel separately.
///
/// If a proxy is operating in channel aggregating mode (translating downstream channels into
/// aggregated extended upstream channels), it MUST send an UpdateChannel message when it
/// receives CloseChannel or connection closure from a downstream connection. In general, proxy
/// servers MUST keep the upstream node notified about the real state of the downstream
/// channels.
/// Upon receiving this message, upstream **must** stop sending messages for the channel.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CloseChannel<'decoder> {
/// Channel identification.
/// Channel id of the channel to be closed.
pub channel_id: u32,
/// Reason for closing the channel.
#[cfg_attr(feature = "with_serde", serde(borrow))]
Expand Down
134 changes: 28 additions & 106 deletions protocols/v2/subprotocols/mining/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,111 +1,33 @@
#![cfg_attr(feature = "no_std", no_std)]

//! # Mining Protocol
//! ## Channels
//! The protocol is designed such that downstream devices (or proxies) open communication
//! channels with upstream stratum nodes within established connections. The upstream stratum
//! endpoints could be actual mining servers or proxies that pass the messages further upstream.
//! Each channel identifies a dedicated mining session associated with an authorized user.
//! Upstream stratum nodes accept work submissions and specify a mining target on a
//! per-channel basis.
//!
//! There can theoretically be up to 2^32 open channels within one physical connection to an
//! upstream stratum node. All channels are independent of each other, but share some messages
//! broadcasted from the server for higher efficiency (e.g. information about a new prevhash).
//! Each channel is identified by its channel_id (U32), which is consistent throughout the whole
//! life of the connection.
//!
//! A proxy can either transparently allow its clients to open separate channels with the server
//! (preferred behaviour) or aggregate open connections from downstream devices into its own
//! open channel with the server and translate the messages accordingly (present mainly for
//! allowing v1 proxies). Both options have some practical use cases. In either case, proxies
//! SHOULD aggregate clients’ channels into a smaller number of TCP connections. This saves
//! network traffic for broadcast messages sent by a server because fewer messages need to be
//! sent in total, which leads to lower latencies as a result. And it further increases efficiency
//! by allowing larger packets to be sent.
//!
//! The protocol defines three types of channels: **standard channels** , **extended channels**
//! (mining sessions) and **group channels** (organizational), which are useful for different
//! purposes. The main difference between standard and extended channels is that standard channels
//! cannot manipulate the coinbase transaction / Merkle path, as they operate solely on provided
//! Merkle roots. We call this **header-only mining**. Extended channels, on the other hand, are
//! given extensive control over the search space so that they can implement various advanceduse
//! cases such as translation between v1 and v2 protocols, difficulty aggregation, custom
//! search space splitting, etc.
//!
//! This separation vastly simplifies the protocol implementation for clients that don’t support
//! extended channels, as they only need to implement the subset of protocol messages related to
//! standard channels (see Mining Protocol Messages for details).
//!
//! ### Standard Channels
//! # Stratum V2 Mining Protocol Messages Crate
//!
//! Standard channels are intended to be used by end mining devices.
//! The size of the search space for one standard channel (header-only mining) for one particular
//! value in the nTime field is 2^(NONCE_BITS + VERSION_ROLLING_BITS) = ~280Th, where
//! NONCE_BITS = 32 and VERSION_ROLLING_BITS = 16. This is a guaranteed space before
//! nTime rolling (or changing the Merkle root).
//! The protocol dedicates all directly modifiable bits (version, nonce, and nTime) from the block
//! header to one mining channel. This is the smallest assignable unit of search space by the
//! protocol. The client which opened the particular channel owns the whole assigned space and
//! can split it further if necessary (e.g. for multiple hashing boards and for individual chips
//! etc.).
//! `mining_sv2` is a Rust crate that implements a set of messages defined in the Mining protocol
//! of Stratum V2.
//!
//! ### Extended channels
//! The Mining protocol enables the distribution of work to mining devices and the submission of
//! proof-of-work results.
//!
//! Extended channels are intended to be used by proxies. Upstream servers which accept
//! connections and provide work MUST support extended channels. Clients, on the other hand, do
//! not have to support extended channels, as they MAY be implemented more simply with only
//! standard channels at the end-device level. Thus, upstream servers providing work MUST also
//! support standard channels.
//! The size of search space for an extended channel is
//! 2^(NONCE_BITS+VERSION_ROLLING_BITS+extranonce_size*8) per nTime value.
//! For further information about the messages, please refer to [Stratum V2 documentation - Mining](https://stratumprotocol.org/specification/05-Mining-Protocol/).
//!
//! ### Group Channels
//! ## Build Options
//!
//! Standard channels opened within one particular connection can be grouped together to be
//! addressable by a common communication group channel.
//! Whenever a standard channel is created it is always put into some channel group identified by
//! its group_channel_id. Group channel ID namespace is the same as channel ID namespace on a
//! particular connection but the values chosen for group channel IDs must be distinct.
//! This crate can be built with the following features:
//! - `no_std`: Disables the standard library.
//! - `with_serde`: Enables support for serialization and deserialization using Serde.
//!
//! ### Future Jobs
//! An empty future block job or speculated non-empty job can be sent in advance to speedup
//! new mining job distribution. The point is that the mining server MAY have precomputed such a
//! job and is able to pre-distribute it for all active channels. The only missing information to
//! start to mine on the new block is the new prevhash. This information can be provided
//! independently.Such an approach improves the efficiency of the protocol where the upstream node
//! doesn’t waste precious time immediately after a new block is found in the network.
//! **Note that `with_serde` feature flag is only used for the Message Generator, and deprecated
//! for
//! any other kind of usage. It will likely be fully deprecated in the future.**
//!
//! ### Hashing Space Distribution
//! Each mining device has to work on a unique part of the whole search space. The full search
//! space is defined in part by valid values in the following block header fields:
//! * Nonce header field (32 bits),
//! * Version header field (16 bits, as specified by BIP 320),
//! * Timestamp header field.
//! ## Usage
//!
//! The other portion of the block header that’s used to define the full search space is the Merkle
//! root hash of all transactions in the block, projected to the last variable field in the block
//! header:
//! To include this crate in your project, run:
//! ```bash
//! $ cargo add mining_sv2
//! ```
//!
//! * Merkle root, deterministically computed from:
//! * Coinbase transaction: typically 4-8 bytes, possibly much more.
//! * Transaction set: practically unbounded space. All roles in Stratum v2 MUST NOT use
//! transaction selection/ordering for additional hash space extension. This stems both from the
//! concept that miners/pools should be able to choose their transaction set freely without any
//! interference with the protocol, and also to enable future protocol modifications to Bitcoin.
//! In other words, any rules imposed on transaction selection/ordering by miners not described
//! in the rest of this document may result in invalid work/blocks.
//!
//! Mining servers MUST assign a unique subset of the search space to each connection/channel
//! (and therefore each mining device) frequently and rapidly enough so that the mining devices
//! are not running out of search space. Unique jobs can be generated regularly by:
//! * Putting unique data into the coinbase for each connection/channel, and/or
//! * Using unique work from a work provider, e.g. a previous work update (note that this is likely
//! more difficult to implement, especially in light of the requirement that transaction
//! selection/ordering not be used explicitly for additional hash space distribution).
//!
//! This protocol explicitly expects that upstream server software is able to manage the size of
//! the hashing space correctly for its clients and can provide new jobs quickly enough.
//! For further information about the mining protocol, please refer to [Stratum V2 documentation -
//! Mining Protocol](https://stratumprotocol.org/specification/05-Mining-Protocol/).
#![cfg_attr(feature = "no_std", no_std)]
use binary_sv2::{B032, U256};
use core::{
cmp::{Ord, PartialOrd},
Expand Down Expand Up @@ -215,9 +137,11 @@ impl Ord for Target {

// WARNING: do not derive Copy on this type. Some operations performed to a copy of an extranonce
// do not affect the original, and this may lead to different extranonce inconsistency
/// Extranonce bytes which need to be added to the coinbase to form a fully valid submission:
/// (full coinbase = coinbase_tx_prefix + extranonce + coinbase_tx_suffix).
/// Extranonce bytes which need to be added to the coinbase to form a fully valid submission.
///
/// Representation is in big endian, so tail is for the digits relative to smaller powers
///
/// `full coinbase = coinbase_tx_prefix + extranonce + coinbase_tx_suffix`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Extranonce {
extranonce: alloc::vec::Vec<u8>,
Expand Down Expand Up @@ -334,9 +258,9 @@ impl From<&mut ExtendedExtranonce> for Extranonce {
}

#[derive(Debug, Clone)]
/// Downstram and upstream are not global terms but are relative
/// to an actor of the protocol P. In simple terms, upstream is the part of the protocol that a
/// user P sees when he looks above and downstream when he looks beneath.
/// Downstram and upstream are relative to an actor of the protocol P. In simple terms, upstream is
/// the part of the protocol that a user P sees when he looks above and downstream when he looks
/// beneath.
///
/// An ExtendedExtranonce is defined by 3 ranges:
///
Expand Down Expand Up @@ -375,7 +299,6 @@ impl From<&mut ExtendedExtranonce> for Extranonce {
/// range_2 -> 32..32 no more downstream
///
///
///
/// About how the pool work having both extended and standard downstreams:
///
/// the pool reserve the first 16 bytes for herself and let downstreams change the lase 16, so
Expand All @@ -397,7 +320,6 @@ impl From<&mut ExtendedExtranonce> for Extranonce {
/// 0000 0000 0000 0000 0000 0000 0000 0001 ecc ecc
///
///
///
/// ExtendedExtranonce type is meant to be used in cases where the extranonce length is not
/// 32bytes. So, the inner part is an array of 32bytes, but only the firsts corresponding to the
/// range_2.end are used by the pool
Expand Down
Loading

0 comments on commit 904a9c9

Please sign in to comment.