The Job Declaration Protocol is used to coordinate the creation of custom work, avoiding scenarios where Pools are unilaterally imposing work on miners.
Pools that opt into this protocol are only responsible for accounting shares and distributing rewards.
This is a key feature of Stratum V2 that improves Bitcoin decentralization.
The Job Declarator Server (JDS) is deployed on Pool side, although it could be theoretically outsourced to a third party that is trusted by the Pool.
In order to fully implement the Server side of the Job Declaration Protocol, the JDS also needs to exchange RPCs (or similar) with a Bitcoin Node.
It is responsible for:
The Job Declarator Client (JDC) is deployed on the miner side.
In order to fully implement the Client side of the Job Declaration Protocol, the JDC also needs to operate under the Template Distribution and Mining Protocols.
It is responsible for:
Additionally, if:
AllocateMiningJobToken.Success
in a reasonable time.DeclareMiningJob.Error
.SetCustomMiningJob.Success
and/or DeclareMiningJob.Success
.JDC is also responsible for switching to a new Pool+JDS (or solo mining as a last resort).
This fallback strategy incentivizes honesty on Pool side, otherwise it will lose hashrate by rejecting Shares for a Custom Job that was already acknowledged to be valid.
Under Coinbase-only mode:
mining_job_token
to JDC (AllocateMiningJobToken
/ AllocateMiningJobToken.Success
).mining_job_token
) by looking at the coinbase.SetCustomMiningJob.Success
.DeclareMiningJob
message is never used.In other words, Pool + JDS operating under Coinbase-only mode do not require to ever know which transactions are included in the miner template, preserving the privacy around the miner's mempool.
This leaves Pool arguably vulnerable to an attack where miner declares a coinbase with some fee revenue while one of the following situations is true:
This potential attack vector is in many ways identical to block withholding and defenses against block withholding generally apply.
Some pools may wish to utilize additional mitigations. For example, Zero-Knowledge-Proof based protocol extensions, where JDC proves that the fee revenue on the coinbase belongs to a valid template, without ever revealing the template itself.
As soon as JDC has:
It SHOULD start sending the jobs downstream for hashing right away. The proof-of-work (shares) SHOULD be cached until JDC receives an acknowledgement via SetCustomMiningJob.Success
.
We call this optimistic mining.
Under Full-Template mode:
mining_job_token
to JDC (AllocateMiningJobToken
/ AllocateMiningJobToken.Success
).DeclareMiningJob
to JDS (containing the txid
of every transaction in the template).txdata
(via ProvideMissingTransactions
).DeclareMiningJob.Success
.SetCustomMiningJob
, acknowledged via SetCustomMiningJob.Success
.Similarly to Coinbase-only, as soon as JDC has:
It SHOULD do optimistic mining by sending the jobs downstream for hashing right away. The proof-of-work (shares) SHOULD be cached until JDC receives an acknowledgement via SetCustomMiningJob.Success
.
The table below shows a comparison between the two Sv2 Job Declation Modes:
Coinbase-only | Full-Template | |
---|---|---|
knowledge of fee revenue | • JDC • Pool (while blind against tx data) | • JDC • Pool (while blind against tx data) • JDS (verifying against revealed tx data on behalf of Pool) |
knowledge of txdata on the template | • JDC | • JDC • JDS (on behalf of Pool) |
ability to broadcast mined block | • JDC | • JDC • JDS (on behalf of Pool) |
SetupConnection
Flags for Job Declaration ProtocolFlags usable in SetupConnection.flags
and SetupConnection.Error::flags
:
Field Name | Bit | Description |
---|---|---|
DECLARE_TX_DATA | 0 | JDC agrees to reveal the template's txdata via DeclareMiningJob and ProvideMissingTransactions . |
No flags are yet defined for use in SetupConnection.Success
.
AllocateMiningJobToken
(JDC -> JDS)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 AllocateMiningJobToken.Success
are valid.
Field Name | Data Type | Description |
---|---|---|
user_identifier | STR0_255 | Unconstrained sequence of bytes. Whatever is needed by the pool to identify/authenticate the client, e.g. "braiinstest". Additional restrictions can be imposed by the pool. It is highly recommended that UTF-8 encoding is used. |
request_id | U32 | Unique identifier for pairing the response |
AllocateMiningJobToken.Success
(Server -> Client)The Server MUST NOT change the value of coinbase_output_max_additional_size
in AllocateMiningJobToken.Success
messages unless required for changes to the pool’s 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.
Field Name | Data Type | Description |
---|---|---|
request_id | U32 | Unique identifier for pairing the response |
mining_job_token | B0_255 | Token that makes the client eligible for committing a mining job for approval/transaction declaration or for identifying custom mining job on mining connection. |
coinbase_output_max_additional_size | U32 | The maximum additional serialized bytes which the pool will add in coinbase transaction outputs. See discussion in the Template Distribution Protocol's CoinbaseOutputConstraints message for more details. |
coinbase_output_max_additional_sigops | U16 | The maximum additional sigops which the pool will add in coinbase transaction outputs. See discussion in the Template Distribution Protocol's CoinbaseOutputConstraints message for more details. |
coinbase_tx_outputs | B0_64K | Bitcoin transaction outputs added by the pool |
DeclareMiningJob
(Client -> Server)Only used in Full-Template mode.
A request sent by JDC that proposes a selected set of transactions to JDS.
Field Name | Data Type | Description |
---|---|---|
request_id | U32 | Unique identifier for pairing the response |
mining_job_token | B0_255 | Previously reserved mining job token received by AllocateMiningJobToken.Success |
version | U32 | Version header field. To be later modified by BIP320-consistent changes. |
prev_hash | U256 | Optional. Contains the chain tip that the template is based on. JDS SHOULD accept templates based on different tips, as long as they are on the best block height and don't contain double spends. |
coinbase_tx_prefix | B0_64K | Serialized bytes representing the initial part of the coinbase transaction (not including extranonce) |
coinbase_tx_suffix | B0_64K | Serialized bytes representing the final part of the coinbase transaction (after extranonce) |
tx_ids_list | SEQ0_64K[U256] | List of hashes of the transaction set contained in the template. JDS checks the list against its mempool and requests missing txs via ProvideMissingTransactions . Does not include the coinbase transaction (as there is no corresponding full data for it yet). |
excess_data | B0_64K | Extra data which the Pool may require to validate the work (as defined in the Template Distribution Protocol) |
DeclareMiningJob.Success
(Server -> Client)A response sent by JDS acknowledging some Custom Job declaration.
JDS MAY request txdata via ProvideMissingTransactions
before making this commitment.
Since JDS could be third party (not necessarily integrated to Pool), DeclareMiningJob.Success.new_mining_job_token
MAY carry a cryptographic commitment from JDS where:
DeclareMiningJob.mining_job_token
is validSetCustomMininingJob.mining_job_token = DeclareMiningJob.Success.new_mining_job_token
when declaring Custom Jobs to Pool as a way to prove it went through the Full-Template declaration processField Name | Data Type | Description |
---|---|---|
request_id | U32 | Identifier of the original request. |
new_mining_job_token | B0_255 | Unique custom work identifier. |
DeclareMiningJob.Error
(Server->Client)A response sent by JDS rejecting some Custom Job declaration.
This should be a trigger for fallback into some other Pool+JDS or solo mining.
Field Name | Data Type | Description |
---|---|---|
request_id | U32 | Identifier of the original request |
error_code | STR0_255 | |
error_details | B0_64K | Optional data providing further details to given error |
Possible error codes:
invalid-mining-job-token
invalid-job-param-value-{}
- {}
is replaced by a particular field name from DeclareMiningJob
messageProvideMissingTransactions
(Server->Client)Only used in Full-Template mode.
If DeclareMiningJob
includes some transactions that JDS's mempool has not yet seen, then JDS needs to request that JDC provides those missing ones.
Field Name | Data Type | Description |
---|---|---|
request_id | U32 | Identifier of the original AllocateMiningJobToken request |
unknown_tx_position_list | SEQ0_64K[U16] | A list of unrecognized transactions that need to be supplied by the Job Declarator in full. They are specified by their position in the original DeclareMiningJob message, 0-indexed not including the coinbase transaction transaction. |
ProvideMissingTransactions.Success
(Client->Server)This is a message to push transactions that the server did not recognize and requested them to be supplied in ProvideMissingTransactions
.
Field Name | Data Type | Description |
---|---|---|
request_id | U32 | Identifier of the original AllocateMiningJobToken request "" |
transaction_list | SEQ0_64K[B0_16M] | List of full transactions as requested by ProvideMissingTransactions, in the order they were requested in ProvideMissingTransactions |
PushSolution
(Client -> Server)Only used in Full-Template mode.
Sent by JDC as soon as a valid block is found, so that it can be propagated also by JDS.
In the meantime, the block is also transmitted to the network by JDC through the SubmitSolution
message under in Template Distribution Protocol.
In this way, a valid solution is immediately propagated on both client and server sides, decreasing the chance of the block being orphaned by the network.
Field Name | Data Type | Description |
---|---|---|
extranonce | B0_32 | Extranonce bytes which need to be added to coinbase to form a fully valid submission. (This is the full extranonce) |
prev hash | U256 | Hash of the last block |
nonce | U32 | Nonce leading to the hash being submitted |
ntime | U32 | The nTime field in the block header. |
nbits | U32 | The nBits field in the block header. |
version | U32 | Version header field. |