Skip to content

Commit

Permalink
Improve Job Declaration Documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
jbesraa committed Dec 9, 2024
1 parent 66c135f commit c0ff977
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,49 @@ use binary_sv2::{Deserialize, Serialize, Str0255, B0255, B064K};
#[cfg(not(feature = "with_serde"))]
use core::convert::TryInto;

/// ## AllocateMiningJobToken (Client -> Server)
/// A request to get an identifier for a future-submitted mining job.
/// Rate limited to a rather slow rate and only available on connections where this has been
/// negotiated. Otherwise, only `mining_job_token(s)` from `CreateMiningJob.Success` are valid.
/// Message used by JDC to request an identifier for a future mining job from JDS.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct AllocateMiningJobToken<'decoder> {
/// Unconstrained sequence of bytes. Whatever is needed by the JDS to
/// identify/authenticate the client. Additional restrictions can be imposed by the
/// JDS. It is highly recommended that UTF-8 encoding is used.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub user_identifier: Str0255<'decoder>,
/// A unique identifier for pairing the response/request.
pub request_id: u32,
}

/// ## AllocateMiningJobTokenSuccess (Server -> Clien)
/// The Server MUST NOT change the value of `coinbase_output_max_additional_size` in
/// `AllocateMiningJobToken.Success` messages unless required for changes to the pool’
/// configuration.
/// Notably, if the pool intends to change the space it requires for coinbase transaction outputs
/// regularly, it should simply prefer to use the maximum of all such output sizes as the
/// `coinbase_output_max_additional_size` value.
/// Message used by JDS to accept [`AllocateMiningJobToken`] message.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct AllocateMiningJobTokenSuccess<'decoder> {
/// A unique identifier for pairing the response/request.
///
/// This **must** be the same as the received [`AllocateMiningJobToken::request_id`].
pub request_id: u32,
/// A token that makes the JDC eligible for committing a mining job for approval/transactions
/// declaration or for identifying custom mining job on mining connection.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub mining_job_token: B0255<'decoder>,
/// The maximum additional size that can be added to the coinbase output.
///
/// The maximum additional serialized bytes which the JDS will add in coinbase transaction
/// outputs.
pub coinbase_output_max_additional_size: u32,
/// Bitcoin transaction outputs added by JDS.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub coinbase_output: B064K<'decoder>,
/// Whether the client is allowed to mine asynchronously.
///
/// If set to true, the [`AllocateMiningJobTokenSuccess::mining_job_token`] can be used
/// immediately on a mining connection in the `SetCustomMiningJob` message, even before
/// [`crate::DeclareMiningJob`] and [`DeclareMiningJobSuccess`] messages have been exchanged.
///
/// If set to false, JDC **must** use this token for [`crate::DeclareMiningJob`] only.
///
/// This **must** be set to true if `SetupConnection::flags` included
/// `REQUIRES_ASYNC_JOB_MINING`.
pub async_mining_allowed: bool,
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,88 @@ use binary_sv2::{Deserialize, Seq064K, Serialize, ShortTxId, Str0255, B0255, B06
#[cfg(not(feature = "with_serde"))]
use core::convert::TryInto;

/// ## DeclareMiningJob (Client -> Server)
/// A request sent by the Job Declarator that proposes a selected set of transactions to the
/// upstream (pool) node.
/// Message used by JDC to proposes a selected set of transactions to JDS they wish to
/// mine on.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct DeclareMiningJob<'decoder> {
/// A unique identifier for this request.
///
/// Used for pairing request/response.
pub request_id: u32,
/// Token received previously through [`crate::AllocateMiningJobTokenSuccess`] message.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub mining_job_token: B0255<'decoder>,
/// Header version field.
pub version: u32,
/// The coinbase transaction nVersion field
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub coinbase_prefix: B064K<'decoder>,
/// Up to 8 bytes (not including the length byte) which are to be placed at the beginning of
/// the coinbase field in the coinbase transaction.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub coinbase_suffix: B064K<'decoder>,
/// A unique nonce used to ensure [`DeclareMiningJob::tx_short_hash_list`] collisions are
/// uncorrelated across the network.
pub tx_short_hash_nonce: u64,
/// A list of short transaction hashes which are used to identify the transactions.
///
/// SipHash 2-4 variant is used for short txids as a strategy to reduce bandwidth consumption.
/// More specifically, the SipHash 2-4 variant is used.
///
/// Inputs to the SipHash functions are transaction hashes from the mempool. Secret keys k0, k1
/// are derived from the first two little-endian 64-bit integers from the
/// SHA256(tx_short_hash_nonce), respectively. For more info see
/// [BIP-0152](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki).
///
/// Upon receiving this message, JDS must check the list against its mempool.
///
/// This list does not include the coinbase transaction.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub tx_short_hash_list: Seq064K<'decoder, ShortTxId<'decoder>>,
/// Hash of the list of full txids, concatenated in the same sequence as they are declared in
/// [`DeclareMiningJob::tx_short_hash_list`].
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub tx_hash_list_hash: U256<'decoder>,
/// Extra data which the JDS may require to validate the work.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub excess_data: B064K<'decoder>,
}

