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

mining_sv2 docs #1243

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions protocols/v2/subprotocols/mining/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
README
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)
/// 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 connection 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
118 changes: 10 additions & 108 deletions protocols/v2/subprotocols/mining/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,111 +1,9 @@
#![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
//!
//! 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.).
//!
//! ### Extended channels
//!
//! 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.
//!
//! ### Group Channels
//! The mining protocol is benifical for facilitating the work distibution from upstream roles and
//! also the work submission from downstream roles.
//!
//! 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.
//!
//! ### 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.
//!
//! ### 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.
//!
//! 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:
//!
//! * 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/).
use binary_sv2::{B032, U256};
use core::{
cmp::{Ord, PartialOrd},
Expand Down Expand Up @@ -215,9 +113,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,6 +234,8 @@ impl From<&mut ExtendedExtranonce> for Extranonce {
}

#[derive(Debug, Clone)]
/// ExtendedExtranonce is Lorem Ipsum.
///
/// 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.
Expand Down
Loading
Loading