├── .github └── workflows │ └── dispatch-update.yml ├── 00-Abstract.md ├── 01-Motivation.md ├── 02-Design-Goals.md ├── 03-Protocol-Overview.md ├── 04-Protocol-Security.md ├── 05-Mining-Protocol.md ├── 06-Job-Declaration-Protocol.md ├── 07-Template-Distribution-Protocol.md ├── 08-Message-Types.md ├── 09-Extensions.md ├── 10-Discussion.md ├── License ├── BSD-3-Clause └── CC0-1.0 ├── README.md └── img ├── drawio ├── README.md ├── extended_extranonce.drawio.xml ├── extended_extranonce_layers.drawio.xml ├── extended_job.drawio.xml ├── jd_coinbase_mode.drawio.xml ├── jd_template_mode.drawio.xml └── standard_job.drawio.xml ├── extended_extranonce.png ├── extended_extranonce_layers.png ├── extended_job.png ├── jd_coinbase_mode.png ├── jd_template_mode.png └── standard_job.png /.github/workflows/dispatch-update.yml: -------------------------------------------------------------------------------- 1 | name: Dispatch update 2 | on: 3 | - push 4 | - workflow_dispatch 5 | jobs: 6 | dispatch: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Push to repo 10 | uses: peter-evans/repository-dispatch@v3 11 | with: 12 | token: ${{ secrets.PAT }} 13 | repository: stratum-mining/stratumprotocol.org 14 | event-type: update-submodule 15 | client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "module": "src/specification", "branch": "main"}' 16 | -------------------------------------------------------------------------------- /00-Abstract.md: -------------------------------------------------------------------------------- 1 | # 0. Abstract 2 | The current stratum protocol (v1) is used prevalently throughout the cryptocurrency mining industry today, but it was never intended nor designed to be an industry standard. 3 | 4 | This document proposes a new version of stratum protocol that addresses scaling and quality issues of the previous version, focusing on more efficient data transfers (i.e. distribution of mining jobs and result submissions) as well as increased security. 5 | 6 | Additionally, the redesigned protocol includes support for transaction selection by the miners themselves, as opposed to the current version of the protocol in which only the pool operators can determine a new block’s transaction set. 7 | 8 | There are some trade offs necessary to make the protocol scalable and relatively simple, which will be addressed in the detailed discussions below. 9 | 10 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC2119. 11 | 12 | We keep the name "Stratum" so that people will recognize that this is an upgrade of the widespread protocol version 1, with the hope that it will help gather support for the new version more easily. 13 | -------------------------------------------------------------------------------- /01-Motivation.md: -------------------------------------------------------------------------------- 1 | # 1. Motivation 2 | Stratum protocol v1 is JSON-based and lacks cryptographic authentication, making it slower, heavier, and less secure than it can be considering the alternatives available today. 3 | Given the cryptocurrency mining industry’s continued maturation and growth, it’s necessary to address v1’s deficiencies and move to a more efficient solution with a precise definition. 4 | 5 | One of the primary motivations of the new protocol is to reduce the amount and respective size of data transfers between miners, proxies, and pool operators to an absolute minimum. 6 | This will enable stratum servers to use the saved bandwidth for higher submission rates, thus yielding a reduced variance in hash rate (and in turn in miner payouts). 7 | 8 | To increase efficiency further, we will enable a simplified mode for end mining devices which completely eliminates the need for extranonce and Merkle path handling (i.e. any coinbase modification on downstream machines). 9 | This mode, called header-only mining, makes computations simpler for miners and work validation much lighter on the server side. 10 | Furthermore, header-only mining reduces the cost of future changes to the Bitcoin protocol, as mining firmware and protocols do not need to be upgraded in conjunction with full nodes. 11 | 12 | In terms of security, another important improvement to make is hardening the protocol against man-in-the-middle attacks by providing a way for mining devices to verify the integrity of the assigned mining jobs and other commands. 13 | 14 | Last but not the least, this protocol strives to allow downstream nodes to choose mining jobs and efficiently communicate them to upstream nodes to reduce power currently held by mining pools (block version selection, transaction selection). This should be possible without harming public pool business models or otherwise leading to more centralization in another area of the mining industry. 15 | -------------------------------------------------------------------------------- /02-Design-Goals.md: -------------------------------------------------------------------------------- 1 | # 2. Design Goals 2 | As there are numerous changes from the original Stratum v1 to v2, it may be helpful to briefly review some high-level design goals before getting into more detailed technical specifications: 3 | 4 | - Develop a binary protocol with a precise definition. 5 | Despite its simplicity, v1 was not a precisely defined protocol and ended up with multiple slightly different dialects. 6 | We don’t want any room for different interpretations of v2. 7 | 8 | - Make Stratum v2 logically similar to v1 whenever possible so that it’s easier to understand for people who are already familiar with the protocol. 9 | V1 is widely used not only in bitcoin mining, but also for mining various altcoins. 10 | 11 | - Remove as many issues caused by v1 as possible, based on substantial historical experience with it. 12 | - Remove explicit mining subscriptions (mining.subscribe) altogether. It was originally part of a more elaborate protocol and is no longer relevant. 13 | - Make extranonce subscription a native part of the protocol, not an extension. 14 | - Clean up difficulty controlling, which is really suboptimal v1. 15 | - Drop JSON. 16 | - Rework [BIP310](https://github.com/bitcoin/bips/blob/master/bip-0310.mediawiki) from scratch. 17 | 18 | - Allow different mining jobs on the same connection. 19 | 20 | - Avoid introducing any additional risks to pool operators and miners since that would make adoption of v2 very improbable. 21 | 22 | - Support version rolling natively. 23 | Bitcoin block header contains a version field whose bits (determined by [BIP320](https://github.com/bitcoin/bips/blob/master/bip-0320.mediawiki)) can be freely used to extend the hashing space for a miner. 24 | It is already a common tech, we want to include it as a first class citizen in the new protocol. 25 | 26 | - Support header-only mining (not touching the coinbase transaction) in as many situations as possible. 27 | Header-only mining should be easier and faster on mining devices, while also decreasing network traffic. 28 | 29 | - Dramatically reduce network traffic as well as client-side and server-side computational intensity, while still being able to send and receive hashing results rapidly for precise hash rate measurement (and therefore more precise mining reward distribution). 30 | 31 | - Allow miners to (optionally) choose the transaction set they mine through work declaration on some independent communication channel. 32 | At the same time, allow miners to choose how they utilize the available bits in the block header `nVersion` field, including both those bits which are used for mining (e.g. version-rolling AsicBoost) by [BIP320](https://github.com/bitcoin/bips/blob/master/bip-0320.mediawiki), and those bits used for [BIP8](https://github.com/bitcoin/bips/blob/master/bip-0008.mediawiki)/[BIP9](https://github.com/bitcoin/bips/tree/master/bip-0009) signaling. 33 | This mechanism must not interfere with the efficiency or security of the main mining protocol. 34 | - Use a separate communication channel for transaction selection so that it does not have a performance impact on the main mining/share communication, as well as can be run in three modes - disabled (i.e.pool does not yet support client work selection, to provide an easier transition from Stratum v1), client-push (to maximally utilize the client’s potential block-receive-latency differences from the pool), and client-declared (for pools worried about the potential of clients generating invalid block templates). The key issue to note is that both the client-push and client-declared approaches essentially function as client-push. The primary distinction between them lies in whether the pool validates the job proposed by the miner or not. 35 | 36 | - Put complexity on the pool side rather than the miner side whenever possible. 37 | Keep the protocol part to be implemented in embedded devices as small and easy as possible. 38 | Mining devices tend to be difficult to update. 39 | Any mistake in a firmware can be very costly. 40 | Either on miners side (non-functioning firmware) or pool side (necessity to implement various workarounds and hacks to support misbehaving firmware). 41 | 42 | - Allow for translation to and from the original protocol on a proxy level (e.g. different downstream devices) without the necessity to reconnect. 43 | 44 | - Reduce the stale ratio as much as possible through efficiency improvements. 45 | 46 | - Support/allow for `nTime` rolling in hardware in a safe and controlled way. 47 | 48 | - Simple support for vendor-specific extensions without polluting the protocol, or complicating pool implementation. 49 | 50 | - Optional telemetry data, allowing for easy monitoring of farms, without sacrificing the privacy of miners who wish to remain private. 51 | 52 | - Allow aggregation of connections to upstream nodes with an option to aggregate or not aggregate hash rate for target setting on those connections. 53 | 54 | - Ensure protocol design allows for devices to implement their own swarm algorithms. 55 | Mining devices can dynamically form small groups with an elected master that is responsible for aggregating connections towards upstream endpoint(s), acting as a local proxy. 56 | Aggregating connections and running multiple channels across a single TCP connection yields a better ratio of actual payload vs TCP/IP header sizes, as the share submission messages are in the range of 20 bytes. 57 | Still, to avoid overly complicating the protocol, automated negotiation of swarm/proxy detection is left to future extensions or vendor-specific messages. 58 | -------------------------------------------------------------------------------- /04-Protocol-Security.md: -------------------------------------------------------------------------------- 1 | # 4 Protocol Security 2 | 3 | Stratum V2 employs a type of encryption scheme called AEAD (authenticated encryption with associated data) to address the security aspects of all communication that occurs between clients and servers. 4 | This provides both confidentiality and integrity for the ciphertexts (i.e. encrypted data) being transferred, as well as providing integrity for associated data which is not encrypted. 5 | Prior to opening any Stratum V2 channels for mining, clients MUST first initiate the cryptographic session state that is used to encrypt all messages sent between themselves and servers. 6 | Thus, the cryptographic session state is independent of V2 messaging conventions. 7 | 8 | At the same time, this specification proposes optional use of a particular handshake protocol based on the **[Noise Protocol framework](https://noiseprotocol.org/noise.html)**. 9 | The client and server establish secure communication using Diffie-Hellman (DH) key agreement, as described in greater detail in the Authenticated Key Agreement Handshake section below. 10 | 11 | Using the handshake protocol to establish secured communication is **optional** on the local network (e.g. local mining devices talking to a local mining proxy). 12 | However, it is **mandatory** for remote access to the upstream nodes, whether they be pool mining services, job declarating services or template distributors. 13 | 14 | ## 4.1 Motivation for Authenticated Encryption with Associated Data 15 | 16 | Data transferred by the mining protocol MUST not provide adversary information that they can use to estimate the performance of any particular miner. Any intelligence about submitted shares can be directly converted to estimations of a miner’s earnings and can be associated with a particular username. This is unacceptable privacy leakage that needs to be addressed. 17 | 18 | ## 4.2 Motivation for Using the Noise Protocol Framework 19 | 20 | The reasons why Noise Protocol Framework has been chosen are listed below: 21 | 22 | - The Framework provides a formalism to describe the handshake protocol that can be verified. 23 | - A custom certificate scheme is now possible (no need to use x509 certificates). 24 | 25 | ## 4.3 Choice of cryptographic primitives 26 | 27 | Noise encrypted session requires Elliptic Curve (EC), Hash function (`HASH()`) and cipher function that supports AEAD mode[1](#reference-1). 28 | 29 | This specification describes mandatory cryptographic primitives that each implementation needs to support. 30 | These primitives are chosen so that Noise Encryption layer for Stratum V2 can be implemented using primitives already present in Bitcoin Core project at the time of writing this spec. 31 | 32 | ### 4.3.1 Elliptic Curve 33 | 34 | - Bitcoin's secp256k1 curve[2](#reference-2) is used 35 | - Schnorr signature scheme is used as described in BIP340[3](#reference-3) 36 | 37 | #### 4.3.1.1 EC point encoding remarks 38 | 39 | Secp256k1 curve points, i.e. Public Keys, are points with of X- and Y-coordinate. 40 | We serialize them in three different ways, only using the x-coordinate. 41 | 42 | 1. When signing or verifying a certificate, we use the 32 byte x-only 43 | encoding as defined in BIP 340.[3](#reference-3). 44 | 45 | 2. When sharing keys during the handshake, whether in plain text or encrypted, 46 | we use the 64 byte ElligatorSwift x-only encoding as defined in BIP324[7](#reference-7) under "ElligatorSwift encoding of curve X coordinates". This encoding uses 64-bytes instead of 32-bytes in order to produce a 47 | pseudo-random bytesteam. This is useful because the protocol handshake starts with 48 | each side sending their public key in plain text. Additionally the use of X-only 49 | ElligatorSwift ECDH removes the need to grind or negate private keys. 50 | 51 | 3. The Authority public key is base58-check encoded as described in 4.7. 52 | 53 | Digital signatures are serialized in 64-bytes like in BIP340[3](#reference-3). 54 | 55 | Key generation algorithm: 56 | 57 | 1. generate random 32-byte secret key `sk` 58 | 2. let `d' = int(sk)` 59 | 3. fail if `d = 0` or `d' > n` where `n` is group order of secp256k1 curve 60 | 4. compute `P` as `d'⋅G` 61 | 5. drop the Y coordinate and compute (u, t) = XElligatorSwift(P.x) 62 | 6. ellswift_pub = bytes(u) || bytes(t) 63 | 7. output keypair `(sk, ellswift_pub)` 64 | 65 | To perform X-only ECDH we use ellswift_ecdh_xonly(ellswift_theirs, d) as described in BIP324[7](#reference-7) under "Shared secret computation". The result is 32 bytes. 66 | 67 | No assumption is made about the parity of Y-coordinate. For the purpose of signing 68 | (e.g. certificate) and ECDH (handshake) it is _not_ necessary to "grind" 69 | the private key. The choosen algoritms take care of this by implicitly negatating 70 | the key, as if its public key had an even Y-coordinate. 71 | 72 | For more information refer to BIP340[3](#reference-3) and BIP324[7](#reference-7). 73 | 74 | ### 4.3.2 Hash function 75 | 76 | - `SHA-256()` is used as a `HASH()` 77 | 78 | ### 4.3.3 Cipher function for authenticated encryption 79 | 80 | - Cipher has methods for encryption and decryption for key `k`, nonce `n`, associated_data `ad`, plaintext `pt` and ciphertext `ct` 81 | - `ENCRYPT(k, n, ad, pt)` 82 | - `DECRYPT(k, n, ad, ct)` 83 | - ChaCha20 and Poly1305 in AEAD mode[4](#reference-4) (ChaChaPoly) is used as a default AEAD cipher 84 | 85 | ## 4.4 Cryptographic operations 86 | 87 | ### 4.4.1 CipherState object 88 | 89 | Object that encapsulates encryption and decryption operations with underlying AEAD mode cipher functions using 32-byte encryption key `k` and 8-byte nonce `n`. 90 | CipherState has the following interface: 91 | 92 | - `InitializeKey(key)`: 93 | - Sets `k = key`, `n = 0` 94 | - `EncryptWithAd(ad, plaintext)` 95 | - If `k` is non-empty, performs `ENCRYPT(k, n++, ad, plaintext)` on the underlying cipher function, otherwise returns `plaintext`. The `++` post-increment operator applied to `n` means: "use the current n value, then increment it". 96 | - Where `ENCRYPT` is an evaluation of `ChaCha20-Poly1305` (IETF variant) with the passed arguments, with nonce `n` encoded as 32 zero bits, followed by a _little-endian_ 64-bit value. Note: this follows the Noise Protocol convention, rather than our normal endian. 97 | - `DecryptWithAd(ad, ciphertext)` 98 | - If `k` is non-empty performs `DECRYPT(k, n++, ad, plaintext)` on the underlying cipher function, otherwise returns ciphertext. If an authentication failure occurs in `DECRYPT()` then `n` is not incremented and an error is signaled to the caller. 99 | - Where `DECRYPT` is an evaluation of `ChaCha20-Poly1305` (IETF variant) with the passed arguments, with nonce `n` encoded as 32 zero bits, followed by a _little-endian_ 64-bit value. 100 | 101 | ### 4.4.2 Handshake Operation 102 | 103 | Throughout the handshake process, each side maintains these variables: 104 | 105 | - `ck`: **chaining key**. Accumulated hash of all previous ECDH outputs. At the end of the handshake `ck` is used to derive encryption key `k`. 106 | - `h`: **handshake hash**. Accumulated hash of _all_ handshake data that has been sent and received so far during the handshake process 107 | - `e`, `re` **ephemeral keys**. Ephemeral key and remote party's ephemeral key, respectively. 108 | - `s`, `rs` **static keys**. Static key and remote party's static key, respectively. 109 | 110 | The following functions will also be referenced: 111 | 112 | - `generateKey()`: generates and returns a fresh `secp256k1` keypair 113 | 114 | - Where the object returned by `generateKey` has two attributes: 115 | - `.public_key`, which returns an abstract object representing the public key 116 | - `.private_key`, which represents the private key used to generate the public key 117 | - Where the public_key object also has a single method: 118 | - `.serializeEllSwift()` that outputs a 64-byte EllSwift encoded serialization of the X-coordinate of EC point (the Y-coordinate is ignored) 119 | 120 | - `a || b` denotes the concatenation of two byte strings `a` and `b` 121 | 122 | - `HMAC-HASH(key, data)` 123 | 124 | - Applies HMAC defined in `RFC 2104`[5](#reference-5) 125 | - In our case where the key is always 32 bytes, this reduces down to: 126 | - pad the key with zero bytes to fill the hash block (block length is 64 bytes in case of SHA-256): `k' = k || ` 127 | - calculate `temp = SHA-256((k' XOR ipad) || data)` where ipad is repeated 0x36 byte 128 | - output `SHA-256((k' XOR opad) || temp)` where opad is repeated 0x5c byte 129 | 130 | - `HKDF(chaining_key, input_key_material)`: a function defined in `RFC 5869`[6](#reference-6), evaluated with a zero-length `info` field and 2 `num_output` field: 131 | 132 | - Sets `temp_key = HMAC-HASH(chaining_key, input_key_material)` 133 | - Sets `output1 = HMAC-HASH(temp_key, byte(0x01))` 134 | - Sets `output2 = HMAC-HASH(temp_key, output1 || byte(0x02))` 135 | - Returns the pair `(output1, output2)` 136 | 137 | - `MixKey(input_key_material)`: Executes the following steps: 138 | 139 | - sets `(ck, temp_k) = HKDF(ck, input_key_material, 2)` 140 | - calls `InitializeKey(temp_k)` 141 | 142 | - `MixHash(data)`: Sets `h = HASH(h || data)` 143 | 144 | - `EncryptAndHash(plaintext)`: 145 | 146 | - If `k` is non-empty sets `ciphertext = EncryptWithAd(h, plaintext)`, otherwise `ciphertext = plaintext` 147 | - Calls `MixHash(ciphertext)` 148 | - returns `ciphertext` 149 | 150 | - `DecryptAndHash(ciphertext)`: 151 | 152 | - If `k` is non-empty sets `plaintext = DecryptWithAd(h, ciphertext)`, otherwise `plaintext = ciphertext` 153 | - Calls `MixHash(ciphertext)` 154 | - returns `plaintext` 155 | 156 | - `ECDH(k, rk)`: performs an Elliptic-Curve Diffie-Hellman operation 157 | using `k`, which is a valid `secp256k1` private key, and `rk`, which is a EllSwift 158 | encoded public key 159 | - The output is 32 bytes 160 | - It is a shortcut for performing operation `v2_ecdh` defined in BIP324[7](#reference-7): 161 | - let `k, ellswift_k` be key pair created by `ellswift_create()` function 162 | - let `rk` be remote public key **encoded as ellswift**. 163 | - let `initiator` be bool flag that is **true** if the party performing ECDH initiated the handshake 164 | - then `ECDH(k, rk) = v2_ecdh(k, ellswift_k, rk, initiator)` 165 | 166 | - `v2_ecdh(k, ellswift_k, rk, initiator)`: 167 | - let `ecdh_point_x32` = `ellswift_ecdh_xonly(rk, k)` 168 | - if initiator == true: 169 | - return `tagged_hash(ellswift_k, rk, ecdh_point_x32)` 170 | - else return `tagged_hash(rk, ellswift_k, ecdh_point_x32)` 171 | - **Note that the ecdh result is not commutative with respect to roles! Therefore the initiator flag is needed** 172 | 173 | - `ellswift_ecdh_xonly` - see BIP324[7](#reference-7) 174 | - `tagged_hash(a, b, c)`: 175 | - let tag = `SHA256("bip324_ellswift_xonly_ecdh")` 176 | - return `SHA256(concatenate(tag, tag, a, b, c))` 177 | 178 | 179 | 180 | 181 | ## 4.5 Authenticated Key Agreement Handshake 182 | 183 | The handshake chosen for the authenticated key exchange is an **`Noise_NX`** augmented by server authentication with simple 2 level public key infrastructure. 184 | 185 | The complete authenticated key agreement (`Noise NX`) is performed in three distinct steps (acts). 186 | 187 | 1. NX-handshake part 1: `-> e` 188 | 2. NX-handshake part 2: `<- e, ee, s, es, SIGNATURE_NOISE_MESSAGE` 189 | 3. Server authentication: Initiator validates authenticity of server using from `SIGNATURE_NOISE_MESSAGE` 190 | 191 | Should the decryption (i.e. authentication code validation) fail at any point, the session must be terminated. 192 | 193 | ### 4.5.1 Handshake Act 1: NX-handshake part 1 `-> e` 194 | 195 | Prior to starting first round of NX-handshake, both initiator and responder initializes handshake variables `h` (hash output), `ck` (chaining key) and `k` (encryption key): 196 | 197 | 1. **hash output** `h = HASH(protocolName)` 198 | 199 | - Since `protocolName` more than 32 bytes in length, apply `HASH` to it. 200 | - `protocolName` is official noise protocol name: `Noise_NX_Secp256k1+EllSwift_ChaChaPoly_SHA256` 201 | encoded as an ASCII string 202 | 203 | 2. **chaining key** `ck = h` 204 | 3. **hash output** `h = HASH(h)` 205 | 4. **encryption key** `k ` empty 206 | 207 | #### 4.5.1.1 Initiator 208 | 209 | Initiator generates ephemeral keypair and sends the public key to the responder: 210 | 211 | 1. initializes empty output buffer 212 | 2. generates ephemeral keypair `e`, appends `e.public_key.serializeEllSwift()` to the buffer (64 bytes plaintext EllSwift encoded public key) 213 | 3. calls `MixHash(e.public_key)` 214 | 4. calls `EncryptAndHash()` with empty payload and appends the ciphertext to the buffer (note that _k_ is empty at this point, so this effectively reduces down to `MixHash()` on empty data) 215 | 5. submits the buffer for sending to the responder in the following format 216 | 217 | ##### Ephemeral public key message: 218 | 219 | | Field name | Description | 220 | | ---------- | -------------------------------- | 221 | | PUBKEY | Initiator's ephemeral public key | 222 | 223 | Message length: 64 bytes 224 | 225 | #### 4.5.1.2 Responder 226 | 227 | 1. receives ephemeral public key message (64 bytes plaintext EllSwift encoded public key) 228 | 2. parses received public key as `re.public_key` 229 | 3. calls `MixHash(re.public_key)` 230 | 4. calls `DecryptAndHash()` on remaining bytes (i.e. on empty data with empty _k_, thus effectively only calls `MixHash()` on empty data) 231 | 232 | ### 4.5.2 Handshake Act 2: NX-handshake part 2 `<- e, ee, s, es, SIGNATURE_NOISE_MESSAGE` 233 | 234 | Responder provides its ephemeral, encrypted static public keys and encrypted `SIGNATURE_NOISE_MESSAGE` to the initiator, performs Elliptic-Curve Diffie-Hellman operations. 235 | 236 | ##### SIGNATURE_NOISE_MESSAGE 237 | 238 | | Field Name | Data Type | Description | 239 | | --------------- | --------- | -------------------------------------------------------------- | 240 | | version | U16 | Version of the certificate format | 241 | | valid_from | U32 | Validity start time (unix timestamp) | 242 | | not_valid_after | U32 | Signature is invalid after this point in time (unix timestamp) | 243 | | signature | SIGNATURE | Certificate signature | 244 | 245 | Length: 74 bytes 246 | 247 | #### 4.5.2.1 Responder 248 | 249 | 1. initializes empty output buffer 250 | 2. generates ephemeral keypair `e`, appends `e.public_key` to the buffer (64 bytes plaintext EllSwift encoded public key) 251 | 3. calls `MixHash(e.public_key)` 252 | 4. calls `MixKey(ECDH(e.private_key, re.public_key))` 253 | 5. appends `EncryptAndHash(s.public_key)` (64 bytes encrypted EllSwift encoded public key, 16 bytes MAC) 254 | 6. calls `MixKey(ECDH(s.private_key, re.public_key))` 255 | 7. appends `EncryptAndHash(SIGNATURE_NOISE_MESSAGE)` to the buffer 256 | 8. submits the buffer for sending to the initiator 257 | 9. return pair of CipherState objects, the first for encrypting transport messages from initiator to responder, and the second for messages in the other direction: 258 | 1. sets `temp_k1, temp_k2 = HKDF(ck, zerolen, 2)` 259 | 2. creates two new CipherState objects `c1` and `c2` 260 | 3. calls `c1.InitializeKey(temp_k1)` and `c2.InitializeKey(temp_k2)` 261 | 4. returns the pair `(c1, c2)` 262 | 263 | ##### Message format of NX-handshake part 2 264 | 265 | | Field name | Description | 266 | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | 267 | | PUBKEY | Responder's plaintext ephemeral public key | 268 | | PUBKEY | Responder's encrypted static public key | 269 | | MAC | Message authentication code for responder's static public key | 270 | | SIGNATURE_NOISE_MESSAGE | Signed message containing Responder's static key. Signature is issued by authority that is generally known to operate the server acting as the noise responder | 271 | | MAC | Message authentication code for SIGNATURE_NOISE_MESSAGE | 272 | 273 | Message length: 170 bytes 274 | 275 | #### 4.5.2.2 Initiator 276 | 277 | 1. receives NX-handshake part 2 message 278 | 2. interprets first 64 bytes as EllSwift encoded `re.public_key` 279 | 3. calls `MixHash(re.public_key)` 280 | 4. calls `MixKey(ECDH(e.private_key, re.public_key))` 281 | 5. decrypts next 80 bytes with `DecryptAndHash()` and stores the results as `rs.public_key` which is **server's static public key** (note that 64 bytes is the public key and 16 bytes is MAC) 282 | 6. calls `MixKey(ECDH(e.private_key, rs.public_key)` 283 | 7. decrypts next 90 bytes with `DecryptAndHash()` and deserialize plaintext into `SIGNATURE_NOISE_MESSAGE` (74 bytes data + 16 bytes MAC) 284 | 8. return pair of CipherState objects, the first for encrypting transport messages from initiator to responder, and the second for messages in the other direction: 285 | 1. sets `temp_k1, temp_k2 = HKDF(ck, zerolen, 2)` 286 | 2. creates two new CipherState objects `c1` and `c2` 287 | 3. calls `c1.InitializeKey(temp_k1)` and `c2.InitializeKey(temp_k2)` 288 | 4. returns the pair `(c1, c2)` 289 | 290 | ### 4.5.3 Server authentication 291 | 292 | During the handshake, initiator receives `SIGNATURE_NOISE_MESSAGE` and **server's static public key**. These parts make up a `CERTIFICATE` signed by an authority whose public key is generally known (for example from pool's website). Initiator confirms the identity of the server by verifying the signature in the certificate. 293 | 294 | ##### CERTIFICATE 295 | 296 | | Field Name | Data Type | Description | Signed field | 297 | | -------------------- | --------- | -------------------------------------------------------------- | ------------ | 298 | | version | U16 | Version of the certificate format | YES | 299 | | valid_from | U32 | Validity start time (unix timestamp) | YES | 300 | | not_valid_after | U32 | Signature is invalid after this point in time (unix timestamp) | YES | 301 | | server_public_key | PUBKEY | Server's static public key that was used during NX handshake | YES | 302 | | authority_public_key | PUBKEY | Certificate authority's public key that signed this message | NO | 303 | | signature | SIGNATURE | Signature over the serialized fields marked for signing | NO | 304 | 305 | This message is not sent directly. Instead, it is constructed from SIGNATURE_NOISE_MESSAGE and server's static public 306 | key that are sent during the handshake process 307 | 308 | The PUBKEY fields are encoded using only their 32 byte x-coordinate and _not_ with 309 | EllSwift. For the purpose of generating and verifying the certificate, the 64 byte 310 | EllSwift encoded server_public_key can be decoded to its 32 byte x-coordinate. 311 | 312 | #### 4.5.3.1 Signature structure 313 | 314 | Schnorr signature with _key prefixing_ is used[3](#reference-3) 315 | 316 | signature is constructed for 317 | 318 | - message `m`, where `m` is `HASH` of the serialized fields of the `CERTIFICATE` that are marked for signing, i.e. `m = SHA-256(version || valid_from || not_valid_after || server_public_key)` 319 | - public key `P` that is Certificate Authority 320 | 321 | Signature itself is concatenation of an EC point `R` and an integer `s` (note that each item is serialized as 32 bytes array) for which identity `s⋅G = R + HASH(R || P || m)⋅P` holds. 322 | 323 | ## 4.6 Encrypted stratum message framing 324 | 325 | After handshake process is finished, both initiator and responder have CipherState objects for encryption and decryption and after initiator validated server's identity, any subsequent traffic is encrypted and decrypted with `EncryptWithAd()` and `DecryptWithAd()` methods of the respective CipherState objects with zero-length associated data. 326 | 327 | Maximum transport message length (ciphertext) is for noise protocol message 65535 bytes. 328 | 329 | Since Stratum Message Frame consists of 330 | - fixed length message header: 6 bytes 331 | - variable length serialized stratum message 332 | 333 | Stratum Message header and stratum message payload are processed separately. 334 | 335 | #### Encrypting stratum message 336 | 1. serialize stratum message into a plaintext binary string (payload) 337 | 2. prepare the frame header for the Stratum message `message_length` is the length of the plaintext payload. 338 | 3. encrypt and concatenate serialized header and payload: 339 | 4. `EncryptWithAd([], header)` - 22 bytes 340 | 5. `EncryptWithAd([], payload)` - variable length encrypted message 341 | 4. concatenate resulting header and payload ciphertext 342 | 343 | - Note: The `message_length` (payload_length) in the encrypted Stratum message header always reflects the plaintext payload size. The size of the encrypted payload is implicitly understood to be message_length + MAC size for each block. This simplifies the decryption process and ensures clarity in interpreting frame data. 344 | 345 | #### Decrypting stratum message 346 | 1. read exactly 22 bytes and decrypt into stratum frame or fail 347 | 2.The value `frame.message_length` should first be converted to the ciphertext length, and then that amount of data should be read and decrypted into plaintext payload. If decryption fails, the process stops 348 | 3. deserialize plaintext payload into stratum message given by `frame.extension_type` and `frame.message_type` or fail 349 | 350 | 351 | *converting plaintext length to ciphertext length: 352 | ```c 353 | #define MAX_CT_LEN 65535 354 | #define MAC_LEN 16 355 | #define MAX_PT_LEN (MAX_CT_LEN - MAC_LEN) 356 | 357 | uint pt_len_to_ct_len(uint pt_len) { 358 | uint remainder; 359 | remainder = pt_len % MAX_PT_LEN; 360 | if (remainder > 0) { 361 | remainder += MAC_LEN; 362 | } 363 | return pt_len / MAX_PT_LEN * MAX_CT_LEN + remainder; 364 | } 365 | ``` 366 | 367 | 368 | #### Encrypted stratum message frame layout 369 | ``` 370 | +--------------------------------------------------+-------------------------------------------------------------------+ 371 | | Extended noise header | Encrypted stratum-message payload | 372 | +--------------------------------------------------+-------------------+-------------------+---------------------------+ 373 | | Header AEAD ciphertext | Noise block 1 | Noise block 2 | Last Noise block | 374 | | 22 Bytes | 65535 Bytes | 65535 Bytes | 17 - 65535 Bytes | 375 | +----------------------------------------+---------+-----------+-------+-----------+-------+---------------+-----------+ 376 | | Encrypted Stratum message Header | MAC | ct_pld_1 | MAC_1 | ct_pld_2 | MAC_2 | ct_pld_rest | MAC_rest | 377 | | 6 Bytes | 16 B | 65519 B | 16 B | 65519 B | 16 B | 1 - 65519 B | 16 Bytes | 378 | +================+==========+============+=========+===========+=======+===========+=======+===============+===========+ 379 | | extension_type | msg_type | pld_length | | 380 | | U16 | U8 | U24 | ing> | 65519 B | ing> | 65519 B | ing> | 1 - 65519 B | | 381 | +----------------+----------+------------+---------+-------------------------------------------------------------------+ 382 | 383 | The `pld_length` field in the Encrypted Stratum message Header now consistently represents the plaintext length of the payload. 384 | Serialized stratum-v2 body (payload) is split into 65519-byte chunks and encrypted to form 65535-bytes AEAD ciphertexts, 385 | where `ct_pld_N` is the N-th ciphertext block of payload and `pt_pld_N` is the N-th plaintext block of payload. 386 | ``` 387 | 388 | ## 4.7 URL Scheme and Pool Authority Key 389 | 390 | Downstream nodes that want to use the above outlined security scheme need to have configured the **Pool Authority Public Key** of the pool that they intend to connect to. It is provided by the target pool and communicated to its users via a trusted channel. 391 | At least, it can be published on the pool's public website. 392 | 393 | The key can be embedded into the mining URL as part of the path. 394 | 395 | Authority Public key is [base58-check](https://en.bitcoin.it/wiki/Base58Check_encoding) encoded 32-byte secp256k1 public key (with implicit Y coordinate) prefixed with a LE u16 version prefix, currently `[1, 0]`: 396 | 397 | | [1, 0] | 2 bytes prefix | 398 | | ------ | -------------- | 399 | | PUBKEY | 32 bytes authority public key | 400 | 401 | URL example: 402 | 403 | ``` 404 | 405 | stratum2+tcp://thepool.com:34254/9bXiEd8boQVhq7WddEcERUL5tyyJVFYdU8th3HfbNXK3Yw6GRXh 406 | 407 | ``` 408 | 409 | ### 4.7.1 Test vector: 410 | 411 | ``` 412 | 413 | raw_ca_public_key = [118, 99, 112, 0, 151, 156, 28, 17, 175, 12, 48, 11, 205, 140, 127, 228, 134, 16, 252, 233, 185, 193, 30, 61, 174, 227, 90, 224, 176, 138, 116, 85] 414 | prefixed_base58check = "9bXiEd8boQVhq7WddEcERUL5tyyJVFYdU8th3HfbNXK3Yw6GRXh" 415 | 416 | ``` 417 | 418 | ## 4.8 References 419 | 420 | 1. https://web.cs.ucdavis.edu/~rogaway/papers/ad.pdf 421 | 2. https://www.secg.org/sec2-v2.pdf 422 | 3. https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki 423 | 4. https://tools.ietf.org/html/rfc8439 424 | 5. https://www.ietf.org/rfc/rfc2104.txt 425 | 6. https://tools.ietf.org/html/rfc5869 426 | 7. https://github.com/bitcoin/bips/blob/master/bip-0324.mediawiki 427 | ``` 428 | -------------------------------------------------------------------------------- /06-Job-Declaration-Protocol.md: -------------------------------------------------------------------------------- 1 | # 6. Job Declaration Protocol 2 | 3 | The Job Declaration Protocol is used to coordinate the creation of custom work, avoiding scenarios where Pools are unilaterally imposing work on miners. 4 | 5 | Pools that opt into this protocol are only responsible for accounting shares and distributing rewards. 6 | 7 | This is a key feature of Stratum V2 that improves Bitcoin decentralization. 8 | 9 | ## 6.1 Job Declarator Server 10 | 11 | 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. 12 | 13 | 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. 14 | 15 | It is responsible for: 16 | - Allocating tokens that JDC will use to declare Custom Jobs. 17 | - Acknowledging declaration of Custom Jobs associated with specific allocated tokens. 18 | - Maintaining an internal mempool (via RPCs (or similar) to a Bitcoin Node). 19 | - Requesting identification for transactions on some declared Custom Job. 20 | - Requesting missing transactions on some declared Custom Job. 21 | - Publishing valid block submissions received from JDC. 22 | 23 | ## 6.2 Job Declarator Client 24 | 25 | The Job Declarator Client (JDC) is deployed on the miner side. 26 | 27 | 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. 28 | 29 | It is responsible for: 30 | - Receiving Templates from the Template Provider (via Template Distribution Protocol). 31 | - Declaring Custom Jobs to JDS (via Job Declaration Protocol under Full-Template mode). 32 | - Notifying declared Custom Jobs to Pool (via Mining Protocol). 33 | - Receiving Shares from downstream Mining Devices working on Custom Jobs (via Mining Protocol). 34 | - Submitting Shares for Custom Jobs to Pool. 35 | - Publishing valid blocks found by downstream Mining Devices (both to Template Provider (TP) and JDS). 36 | 37 | Additionally, if: 38 | - JDS fails to respond with an `AllocateMiningJobToken.Success` in a reasonable time. 39 | - JDS rejects some Custom Job declaration via `DeclareMiningJob.Error`. 40 | - Pool rejects valid shares under a Custom Job that was previously acknowledged via `SetCustomMiningJob.Success` and/or `DeclareMiningJob.Success`. 41 | 42 | JDC is also responsible for switching to a new Pool+JDS (or solo mining as a last resort). 43 | 44 | 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. 45 | 46 | ## 6.3 Job Declaration Modes 47 | 48 | ### 6.3.1 Coinbase-only Mode 49 | 50 | Under Coinbase-only mode: 51 | - JDS allocates `mining_job_token` to JDC (`AllocateMiningJobToken` / `AllocateMiningJobToken.Success`). 52 | - Pool evaluates fee revenue of some proposed work (uniquely identified by `mining_job_token`) by looking at the coinbase. 53 | - JDC never reveals the tx data contained in the template (in other words, the transaction set). 54 | - proposed work is acknowledged as valid by Pool via `SetCustomMiningJob.Success`. 55 | - the `DeclareMiningJob` message is never used. 56 | - if a valid block is found, JDC propagates it unilaterally. 57 | 58 | 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. 59 | 60 | 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: 61 | - the template actually has a different fee revenue. 62 | - the template has invalid transactions. 63 | 64 | This potential attack vector is in many ways identical to block withholding and defenses against block withholding generally apply. 65 | 66 | 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. 67 | 68 | ![](./img/jd_coinbase_mode.png) 69 | 70 | As soon as JDC has: 71 | - a token (allocated by JDS), so it can use it to identify some unique work that it wants to advertise 72 | - a new template 73 | 74 | 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`. 75 | 76 | We call this **optimistic mining**. 77 | 78 | ### 6.3.2 Full-Template Mode 79 | 80 | Under Full-Template mode: 81 | - JDS allocates `mining_job_token` to JDC (`AllocateMiningJobToken` / `AllocateMiningJobToken.Success`). 82 | - JDC sends `DeclareMiningJob` to JDS (containing the `txid` of every transaction in the template). 83 | - JDS could potentially request for JDC to reveal `txdata` (via `ProvideMissingTransactions`). 84 | - JDS acknowledges proposed work via `DeclareMiningJob.Success`. 85 | - JDC notifies work to Pool via `SetCustomMiningJob`, acknowledged via `SetCustomMiningJob.Success`. 86 | - if a valid block is found, both JDC and JDS propagate it. 87 | 88 | ![](./img/jd_template_mode.png) 89 | 90 | Similarly to Coinbase-only, as soon as JDC has: 91 | - a token (allocated by JDS), so it can use it to identify some unique work that it wants to advertise 92 | - a new template 93 | 94 | 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`. 95 | 96 | ### 6.3.3 Coinbase-only vs Full-Template 97 | 98 | The table below shows a comparison between the two Sv2 Job Declation Modes: 99 | 100 | | | Coinbase-only | Full-Template | 101 | |-------------------------------------|-|-| 102 | | 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) | 103 | | knowledge of txdata on the template | • JDC | • JDC
• JDS (on behalf of Pool) | 104 | | ability to broadcast mined block | • JDC | • JDC
• JDS (on behalf of Pool) | 105 | 106 | ## 6.4 Job Declaration Protocol Messages 107 | 108 | ### 6.4.1 `SetupConnection` Flags for Job Declaration Protocol 109 | 110 | Flags usable in `SetupConnection.flags` and `SetupConnection.Error::flags`: 111 | 112 | | Field Name | Bit | Description | 113 | | ------------------------- | --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 114 | | DECLARE_TX_DATA | 0 | JDC agrees to reveal the template's txdata via `DeclareMiningJob` and `ProvideMissingTransactions`. | 115 | 116 | No flags are yet defined for use in `SetupConnection.Success`. 117 | 118 | ### 6.4.2 `AllocateMiningJobToken` (JDC -> JDS) 119 | 120 | A request to get an identifier for a future-submitted mining job. 121 | 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. 122 | 123 | | Field Name | Data Type | Description | 124 | | --------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 125 | | 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. | 126 | | request_id | U32 | Unique identifier for pairing the response | 127 | 128 | ### 6.4.3 `AllocateMiningJobToken.Success` (Server -> Client) 129 | 130 | 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. 131 | 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. 132 | 133 | | Field Name | Data Type | Description | 134 | | ----------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 135 | | request_id | U32 | Unique identifier for pairing the response | 136 | | 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. | 137 | | coinbase_tx_outputs | B0_64K | Serialized Bitcoin transaction outputs added by the pool. | 138 | 139 | The following rules apply to `AllocateMiningJobToken.Success.coinbase_tx_outputs`: 140 | - JDS MUST reserve the **first** output with a locking script where the pool payout will go. While this output is initally set with a 0 amount of sats, this convention designates this locking script as the **pool payout output**. 141 | - JDS MAY add more 0 value outputs in addition to the pool payout output. 142 | 143 | Once JDC receives `AllocateMiningJobToken.Success`, the following rules apply to the subsequent `DeclareMiningJob.coinbase_tx_suffix` (if under Full-Template mode) and `SetCustomMiningJob.coinbase_tx_outputs` (under both Full-Template and Coinbase-only modes) message fields: 144 | - JDC MUST allocate sats into the pool payout output in order to qualify for pooled mining rewards. JDS and Pool SHOULD reject custom jobs that fail to do so. 145 | - JDC MAY add more 0 value outputs in addition to the ones established by JDS. 146 | - JDC MAY add more non-0 value outputs in addition to the ones established by JDS. In doing so, the template revenue is not fully allocated to the designated pool payout output, so Pool MAY pay proportionally smaller rewards for this job. 147 | - JDC MAY arbitrarily reorder the outputs to something different from the original ordering of `AllocateMiningJobToken.Success.coinbase_tx_outputs`. 148 | - Under Full-Template mode, the order of the outputs under `DeclareMiningJob.coinbase_tx_suffix` and `SetCustomMiningJob.coinbase_tx_outputs` MUST remain the same, even if they differ from the original `AllocateMiningJobToken.Success.coinbase_tx_outputs`. 149 | 150 | In summary, the pool payout goes to one single output (standardized as the first output of `AllocateMiningJobToken.Success.coinbase_tx_outputs`), and JDC is free to add more outputs and shuffle them under any arbitrary ordering scheme. 151 | 152 | Here's a few examples for clarification: 153 | 154 | #### Example A 155 | 156 | Example A illustrates JDS and JDC adding arbitrary 0 valued outputs in addition to the pool payout output. 157 | 158 | Outputs in `AllocateMiningJobToken.Success.coinbase_tx_outputs`: 159 | | Script | Amount (sats) | Description | 160 | |-------------|------------------|-------------------------------------------------------------------| 161 | | P2WPKH | 0 | pool payout output | 162 | | OP_RETURN X | 0 | arbitrary unspendable output imposed by JDS | 163 | | OP_RETURN Y | 0 | arbitrary unspendable output imposed by JDS | 164 | 165 | Outputs in `DeclareMiningJob.coinbase_tx_suffix` and/or `SetCustomMiningJob.coinbase_tx_outputs`: 166 | | Script | Amount (sats) | Description | 167 | |-------------|------------------|-------------------------------------------------------------------| 168 | | OP_RETURN Z | 0 | arbitrary unspendable output added by JDC | 169 | | P2WPKH | template_revenue | pool payout output | 170 | | OP_RETURN X | 0 | arbitrary unspendable output imposed by JDS | 171 | | OP_RETURN Y | 0 | arbitrary unspendable output imposed by JDS | 172 | | OP_RETURN W | 0 | SegWit commitment added by Template Provider | 173 | 174 | 175 | #### Example B 176 | 177 | Example B illustrates JDC allocating part of the template revenue to some outputs that are not the pool payout. Here, the Pool MAY pay proportionally smaller rewards for this custom job, since the template revenue is not fully allocated to the pool payout output. 178 | 179 | Ordered outputs in `AllocateMiningJobToken.Success.coinbase_tx_outputs`: 180 | | Script | Amount (sats) | Description | 181 | |-----------|------------------|-----------------------------------------------------| 182 | | P2TR | 0 | pool payout output | 183 | 184 | Ordered outputs in `DeclareMiningJob.coinbase_tx_suffix` and/or `SetCustomMiningJob.coinbase_tx_outputs`: 185 | | Script | Amount (sats) | Description | 186 | |-----------|--------------------------|-----------------------------------------------------| 187 | | P2PKH | X | arbitrary output added by JDC | 188 | | P2WSH | Y | arbitrary output added by JDC | 189 | | P2TR | template_revenue - X - Y | pool payout output | 190 | | OP_RETURN | 0 | SegWit commitment added by Template Provider | 191 | 192 | 193 | ### 6.4.4 `DeclareMiningJob` (Client -> Server) 194 | 195 | Only used in Full-Template mode. 196 | 197 | A request sent by JDC that proposes a selected set of transactions to JDS. 198 | 199 | | Field Name | Data Type | Description | 200 | | --------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 201 | | request_id | U32 | Unique identifier for pairing the response | 202 | | mining_job_token | B0_255 | Previously reserved mining job token received by AllocateMiningJobToken.Success | 203 | | version | U32 | Version header field. To be later modified by BIP320-consistent changes. | 204 | | 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. | 205 | | coinbase_tx_prefix | B0_64K | Serialized bytes representing the initial part of the coinbase transaction (not including extranonce) | 206 | | coinbase_tx_suffix | B0_64K | Serialized bytes representing the final part of the coinbase transaction (after extranonce) | 207 | | 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). | 208 | | excess_data | B0_64K | Extra data which the Pool may require to validate the work (as defined in the Template Distribution Protocol) | 209 | 210 | ### 6.4.5 `DeclareMiningJob.Success` (Server -> Client) 211 | 212 | A response sent by JDS acknowledging some Custom Job declaration. 213 | 214 | JDS MAY request txdata via `ProvideMissingTransactions` before making this commitment. 215 | 216 | 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: 217 | - JDS acknowledges that the template declared under `DeclareMiningJob.mining_job_token` is valid 218 | - it signals to JDC that it should use `SetCustomMininingJob.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 process 219 | 220 | | Field Name | Data Type | Description | 221 | | -------------------- | --------- |-------------------------------------| 222 | | request_id | U32 | Identifier of the original request. | 223 | | new_mining_job_token | B0_255 | Unique custom work identifier. | 224 | 225 | ### 6.4.6 `DeclareMiningJob.Error` (Server->Client) 226 | 227 | A response sent by JDS rejecting some Custom Job declaration. 228 | 229 | This should be a trigger for fallback into some other Pool+JDS or solo mining. 230 | 231 | | Field Name | Data Type | Description | 232 | | ------------- | --------- | ------------------------------------------------------ | 233 | | request_id | U32 | Identifier of the original request | 234 | | error_code | STR0_255 | | 235 | | error_details | B0_64K | Optional data providing further details to given error | 236 | 237 | Possible error codes: 238 | 239 | - `invalid-mining-job-token` 240 | - `invalid-job-param-value-{}` - `{}` is replaced by a particular field name from `DeclareMiningJob` message 241 | 242 | ### 6.4.7 `ProvideMissingTransactions` (Server->Client) 243 | 244 | Only used in Full-Template mode. 245 | 246 | If `DeclareMiningJob` includes some transactions that JDS's mempool has not yet seen, then JDS needs to request that JDC provides those missing ones. 247 | 248 | | Field Name | Data Type | Description | 249 | | ------------------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 250 | | request_id | U32 | Identifier of the original AllocateMiningJobToken request | 251 | | 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. | 252 | 253 | ### 6.4.8 `ProvideMissingTransactions.Success` (Client->Server) 254 | This is a message to push transactions that the server did not recognize and requested them to be supplied in `ProvideMissingTransactions`. 255 | 256 | | Field Name | Data Type | Description | 257 | | ---------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ | 258 | | request_id | U32 | Identifier of the original AllocateMiningJobToken request ""| 259 | | transaction_list | SEQ0_64K[B0_16M] | List of full transactions as requested by ProvideMissingTransactions, in the order they were requested in ProvideMissingTransactions | 260 | 261 | ### 6.4.9 `PushSolution` (Client -> Server) 262 | 263 | Only used in Full-Template mode. 264 | 265 | Sent by JDC as soon as a valid block is found, so that it can be propagated also by JDS. 266 | 267 | In the meantime, the block is also transmitted to the network by JDC through the `SubmitSolution` message under in Template Distribution Protocol. 268 | 269 | 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. 270 | 271 | | Field Name | Data Type | Description | 272 | | --------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 273 | | extranonce | B0_32 | Extranonce bytes which need to be added to coinbase to form a fully valid submission. (This is the full extranonce) | 274 | | prev hash | U256 | Hash of the last block | 275 | | nonce | U32 | Nonce leading to the hash being submitted | 276 | | ntime | U32 | The nTime field in the block header. | 277 | | nbits | U32 | The nBits field in the block header. | 278 | | version | U32 | Version header field. | 279 | -------------------------------------------------------------------------------- /07-Template-Distribution-Protocol.md: -------------------------------------------------------------------------------- 1 | # 7. Template Distribution Protocol 2 | 3 | The Template Distribution protocol is used to receive updates of the block template to use in mining the next block. 4 | It effectively replaces [BIP 22](https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki) and [BIP 23](https://github.com/bitcoin/bips/blob/master/bip-0023.mediawiki) (`getblocktemplate`) and provides a much more efficient API which allows Bitcoin Core (or some other full node software) to push template updates at more appropriate times as well as provide a template which may be mined on quickly for the block-after-next. 5 | While not recommended, the template update protocol can be a remote server, and is thus authenticated and signed in the same way as all other protocols (using the same SetupConnection handshake). 6 | 7 | Like the Job Declaration and Job Distribution protocols, all Template Distribution messages have the `channel_msg` bit unset, and there is no concept of channels. 8 | After the initial common handshake, the client MUST immediately send a `CoinbaseOutputConstraints` message to indicate the space it requires for coinbase output addition, to which the server MUST immediately reply with the current best block template it has available to the client. 9 | Thereafter, the server SHOULD push new block templates to the client whenever the total fee in the current block template increases materially, and MUST send updated block templates whenever it learns of a new block. 10 | 11 | Template Providers MUST attempt to broadcast blocks which are mined using work they provided, and thus MUST track the work which they provided to clients. 12 | 13 | ## 7.1 `CoinbaseOutputConstraints` (Client -> Server) 14 | 15 | Ultimately, the pool is responsible for adding coinbase transaction outputs for payouts and other uses, and thus the Template Provider will need to consider this additional block size, and sigops when selecting transactions for inclusion in a block (to not create an invalid, oversized block). 16 | Thus, this message is used to indicate that some additional space and sigops in the block/coinbase transaction be reserved for the pool’s use (while always assuming the pool will use the entirety of available coinbase space and sigops). 17 | 18 | The Job Declarator MUST discover the maximum serialized size of the additional outputs and sigops which will be added by the pool(s) it intends to use this work. 19 | It then MUST communicate it to the Template Provider via this message. 20 | The Template Provider MUST NOT provide `NewMiningJob` messages which would represent consensus-invalid blocks once this additional size and sigops — along with a maximally-sized (100 byte) coinbase script field — is added. 21 | Further, the Template Provider MUST consider the maximum additional bytes required in the output count variable-length integer in the coinbase transaction when complying with the size limits. 22 | Current sigops limit per block in bitcoin is 80_000. We are not aware of any use cases where 23 | coinbase have more the 65_535 so coinbase_output_max_sigops is an U16. Note that taproot outputs consume 0 sigops. 24 | 25 | | Field Name | Data Type | Description | 26 | | ----------------------------------- | --------- | ----------------------------------------------------------------------------------------------- | 27 | | coinbase_output_max_additional_size | U32 | The maximum additional serialized bytes which the pool will add in coinbase transaction outputs | 28 | | coinbase_output_max_additional_sigops | U16 | The maximum additional sigops which the pool will add in coinbase transaction outputs | 29 | 30 | ## 7.2 `NewTemplate` (Server -> Client) 31 | 32 | The primary template-providing function. Note that the `coinbase_tx_outputs` bytes will appear as is at the end of the coinbase transaction. 33 | 34 | | Field Name | Data Type | Description | 35 | | --------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 36 | | template_id | U64 | Server’s identification of the template. Strictly increasing, the current UNIX time may be used in place of an ID | 37 | | future_template | BOOL | True if the template is intended for future SetNewPrevHash message sent on the channel. If False, the job relates to the last sent SetNewPrevHash message on the channel and the miner should start to work on the job immediately. | 38 | | version | U32 | Valid header version field that reflects the current network consensus. The general purpose bits (as specified in BIP320) can be freely manipulated by the downstream node. The downstream node MUST NOT rely on the upstream node to set the BIP320 bits to any particular value. | 39 | | coinbase_tx_version | U32 | The coinbase transaction nVersion field | 40 | | coinbase_prefix | B0_255 | 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 | 41 | | coinbase_tx_input_sequence | U32 | The coinbase transaction input's nSequence field | 42 | | coinbase_tx_value_remaining | U64 | The value, in satoshis, available for spending in coinbase outputs added by the client. Includes both transaction fees and block subsidy. | 43 | | coinbase_tx_outputs_count | U32 | The number of transaction outputs included in coinbase_tx_outputs | 44 | | coinbase_tx_outputs | B0_64K | Bitcoin transaction outputs to be included as the last outputs in the coinbase transaction | 45 | | coinbase_tx_locktime | U32 | The locktime field in the coinbase transaction | 46 | | merkle_path | SEQ0_255[U256] | Merkle path hashes ordered from deepest | 47 | 48 | ## 7.3 `SetNewPrevHash` (Server -> Client) 49 | 50 | Upon successful validation of a new best block, the server MUST immediately provide a `SetNewPrevHash` message. 51 | If a `NewMiningJob` message has previously been sent with an empty `min_ntime`, which is valid work based on the `prev_hash` contained in this message, the `template_id` field SHOULD be set to the `job_id` present in that `NewTemplate` message indicating the client MUST begin mining on that template as soon as possible. 52 | 53 | TODO: Define how many previous works the client has to track (2? 3?), and require that the server reference one of those in `SetNewPrevHash`. 54 | 55 | | Field Name | Data Type | Description | 56 | | ---------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 57 | | template_id | U64 | template_id referenced in a previous NewTemplate message | 58 | | prev_hash | U256 | Previous block’s hash, as it must appear in the next block's header | 59 | | header_timestamp | U32 | The nTime field in the block header at which the client should start (usually current time). This is NOT the minimum valid nTime value. | 60 | | nBits | U32 | Block header field | 61 | | target | U256 | The maximum double-SHA256 hash value which would represent a valid block. Note that this may be lower than the target implied by nBits in several cases, including weak-block based block propagation. | 62 | 63 | ## 7.4 `RequestTransactionData` (Client -> Server) 64 | 65 | A request sent by the Job Declarator to the Template Provider which requests the set of transaction data for all transactions (excluding the coinbase transaction) included in a block, as well as any additional data which may be required by the Pool to validate the work. 66 | 67 | | Field Name | Data Type | Description | 68 | | ----------- | --------- | ------------------------------------------------------ | 69 | | template_id | U64 | The template_id corresponding to a NewTemplate message | 70 | 71 | ## 7.5 `RequestTransactionData.Success` (Server->Client) 72 | 73 | A response to `RequestTransactionData` which contains the set of full transaction data and excess data required for validation. 74 | For practical purposes, the excess data is usually the SegWit commitment, however the Job Declarator MUST NOT parse or interpret the excess data in any way. 75 | Note that the transaction data MUST be treated as opaque blobs and MUST include any SegWit or other data which the Pool may require to verify the transaction. 76 | For practical purposes, the transaction data is likely the witness-encoded transaction today. 77 | However, to ensure backward compatibility, the transaction data MAY be encoded in a way that is different from the consensus serialization of Bitcoin transactions. 78 | 79 | Ultimately, having some method of negotiating the specific format of transactions between the Template Provider and the Pool’s Template verification node would be overly burdensome, thus the following requirements are made explicit. 80 | The `RequestTransactionData.Success` sender MUST ensure that the data is provided in a forwards- and backwards-compatible way to ensure the end receiver of the data can interpret it, even in the face of new, consensus-optional data. 81 | This allows significantly more flexibility on both the `RequestTransactionData.Success`-generating and -interpreting sides during upgrades, at the cost of breaking some potential optimizations which would require version negotiation to provide support for previous versions. 82 | For practical purposes, and as a non-normative suggested implementation for Bitcoin Core, this implies that additional consensus-optional data be appended at the end of transaction data. 83 | It will simply be ignored by versions which do not understand it. 84 | 85 | To work around the limitation of not being able to negotiate e.g. a transaction compression scheme, the format of the opaque data in `RequestTransactionData.Success` messages MAY be changed in non-compatible ways at the time a fork activates, given sufficient time from code-release to activation (as any sane fork would have to have) and there being some in-Template Negotiation Protocol signaling of support for the new fork (e.g. for soft-forks activated using [BIP 9](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki)). 86 | 87 | | Field Name | Data Type | Description | 88 | | ---------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ | 89 | | template_id | U64 | The template_id corresponding to a NewTemplate/RequestTransactionData message | 90 | | excess_data | B0_64K | Extra data which the Pool may require to validate the work | 91 | | transaction_list | SEQ0_64K[B0_16M] | List of full transactions as requested by ProvideMissingTransactions, in the order they were requested in ProvideMissingTransactions | 92 | 93 | ## 7.6 `RequestTransactionData.Error` (Server->Client) 94 | 95 | | Field Name | Data Type | Description | 96 | | ----------- | --------- | ----------------------------------------------------------------------------- | 97 | | template_id | U64 | The template_id corresponding to a NewTemplate/RequestTransactionData message | 98 | | error_code | STR0_255 | Reason why no transaction data has been provided | 99 | 100 | Possible error codes: 101 | 102 | - `template-id-not-found` - used when the template being referenced is too old and no longer stored in the memory of the Template Provider 103 | - `stale-template-id` - used when the prev_hash of the corresponding template is still in the Template Provider's memory, but it no longer points to the latest tip 104 | 105 | ## 7.7 `SubmitSolution` (Client -> Server) 106 | 107 | Upon finding a coinbase transaction/nonce pair which double-SHA256 hashes at or below `SetNewPrevHash::target`, the client MUST immediately send this message, and the server MUST then immediately construct the corresponding full block and attempt to propagate it to the Bitcoin network. 108 | 109 | | Field Name | Data Type | Description | 110 | | ---------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 111 | | template_id | U64 | The template_id field as it appeared in NewTemplate | 112 | | version | U32 | The version field in the block header. Bits not defined by BIP320 as additional nonce MUST be the same as they appear in the NewMiningJob message, other bits may be set to any value. | 113 | | header_timestamp | U32 | The nTime field in the block header. This MUST be greater than or equal to the header_timestamp field in the latest SetNewPrevHash message and lower than or equal to that value plus the number of seconds since the receipt of that message. | 114 | | header_nonce | U32 | The nonce field in the header | 115 | | coinbase_tx | B0_64K | The full serialized coinbase transaction, meeting all the requirements of the NewMiningJob message, above | 116 | -------------------------------------------------------------------------------- /08-Message-Types.md: -------------------------------------------------------------------------------- 1 | # 8. Message Types 2 | 3 | | Message Type (8-bit) | channel_msg bit | Message Name | 4 | | ------------------------------ | --------------- | ---------------------------------- | 5 | | 0x00 | 0 | SetupConnection | 6 | | 0x01 | 0 | SetupConnection.Success | 7 | | 0x02 | 0 | SetupConnection.Error | 8 | | 0x03 | 1 | ChannelEndpointChanged | 9 | | 0x04 | 0 | Reconnect | 10 | | Mining Protocol | | | 11 | | 0x10 | 0 | OpenStandardMiningChannel | 12 | | 0x11 | 0 | OpenStandardMiningChannel.Success | 13 | | 0x12 | 0 | OpenMiningChannel.Error | 14 | | 0x13 | 0 | OpenExtendedMiningChannel | 15 | | 0x14 | 0 | OpenExtendedMiningChannel.Success | 16 | | 0x15 | 0 | NewMiningJob | 17 | | 0x16 | 1 | UpdateChannel | 18 | | 0x17 | 1 | UpdateChannel.Error | 19 | | 0x18 | 1 | CloseChannel | 20 | | 0x19 | 1 | SetExtranoncePrefix | 21 | | 0x1a | 1 | SubmitSharesStandard | 22 | | 0x1b | 1 | SubmitSharesExtended | 23 | | 0x1c | 1 | SubmitShares.Success | 24 | | 0x1d | 1 | SubmitShares.Error | 25 | | 0x1e | 1 | Reserved | 26 | | 0x1f | 1 | NewExtendedMiningJob | 27 | | 0x20 | 1 | SetNewPrevHash | 28 | | 0x21 | 1 | SetTarget | 29 | | 0x22 | 0 | SetCustomMiningJob | 30 | | 0x23 | 0 | SetCustomMiningJob.Success | 31 | | 0x24 | 0 | SetCustomMiningJob.Error | 32 | | 0x25 | 0 | SetGroupChannel | 33 | | Job Declaration Protocol | | | 34 | | 0x50 | 0 | AllocateMiningJobToken | 35 | | 0x51 | 0 | AllocateMiningJobToken.Success | 36 | | 0x55 | 0 | ProvideMissingTransactions | 37 | | 0x56 | 0 | ProvideMissingTransactions.Success | 38 | | 0x57 | 0 | DeclareMiningJob | 39 | | 0x58 | 0 | DeclareMiningJob.Success | 40 | | 0x59 | 0 | DeclareMiningJob.Error | 41 | | 0x60 | 1 | SubmitSolution | 42 | | Template Distribution Protocol | | | 43 | | 0x70 | 0 | CoinbaseOutputConstraints | 44 | | 0x71 | 0 | NewTemplate | 45 | | 0x72 | 0 | SetNewPrevHash | 46 | | 0x73 | 0 | RequestTransactionData | 47 | | 0x74 | 0 | RequestTransactionData.Success | 48 | | 0x75 | 0 | RequestTransactionData.Error | 49 | | 0x76 | 0 | SubmitSolution | 50 | -------------------------------------------------------------------------------- /09-Extensions.md: -------------------------------------------------------------------------------- 1 | # 9. Extensions 2 | 3 | There are not yet any defined extensions. 4 | | Extenstion Type | Extension Name | Description / BIP | 5 | | -------------------- | -------------- | ---------------------------------------------------------------------------- | 6 | | (no channel_msg bit) | | | 7 | -------------------------------------------------------------------------------- /10-Discussion.md: -------------------------------------------------------------------------------- 1 | # 10. Discussion 2 | ## 10.1 Speculative Mining Jobs 3 | TBD Describe how exactly sending of new jobs before the next block is found works. 4 | 5 | ## 10.2 Rolling `nTime` 6 | - `nTime `field can be rolled once per second with the following notes: 7 | - Mining proxy must not interpret greater than minimum `nTime` as invalid submission. 8 | - Device MAY roll `nTime` once per second. 9 | - Pool SHOULD accept `nTime` which is within the consensus limits. 10 | - Pool MUST accept `nTime` rolled once per second. 11 | 12 | ### 10.2.1 Hardware `nTime` rolling 13 | The protocol allows `nTime` rolling in the hardware as long as the hardware can roll the `nTime` field once per second. 14 | 15 | Modern bitcoin ASIC miners do/will support `nTime` rolling in hardware because it is the most efficient way to expand hashing space for one hashing core/chip. 16 | The `nTime` field is part of the second SHA256 block so it shares midstates with the nonce. 17 | Rolling `nTime` therefore can be implemented as efficiently as rolling nonce, with lowered communication with a mining chip over its communication channels. 18 | The protocol needs to allow and support this. 19 | 20 | ## 10.3 Notes 21 | - Legacy mode: update extranonce1, don’t send all the time (send common merkle-root) 22 | - mining on a locally obtained prevhash (server SHOULD queue the work for some time if the miner has faster access to the network). 23 | - Proxying with separated channels helps with merging messages into TCP stream, makes reconnecting more efficient (and done in proxy, not HW), allows to negotiate work for all devices at once. 24 | - Evaluate reaching the design goals. 25 | - Add promise protocol extension support. It is mainly for XMR and ZEC, but can be addressed in generic way already. 26 | Promise construction can be coin specific, but the general idea holds for all known use cases. 27 | 28 | ## 10.4 Usage Scenarios 29 | v2 ST - protocol v2 (this), standard channel 30 | 31 | v2 EX - protocol v2, extended channel 32 | 33 | v1 - original stratum v1 protocol 34 | 35 | ### 10.4.1 End Device (v2 ST) 36 | Typical scenario for end mining devices, header-only mining. 37 | The device: 38 | 39 | - Sets up the connection without enabling extended channels. 40 | - Opens a Standard channel or more (in the future). 41 | - Receives standard jobs with Merkle root provided by the upstream node. 42 | - Submits standard shares. 43 | 44 | ### 10.4.2 Transparent Proxy (v2 any -> v2 any) 45 | Translation from v2 clients to v2 upstream, without aggregating difficulty. 46 | 47 | Transparent proxy (connection aggregation): 48 | 49 | - Passes all `OpenChannel` messages from downstream connections to the upstream, with updated `request_id` for unique identification. 50 | - Associates `channel_id` given by `OpenChannel.Success` with the initiating downstream connection. 51 | All further messages addressed to the `channel_id` from the upstream node are passed only to this connection, with `channel_id` staying stable. 52 | 53 | ### 10.4.3 Difficulty Aggregating Proxy (v2 any -> v2 EX) 54 | Proxy: 55 | - Translates all standard ... 56 | 57 | V1 58 | 59 | (todo difficulty aggregation with info about the devices) 60 | 61 | 62 | ### 10.4.4 Proxy (v1 -> v2) 63 | Translation from v1 clients to v2 upstream. 64 | 65 | The proxy: 66 | - Accept Opens ... 67 | 68 | 69 | ### 10.4.5 Proxy (v2 -> v1) 70 | ... 71 | 72 | 73 | ## 10.5 FAQ 74 | 75 | 76 | ### 10.5.1 Why is the protocol binary? 77 | The original stratum protocol uses json, which has very bad ratio between the payload size and the actual information transmitted. 78 | Designing a binary based protocol yields better data efficiency. 79 | Technically, we can use the saved bandwidth for more frequent submits to further reduce the variance in measured hash rate and/or to allow individual machines to submit its work directly instead of using work-splitting mining proxy. 80 | 81 | ## 10.6 Terminology 82 | - **upstream stratum node**: responsible for providing new mining jobs, information about new prevhash, etc. 83 | - **downstream stratum node**: consumes mining jobs by physically performing proof-of-work computations or by passing jobs onto further downstream devices. 84 | - **channel ID**: identifies an individual mining device or proxy after the channel has been opened. Upstream endpoints perform job submission 85 | - **public key**: ... 86 | - **signature**: signature encoded as...(?) 87 | - **BIP320**: this proposal identifies general purpose bits within version field of bitcoin block header. Mining devices use these bits to extend their search space. 88 | - **Merkle root**: the root hash of a Merkle tree which contains the coinbase transaction and the transaction set consisting of all the other transactions in the block. 89 | 90 | ## 10.7 Open Questions / Issues 91 | - Write more about channel ID being identifier valid for a particular connection only. 92 | It works only in the namespace of it. 93 | - Refresh sequence diagrams. 94 | - Is it useful to have channel-based reconnect? 95 | Or is connection-based enough? 96 | - Decide on how to control a single device and allow it to have open multiple channels. 97 | - Describe precisely scenarios with `SetNewPrevHash` with regards to repeated block height 98 | - Decide on how to manage assignment of message ID's and the size of the message ID space. 99 | Shall we allow 2 level multiplexing? 100 | E.g. dedicate an ID to a class of vendor messages, while allowing the vendor to assign custom messages ID’s within the class? 101 | - More information about telemetry data 102 | 103 | ``` 104 | +----------------------------------------------------------------------------------------------------------------------+ 105 | | Hashing Power Information | 106 | +-------------------------+------------------+-------------------------------------------------------------------------+ 107 | | Field Name | Data Type | Description | 108 | +-------------------------+------------------+-------------------------------------------------------------------------+ 109 | | aggregated_device_count | U32 | Number of aggregated devices on the channel. An end mining device must | 110 | | | | send 1. A proxy can send 0 when there are no connections to it yet (in | 111 | | | | aggregating mode) | 112 | +-------------------------+------------------+-------------------------------------------------------------------------+ 113 | ``` 114 | -------------------------------------------------------------------------------- /License/BSD-3-Clause: -------------------------------------------------------------------------------- 1 | Copyright 2019 stratum-mining 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted 4 | provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 7 | and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of 10 | conditions and the following disclaimer in the documentation and/or other materials provided 11 | with the distribution. 12 | 13 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to 14 | endorse or promote products derived from this software without specific prior written 15 | permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 18 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 19 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 20 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 23 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 24 | OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /License/CC0-1.0: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stratum V2 Protocol Specification 2 | This repository contains the Stratum V2 protocol specification. 3 | 4 | - [0. Abstract](./00-Abstract.md) 5 | - [1. Motivation](./01-Motivation.md) 6 | - [2. Design Goals](./02-Design-Goals.md) 7 | - [3. Protocol Overview](./03-Protocol-Overview.md) 8 | - [3.1 Data Types Mapping](./03-Protocol-Overview.md#31-data-types-mapping) 9 | - [3.2 Framing](./03-Protocol-Overview.md#32-framing) 10 | - [3.3 Reconnecting Downstream Nodes](./03-Protocol-Overview.md#33-reconnecting-downstream-nodes) 11 | - [3.4 Protocol Extensions](./03-Protocol-Overview.md#34-protocol-extensions) 12 | - [3.5 Error Codes](./03-Protocol-Overview.md#35-error-codes) 13 | - [3.6 Common Protocol Messages](./03-Protocol-Overview.md#36-common-protocol-messages) 14 | - [3.6.1 SetupConnection (Client -> Server)](./03-Protocol-Overview.md#361-setupconnection-client---server) 15 | - [3.6.2 SetupConnection.Success (Server -> Client)](./03-Protocol-Overview.md#362-setupconnectionsuccess-server---client) 16 | - [3.6.3 SetupConnection.Error (Server -> Client)](./03-Protocol-Overview.md#363-setupconnectionerror-server---client) 17 | - [3.6.4 ChannelEndpointChanged (Server -> Client)](./03-Protocol-Overview.md#364-channelendpointchanged-server---client) 18 | - [4. Protocol Security](./04-Protocol-Security.md) 19 | - [4.1 Motivation for Authenticated Encryption with Associated Data](./04-Protocol-Security.md#41-motivation-for-authenticated-encryption-with-associated-data) 20 | - [4.2 Motivation for Using the Noise Protocol Framework](./04-Protocol-Security.md#42-motivation-for-using-the-noise-protocol-framework) 21 | - [4.3 Choice of cryptographic primitives](./04-Protocol-Security.md#43-choice-of-cryptographic-primitives) 22 | - [4.3.1 Elliptic Curve](./04-Protocol-Security.md#431-elliptic-curve) 23 | - [4.3.1.1 EC point encoding remarks](./04-Protocol-Security.md#4311-ec-point-encoding-remarks) 24 | - [4.3.2 Hash function](./04-Protocol-Security.md#432-hash-function) 25 | - [4.3.3 Cipher function for authenticated encryption](./04-Protocol-Security.md#433-cipher-function-for-authenticated-encryption) 26 | - [4.4 Cryptographic operations](./04-Protocol-Security.md#44-cryptographic-operations) 27 | - [4.4.1 CipherState object](./04-Protocol-Security.md#441-cipherstate-object) 28 | - [4.4.2 Handshake Operation](./04-Protocol-Security.md#442-handshake-operation) 29 | - [4.5 Authenticated Key Agreement Handshake](./04-Protocol-Security.md#45-authenticated-key-agreement-handshake) 30 | - [4.5.1 Handshake Act 1: Noise protocol proposal](./04-Protocol-Security.md#451-handshake-act-1-noise-protocol-proposal) 31 | - [4.5.2 Handshake Act 2: Noise protocol choice](./04-Protocol-Security.md#452-handshake-act-2-noise-protocol-choice) 32 | - [4.5.3 Handshake Act 3: NX-handshake part 1 `-> e`](./04-Protocol-Security.md#453-handshake-act-3-nx-handshake-part-1---e) 33 | - [4.5.4 Handshake Act 4: NX-handshake part 2 `<- e, ee, s, es, SIGNATURE_NOISE_MESSAGE`](./04-Protocol-Security.md#454-handshake-act-4-nx-handshake-part-2---e-ee-s-es-signature_noise_message) 34 | - [4.5.5 Server authentication](./04-Protocol-Security.md#455-server-authentication) 35 | - [4.5.5.1 Signature structure](./04-Protocol-Security.md#4551-signature-structure) 36 | - [4.5.6 Transport message encryption and format](./04-Protocol-Security.md#456-transport-message-encryption-and-format) 37 | - [4.6 URL Scheme and Pool Authority Key](./04-Protocol-Security.md#46-url-scheme-and-pool-authority-key) 38 | - [4.7 References](./04-Protocol-Security.md#47-references) 39 | - [5. Mining Protocol](./05-Mining-Protocol.md) 40 | - [5.1 Jobs](./05-Mining-Protocol.md#51-jobs) 41 | - [5.1.1 Standard Jobs](./05-Mining-Protocol.md#511-standard-jobs) 42 | - [5.1.2 Extended Jobs](./05-Mining-Protocol.md#512-extended-jobs) 43 | - [5.1.2.1 Extended Extranonce](./05-Mining-Protocol.md#5121-extended-extranonce) 44 | - [5.1.3 Future Jobs](./05-Mining-Protocol.md#513-future-jobs) 45 | - [5.1.4 Custom Jobs](./05-Mining-Protocol.md#514-custom-jobs) 46 | - [5.2 Channels](./05-Mining-Protocol.md#52-channels) 47 | - [5.2.1 Standard Channels](./05-Mining-Protocol.md#521-standard-channels) 48 | - [5.2.2 Extended Channels](./05-Mining-Protocol.md#522-extended-channels) 49 | - [5.2.3 Group Channels](./05-Mining-Protocol.md#523-group-channels) 50 | - [5.3 Mining Protocol Messages](./05-Mining-Protocol.md#53-mining-protocol-messages) 51 | - [5.3.1 SetupConnection Flags for Mining Protocol](./05-Mining-Protocol.md#531-setupconnection-flags-for-mining-protocol) 52 | - [5.3.2 OpenStandardMiningChannel (Client -> Server)](./05-Mining-Protocol.md#532-openstandardminingchannel-client---server) 53 | - [5.3.3 OpenStandardMiningChannel.Success (Server -> Client)](./05-Mining-Protocol.md#533-openstandardminingchannelsuccess-server---client) 54 | - [5.3.4 OpenExtendedMiningChannel (Client -> Server)](./05-Mining-Protocol.md#534-openextendedminingchannel-client---server) 55 | - [5.3.5 OpenExtendedMiningChannel.Success (Server -> Client)](./05-Mining-Protocol.md#535-openextendedminingchannelsuccess-server---client) 56 | - [5.3.6 OpenMiningChannel.Error (Server -> Client)](./05-Mining-Protocol.md#536-openminingchannelerror-server---client) 57 | - [5.3.7 UpdateChannel (Client -> Server)](./05-Mining-Protocol.md#537-updatechannel-client---server) 58 | - [5.3.8 UpdateChannel.Error (Server -> Client)](./05-Mining-Protocol.md#538-updatechannelerror-server---client) 59 | - [5.3.9 CloseChannel (Client -> Server, Server -> Client)](./05-Mining-Protocol.md#539-closechannel-client---server-server---client) 60 | - [5.3.10 SetExtranoncePrefix (Server -> Client)](./05-Mining-Protocol.md#5310-setextranonceprefix-server---client) 61 | - [5.3.11 SubmitSharesStandard (Client -> Server)](./05-Mining-Protocol.md#5311-submitsharesstandard-client---server) 62 | - [5.3.12 SubmitSharesExtended (Client -> Server)](./05-Mining-Protocol.md#5312-submitsharesextended-client---server) 63 | - [5.3.13 SubmitShares.Success (Server -> Client)](./05-Mining-Protocol.md#5313-submitsharessuccess-server---client) 64 | - [5.3.14 SubmitShares.Error (Server -> Client)](./05-Mining-Protocol.md#5314-submitshareserror-server---client) 65 | - [5.3.15 NewMiningJob (Server -> Client)](./05-Mining-Protocol.md#5315-newminingjob-server---client) 66 | - [5.3.16 NewExtendedMiningJob (Server -> Client)](./05-Mining-Protocol.md#5316-newextendedminingjob-server---client) 67 | - [5.3.17 SetNewPrevHash (Server -> Client, broadcast)](./05-Mining-Protocol.md#5317-setnewprevhash-server---client-broadcast) 68 | - [5.3.18 SetCustomMiningJob (Client -> Server)](./05-Mining-Protocol.md#5318-setcustomminingjob-client---server) 69 | - [5.3.19 SetCustomMiningJob.Success (Server -> Client)](./05-Mining-Protocol.md#5319-setcustomminingjobsuccess-server---client) 70 | - [5.3.20 SetCustomMiningJob.Error (Server -> Client)](./05-Mining-Protocol.md#5320-setcustomminingjoberror-server---client) 71 | - [5.3.21 SetTarget (Server -> Client)](./05-Mining-Protocol.md#5321-settarget-server---client) 72 | - [5.3.22 SetGroupChannel (Server -> Client)](./05-Mining-Protocol.md#5322-setgroupchannel-server---client) 73 | - [6. Job Declaration Protocol](./06-Job-Declaration-Protocol.md) 74 | - [6.1 Job Declaration Protocol Messages](./06-Job-Declaration-Protocol.md#61-job-declaration-protocol-messages) 75 | - [6.1.1 SetupConnection Flags for Job Declaration Protocol](./06-Job-Declaration-Protocol.md#611-setupconnection-flags-for-job-declaration-protocol) 76 | - [6.1.2 AllocateMiningJobToken (Client -> Server)](./06-Job-Declaration-Protocol.md#612-allocateminingjobtoken-client---server) 77 | - [6.1.3 AllocateMiningJobToken.Success (Server -> Client)](./06-Job-Declaration-Protocol.md#613-allocateminingjobtokensuccess-server---client) 78 | - [6.1.4 CommitMiningJob (Client -> Server)](./06-Job-Declaration-Protocol.md#614-commitminingjob-client---server) 79 | - [6.1.5 CommitMiningJob.Success (Server -> Client)](./06-Job-Declaration-Protocol.md#615-commitminingjobsuccess-server---client) 80 | - [6.1.6 CommitMiningJob.Error (Server->Client)](./06-Job-Declaration-Protocol.md#616-commitminingjoberror-server-client) 81 | - [6.1.7 ProvideMissingTransactions (Server->Client)](./06-Job-Declaration-Protocol.md#619-providemissingtransactions-server-client) 82 | - [6.1.8 ProvideMissingTransactions.Success (Client->Server)](./06-Job-Declaration-Protocol.md#6110-providemissingtransactionssuccess-client-server) 83 | - [7. Template Distribution Protocol](./07-Template-Distribution-Protocol.md) 84 | - [7.1 CoinbaseOutputConstraints (Client -> Server)](./07-Template-Distribution-Protocol.md#71-coinbaseoutputdatasize-client---server) 85 | - [7.2 NewTemplate (Server -> Client)](./07-Template-Distribution-Protocol.md#72-newtemplate-server---client) 86 | - [7.3 SetNewPrevHash (Server -> Client)](./07-Template-Distribution-Protocol.md#73-setnewprevhash-server---client) 87 | - [7.4 RequestTransactionData (Client -> Server)](./07-Template-Distribution-Protocol.md#74-requesttransactiondata-client---server) 88 | - [7.5 RequestTransactionData.Success (Server->Client)](./07-Template-Distribution-Protocol.md#75-requesttransactiondatasuccess-server-client) 89 | - [7.6 RequestTransactionData.Error (Server->Client)](./07-Template-Distribution-Protocol.md#76-requesttransactiondataerror-server-client) 90 | - [7.7 SubmitSolution (Client -> Server)](./07-Template-Distribution-Protocol.md#77-submitsolution-client---server) 91 | - [8. Message Types](./08-Message-Types.md) 92 | - [9. Extensions](./09-Extensions.md) 93 | - [10. Discussion](./10-Discussion.md#10-discussion) 94 | - [10.1 Speculative Mining Jobs](./10-Discussion.md#101-speculative-mining-jobs) 95 | - [10.2 Rolling `nTime`](./10-Discussion.md#102-rolling-ntime) 96 | - [10.2.1 Hardware nTime rolling](./10-Discussion.md#1021-hardware-ntime-rolling) 97 | - [10.3 Notes](./10-Discussion.md#103-notes) 98 | - [10.4 Usage Scenarios](./10-Discussion.md#104-usage-scenarios) 99 | - [10.4.1 End Device (v2 ST)](./10-Discussion.md#1041-end-device-v2-st) 100 | - [10.4.2 Transparent Proxy (v2 any -> v2 any)](./10-Discussion.md#1042-transparent-proxy-v2-any---v2-any) 101 | - [10.4.3 Difficulty Aggregating Proxy (v2 any -> v2 EX)](./10-Discussion.md#1043-difficulty-aggregating-proxy-v2-any---v2-ex) 102 | - [10.4.4 Proxy (v1 -> v2)](./10-Discussion.md#1044-proxy-v1---v2) 103 | - [10.4.5 Proxy (v2 -> v1)](./10-Discussion.md#1045-proxy-v2---v1) 104 | - [10.5. FAQ](./10-Discussion.md#105-faq) 105 | - [10.5.1 Why is the protocol binary?](./10-Discussion.md#1051-why-is-the-protocol-binary) 106 | - [10.6 Terminology](./10-Discussion.md#106-terminology) 107 | - [10.7 Open Questions / Issues](./10-Discussion.md#107-open-questions--issues) 108 | 109 | ## Authors 110 | Pavel Moravec 111 | Jan Čapek 112 | Matt Corallo 113 | -------------------------------------------------------------------------------- /img/drawio/README.md: -------------------------------------------------------------------------------- 1 | In case the `*.png` files on the parent directory need to be adjusted, the `*.drawio.xml` files from this directory 2 | should be imported into the `draw.io` online tool for editing. 3 | 4 | After editing: 5 | - export the `.png` file to replace the old one in the parent directory 6 | - export the `.drawio.xml` file to replace the old one on this directory -------------------------------------------------------------------------------- /img/drawio/extended_extranonce.drawio.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /img/drawio/extended_extranonce_layers.drawio.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | -------------------------------------------------------------------------------- /img/drawio/jd_coinbase_mode.drawio.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | -------------------------------------------------------------------------------- /img/drawio/jd_template_mode.drawio.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | -------------------------------------------------------------------------------- /img/drawio/standard_job.drawio.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /img/extended_extranonce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratum-mining/sv2-spec/9066ae3e3c5b9528f1a284d034c3a57247edf83f/img/extended_extranonce.png -------------------------------------------------------------------------------- /img/extended_extranonce_layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratum-mining/sv2-spec/9066ae3e3c5b9528f1a284d034c3a57247edf83f/img/extended_extranonce_layers.png -------------------------------------------------------------------------------- /img/extended_job.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratum-mining/sv2-spec/9066ae3e3c5b9528f1a284d034c3a57247edf83f/img/extended_job.png -------------------------------------------------------------------------------- /img/jd_coinbase_mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratum-mining/sv2-spec/9066ae3e3c5b9528f1a284d034c3a57247edf83f/img/jd_coinbase_mode.png -------------------------------------------------------------------------------- /img/jd_template_mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratum-mining/sv2-spec/9066ae3e3c5b9528f1a284d034c3a57247edf83f/img/jd_template_mode.png -------------------------------------------------------------------------------- /img/standard_job.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stratum-mining/sv2-spec/9066ae3e3c5b9528f1a284d034c3a57247edf83f/img/standard_job.png --------------------------------------------------------------------------------