/// ## DeclareMiningJobSuccess (Server -> Client)
/// Messaged used by JDS to accept [`DeclareMiningJob`] message.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct DeclareMiningJobSuccess<'decoder> {
/// A unique identifier for this request.
///
/// Must be the same as the received [`DeclareMiningJob::request_id`].
pub request_id: u32,
/// This **may** be the same token as [DeclareMiningJob::mining_job_token] if the pool allows
/// to start mining on a non declared job. If the token is different (irrespective of if the
/// downstream is already mining using it), the downstream **must** send a `SetCustomMiningJob`
/// message on each connection which wishes to mine using the declared job.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub new_mining_job_token: B0255<'decoder>,
}

/// ## DeclareMiningJobError (Server -> Client)
/// Messaged used by JDS to reject [`DeclareMiningJob`] message.
///
/// Downstream should consider this as a trigger to fallback into some other Pool/JDS or solo
/// mining.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct DeclareMiningJobError<'decoder> {
/// The unique identifier of the request.
///
/// Must be the same as the received [`DeclareMiningJob::request_id`].
pub request_id: u32,
/// Possible values:
///
/// - invalid-mining-job-token
/// - invalid-job-param-value-{DeclareMiningJob::field}
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub error_code: Str0255<'decoder>,
/// Optional details about the error.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub error_details: B064K<'decoder>,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,29 @@ use binary_sv2::{Deserialize, Seq064K, Serialize, U256};
#[cfg(not(feature = "with_serde"))]
use core::convert::TryInto;

/// TODO: comment
/// Message used by JDS as a response to a [`crate::DeclareMiningJob`] message indicating it
/// detected a collision in the [`crate::DeclareMiningJob::tx_short_hash_list`], or was unable to
/// reconstruct the [`crate::DeclareMiningJob::tx_hash_list_hash`].
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct IdentifyTransactions {
/// Mining job unique identifier.
///
/// This **must** be the same as the received [`crate::DeclareMiningJob::request_id`].
pub request_id: u32,
}

/// TODO: comment
/// Messaged used by JDC to accept [`IdentifyTransactions`] message and provide the full set
/// of transaction data hashes.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct IdentifyTransactionsSuccess<'decoder> {
/// Unique identifier.
///
/// This **must** be the same as the received [`IdentifyTransactions::request_id`].
pub request_id: u32,
/// The full list of transaction data hashes used to build the mining job in the corresponding
/// DeclareMiningJob message
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub tx_data_hashes: Seq064K<'decoder, U256<'decoder>>,
}
Expand Down
16 changes: 13 additions & 3 deletions protocols/v2/subprotocols/job-declaration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@

//! # Job Declaration Protocol
//!
//! This protocol runs between the Job Declarator and Pool and can be
//! provided as a trusted 3rd party service for mining farms.
//! `job_declaration_sv2` is a Rust crate that implements a set of messages defined in the Job
//! Declaration Protocol of Stratum V2. This protocol runs between the Job Declarator Server
//! (JDS) and Job Declarator Client (JDC).
//!
//! Protocol flow:
//! ## Build Options
//! This crate can be built with the following features:
//! - `std`: Enables support for standard library features.
//! - `with_serde`: Enables support for serialization and de-serialization using Serde.
//!
//! 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.
//!
//! For further information about the messages, please refer to [Stratum V2 documentation - Job
//! Declaration](https://stratumprotocol.org/specification/06-Job-Declaration-Protocol/).
extern crate alloc;
mod allocate_mining_job_token;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,39 @@ use binary_sv2::{Deserialize, Seq064K, Serialize, B016M};
#[cfg(not(feature = "with_serde"))]
use core::convert::TryInto;

// In order to do block propagation, the JDserver must know all the transactions within the current
// block template. These transactions are provided by the JDclient to the JDserver as a sequence
// of short hashes (in the message DeclareMiningJob). The JDserver has a mempool, which uses to
// identify the transactions from this list. If there is some transaction that it is not in the
// JDserver memppol, the JDserver sends this message to ask for them. They are specified by their
// position in the original DeclareMiningJob message, 0-indexed not including the coinbase
// transaction transaction.

/// Message used by the JDS to ask for transactions that it did not recognize from
/// [`crate::DeclareMiningJob`] message.
///
/// In order to do block propagation, JDS must know all the transactions within the current
/// block template. These transactions are provided by the JDC to the JDserver as a sequence
/// of short hashes in the [`crate::DeclareMiningJob::tx_short_hash_list`] message. If JDserver is
/// unable to recognize any of the transactions through its mempool, it sends this message to ask
/// for them. They are specified by their position in the original DeclareMiningJob message,
/// 0-indexed not including the coinbase transaction transaction.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct ProvideMissingTransactions<'decoder> {
/// Unique Identifier.
///
/// Must be the same as the received [`crate::DeclareMiningJob::request_id`].
pub request_id: u32,
/// A list of unrecognized transactions that need to be supplied by the JDC in full. They are
/// specified by their position in the original [`crate::DeclareMiningJob`] message, 0-indexed
/// not including the coinbase transaction transaction.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub unknown_tx_position_list: Seq064K<'decoder, u16>,
}

// List of full transactions as requested by ProvideMissingTransactions, in the order they were
// requested in ProvideMissingTransactions

/// Message used by JDC to accept [`ProvideMissingTransactions`] message and provide the full
/// list of transactions in the order they were requested by [`ProvideMissingTransactions`].
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct ProvideMissingTransactionsSuccess<'decoder> {
/// Unique Identifier.
///
/// Must be the same as the received [`ProvideMissingTransactions::request_id`].
pub request_id: u32,
/// List of full transactions as requested by [`ProvideMissingTransactions`].
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub transaction_list: Seq064K<'decoder, B016M<'decoder>>,
}
Expand Down
14 changes: 13 additions & 1 deletion protocols/v2/subprotocols/job-declaration/src/submit_solution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,29 @@ use binary_sv2::{Deserialize, Serialize, B032, U256};
#[cfg(not(feature = "with_serde"))]
use core::convert::TryInto;

/// TODO: comment
/// Message used by JDC to submit a solution to JDS as soon as it finds a new valid
/// block.
///
/// Upon receiving this message, JDS should propagate the new block as soon as possible.
///
/// Note that JDC is also expected to share the new block data through `SubmitSolution`
/// message under the Template Distribution Protocol.
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[repr(C)]
pub struct SubmitSolutionJd<'decoder> {
/// Full extranonce that forms a valid submission.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub extranonce: B032<'decoder>,
/// Previous block hash.
#[cfg_attr(feature = "with_serde", serde(borrow))]
pub prev_hash: U256<'decoder>,
/// Contains the time the block was constructed as a Unix timestamp.
pub ntime: u32,
/// Nonce of the block.
pub nonce: u32,
/// The bits field is compact representation of the target at the time the block was mined./
pub nbits: u32,
/// The version field is used to signal for upgrades to Bitcoin.
pub version: u32,
}

Expand Down

0 comments on commit c0ff977

Please sign in to comment.