Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIP40: Stratum wire protocol #1557

Draft
wants to merge 34 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
47ca202
Write initial draft of BIP 40
ben221199 Mar 7, 2024
914fb7c
Fix inline code
ben221199 Mar 7, 2024
72bfc4d
Allow public domain
ben221199 Mar 7, 2024
abe08e4
Improve specification of transport protocols
ben221199 Mar 7, 2024
a5aee5b
Add letters and default ports
ben221199 Mar 19, 2024
8658be8
Add more information about WebSockets
ben221199 Mar 19, 2024
e13def4
Add information about WebSocket subprotocol
ben221199 Mar 21, 2024
e280771
Add information about HTTP polling
ben221199 Mar 21, 2024
83647b1
Improve text
ben221199 Mar 21, 2024
3d217b0
Add note
ben221199 Mar 21, 2024
c82a2a1
Add information about HTTP Push
ben221199 Mar 21, 2024
805559f
Add two methods
ben221199 Mar 21, 2024
ec52ae1
Improve commands
ben221199 Mar 21, 2024
84f8519
Process editorial feedback
ben221199 May 6, 2024
b50e9e5
Merge branch 'master' into add-bip40
ben221199 May 6, 2024
0cdfcb5
Add IANA considerations
ben221199 May 6, 2024
19a39e2
Fix links
ben221199 May 6, 2024
1cf5983
Add information about service vendor
ben221199 May 6, 2024
2f620f5
Fix layer
ben221199 May 6, 2024
48adb0f
Merge branch 'master' into add-bip40
ben221199 May 10, 2024
b5a9b10
Add IANA consideration for HTTP fields
ben221199 May 10, 2024
19cf447
Add example commands
ben221199 May 10, 2024
6e26691
Add example pub/sub commands
ben221199 May 10, 2024
73f8ad1
Move services to seperate file
ben221199 May 12, 2024
2787db0
Add information about discovery service
ben221199 May 12, 2024
40bc721
Improve service documentation
ben221199 May 12, 2024
05e1194
Improve blockchain service documentation
ben221199 May 12, 2024
16b6d5c
Apply suggestions
ben221199 May 21, 2024
4cf8985
Improve sentences
ben221199 Nov 25, 2024
1936b49
Improve documents of Stratum methods
ben221199 Nov 26, 2024
bbad8a0
Fix type and description
ben221199 Nov 26, 2024
387af0f
Add examples to Firstbits methods
ben221199 Nov 26, 2024
db5ed75
Improve documentation of server commands
ben221199 Nov 27, 2024
996724f
Add remaining Stratum services
ben221199 Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,12 @@ Those proposing changes should consider that ultimately consent may rest with th
| Standard
| Proposed
|-
| 40
| [[bip-0040.mediawiki|40]]
| API/RPC
| Stratum wire protocol
| Marek Palatinus
| Marek Palatinus, Ben van Hartingsveldt
| Standard
| BIP number allocated
| Draft
|-
| 41
| API/RPC
Expand Down
235 changes: 235 additions & 0 deletions bip-0040.mediawiki
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
<pre>
BIP: 40
Layer: Applications
Title: Stratum wire protocol
Author: Marek Palatinus <slush@satoshilabs.com>
Ben van Hartingsveldt <ben.vanhartingsveldt@yocto.com>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0040
Status: Draft
Type: Standards Track
Created: 2024-03-07
License: PD
</pre>

==Abstract==

This document describes the Stratum wire protocol used in clients such as Electrum, and which also laid the foundation for the Stratum mining protocol, used in many Bitcoin pools.

The specification is intended to set a standard for connections between clients and servers in which the client is able to request data without having to download the full blockchain.

The specification consists of three parts. In the first part, the data format is defined. In the second part, the possible transport protocols (including encapsulation) are described. In the third part, the available methods are documented.

==Motivation==

Many clients want to give users access to the Bitcoin ecosystem. However, for specific reasons not every user is able to download the full blockchain to their machine.

The Stratum wire protocol defines a way to access the blockchain without having it downloaded. For example, a client can request both the genesis block and the latest block with the same latency, because the server does synchronize and index all blocks for us.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

==History==

Stratum wire protocol was introduced by Marek Palatinus in late 2011 and early 2012. It was a language independent alternative for the Python-based protocol in early versions of Electrum, created by Thomas Voegtlin. The Stratum wire protocol made it possible to create compatible servers which Electrum could connect to, but it also made it possible to write alternative clients.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

Later in 2012, Marek Palatinus introduced Stratum also for mining pools: The Stratum mining protocol, as defined in [[bip-0041.mediawiki|BIP 41]].
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

==Specification: Data Format==

Stratum leverages [https://www.jsonrpc.org/ JSON-RPC]. Both versions 1.0 and 2.0 are allowed. Rules of that version apply accordingly.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

Additionally, it is a convention to give all Stratum methods in the <code>method</code> property a name in the following form: <code><service>.<method></code>, where <code><service></code> is allowed to have dots and <code><method></code> isn't. For example, the the value <code>blockchain.block.subscribe</code>.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

''Note: In JSON-RPC 1.0, the <code>param</code> property is an array, so everything should be passed in the right order. In JSON-RPC 2.0, also named parameters are allowed. In that case, the parameter names that are documented should be used. If not, the method can fail. It is maybe also possible that a specific method (or server) only does support <code>params</code> being an array, because it doesn't know how to handle the named ones, even if it supports JSON-RPC 2.0.''
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

==Specification: Transport Protocols==

It is possible to send JSON-RPC messages over different transport protocols, like TCP and HTTP. It is also possible to protect these protocols with SSL/TLS.

''Note: Because HTTP and WebSockets support virtual hosting (<code>Host</code> header or <code>:authority</code> pseudo-header), it is possible to create a server on a single IP address that supports multiple coins by checking the domain name. The same is the case for the transport protocols with SSL/TLS when SNI is used. On plain TCP, virtual hosting is not possible. A similar experience can be reached by using multiple IP addresses. For IPv6, a network of /96 would be enough to hypothetically support all coins ever listed in SLIP-44. For IPv4, you would need all IPv4 addresses that exist to do the same, even the invalid ones, so a suggestion is to only use the server only for coins you really need. Also, other ports could possibly be used and in that case, a /16 IP block with all 65536 TCP ports in use will be enough to support all coins. However, because using non-standard ports is not user-friendly, this is also not recommended.''
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

===TCP===

Stratum over a TCP connection. Every JSON-RPC message (including batch messages) is send on a single line, ending with a line-feed (<code>\n</code>), so <code>\r\n</code> is also allowed. Line-feeds inside the JSON should be encoded as usual. Both client and server can initiate a request on which the other side could respond with a result or an error.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

* Default port: <code>50001</code>
* Letter: <code>t</code>

===TCP over SSL/TLS===

Stratum over a TCP connection with SSL/TLS. Just the same as normal TCP, but with SSL/TLS enabled.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

* Default port: <code>50002</code>
* Letter: <code>s</code>

===HTTP===

Stratum over an HTTP connection. When communicating over HTTP, there 2 possible options: polling and pushing. In both cases, the request and response have a <code>Content-Type</code> header with the value <code>application/stratum</code>. Like in the TCP transport, the messages have to end with a line-feed (\n). It is possible to send more messages in one HTTP request or response.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

It could be possible that a request or response also has a <code>Content-MD5</code> header, so it is possible for the receiver to detect any modifications to the content. It is up to clients and servers how to handle upon a mismatch. A suggestion for a client would be to retry the command. A suggestion for a server would be to return a 400 error (or return a 200 error with a JSON-RPC error message).
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

* Default port: <code>8081</code>
* Letter: <code>h</code>

====Session====

Because it is not sure if an HTTP connection will stay open, it is highly possible that messages will be sent over multiple connections. To keep track of the same "session", a cookie with the name <code>STRATUM_SESSION</code> is used. If a client sends a request with a cookie, the servers knows exactly which session is used and which notifications to send.

Servers could send the <code>Stratum-Session-Timeout</code><ref name="extended"/> header to tell the client when a session with the same session id will be seen as a new session by the server. The header contains a number that indicates how many seconds are left. This is different from <code>Expires</code> or <code>Max-Age</code> parameters of the <code>Set-Cookie</code> header, that indicate when a cookie (not necessarily a session) should have been expired by the client. For backwards compatibility, a <code>X-Session-Timeout</code> header with the same value should be sent in those requests too.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

====HTTP Poll====

When polling, an HTTP POST request is sent with <code>application/stratum</code> in the <code>Content-Type</code> header. In the body, there could be one or more messages. If the body is empty, the client just wants to check for notifications.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

If no error occurred, the server will respond with a 200 status code and with <code>application/stratum</code> in the <code>Content-Type</code> header. If there are one or more notifications or other messages, the body will contain those messages. Else, the body will be empty.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

====HTTP Push====

HTTP Poll is the default mode when connecting with a server over HTTP. To get the session in HTTP Push mode, a client should send a regular HTTP Poll request with an additional <code>Stratum-Callback-URL</code><ref name="extended"/> header. This will let the server send notifications using the callback URL without the client needing to send HTTP poll requests in with a very small interval. To disable HTTP Push mode, a regular HTTP poll request should be sent with an additional empty <code>Stratum-Callback-URL</code><ref name="extended"/> header. For backwards compatibility, a <code>X-Callback-URL</code> header with the same value should be sent in those requests too.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

The callback URL will be called when there are notifications. This request is an HTTP POST request with a <code>Content-Type</code> header and a <code>Stratum-Session-ID</code><ref name="extended"/> header. The <code>Stratum-Session-ID</code><ref name="extended"/> contains the same id as the <code>STRATUM_SESSION</code> cookie. This makes it possible to use the callback URL for multiple sessions. The response is of the callback URL is expected to be empty, so any response body will likely be ignored. For backwards compatibility, a <code>X-Session-ID</code> header with the same value should be sent in those requests too.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

===HTTP over SSL/TLS===

Stratum over an HTTP connection with SSL/TLS. Just the same as normal HTTP, but with SSL/TLS enabled.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

* Default port: <code>8082</code>
* Letter: <code>g</code>

===WebSocket===

Stratum over a WebSocket connection. When using WebSockets, the JSON-RPC messages (including batch messages) are encapsulated in a WebSocket message. It is also possible to send more JSON-RPC messages in one WebSocket message. Every JSON-RPC message should end with a line-feed (\n). Both client and server can initiate a message request on which the other side could respond with a result or an error, like Stratum over TCP.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

* Default port: <code>8083</code><ref name="extended">This is extended specification information of the Stratum wire protocol to make it more complete. This information will not be found in any code or specification before this BIP.</ref>
* Letter: <code>w</code><ref name="extended"/>

====Subprotocol<ref name="extended"/>====

In a WebSocket upgrade request, it is possible to use the <code>Sec-WebSocket-Protocol</code> header to let the WebSocket server know which subprotocol is desired to send over the connection. For Stratum, the value <code>stratum</code> is registered. The use of this header is optional. If the server supports the use of this subprotocol too, it will let the client know by sending a <code>Sec-WebSocket-Protocol</code> header back. If the server doesn't send a subprotocol back, the connection will continue without using one. Use of this feature is fully backwards compatible.

====Example====

<pre>
// Open WebSocket with using a subprotocol
new WebSocket('ws://stratum.example.com:8083',['stratum']);

// Open WebSocket without using a subprotocol
new WebSocket('ws://stratum.example.com:8083');
</pre>

===WebSocket over SSL/TLS===

Stratum over a WebSocket connection with SSL/TLS. Just the same as normal WebSocket, but with SSL/TLS enabled.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved

* Default port: <code>8084</code><ref name="extended"/>
* Letter: <code>u</code><ref name="extended"/>

==Specification: Commands==

===Service: Blockchain Address===

* Service name: <code>blockchain.address</code>

====Method: Get History====

* Method name: <code>get_history</code>

{|
! <ins>[Request]</ins>
! Type
! Example
! Description
|-
! Method
| colspan="3" | <code>blockchain.address.get_history</code>
|-
! Param [0]
| <code>string</code>
| <code>1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L</code>
| The address to get the history of.
|-
! <ins>[Response]</ins>
! Type
! Example
! Description
|-
! Result
| <code>array</code>
|
| The history of the a blockchain address.
ben221199 marked this conversation as resolved.
Show resolved Hide resolved
|}

====Method: Subscribe====

* Method name: <code>subscribe</code>

{|
! <ins>[Request]</ins>
! Type
! Example
! Description
|-
! Method
| colspan="3" | <code>blockchain.address.subscribe</code>
|-
! Param [0]
| <code>string</code>
| <code>1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L</code>
| The address to subscribe to.
|}

===Service: Client===

* Service name: <code>client</code>

====Method: Version====

Send the version of the client to the server. This command doesn't expect a response.

* Method name: <code>version</code>

{|
! <ins>[Request]</ins>
! Type
! Example
! Description
|-
! Method
| colspan="3" | <code>client.version</code>
|-
! Params [0]
| <code>string</code>
| <code>0.41</code>
| The client version.
|}

===Service: Server===

* Service name: <code>server</code>

====Method: Banner====

A command to get the server banner.

* Method name: <code>banner</code>

{|
! <ins>[Request]</ins>
! Type
! Example
! Description
|-
! Method
| colspan="3" | <code>server.banner</code>
|-
! <ins>[Response]</ins>
! Type
! Example
! Description
|-
! Result
| <code>string</code>
| <code>Welcome to Electrum!</code>
| The server banner.
|}

==References==
<references/>
2 changes: 1 addition & 1 deletion scripts/buildtable.pl
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
'OPL' => undef,
'PD' => undef,
);
my %GrandfatheredPD = map { $_ => undef } qw(9 36 37 38 42 49 50 60 65 67 69 74 80 81 83 90 99 105 107 109 111 112 113 114 122 124 125 126 130 131 132 133 140 141 142 143 144 146 147 150 151 152);
my %GrandfatheredPD = map { $_ => undef } qw(9 36 37 38 40 42 49 50 60 65 67 69 74 80 81 83 90 99 105 107 109 111 112 113 114 122 124 125 126 130 131 132 133 140 141 142 143 144 146 147 150 151 152);
my %TolerateMissingLicense = map { $_ => undef } qw(1 10 11 12 13 14 15 16 21 31 33 34 35 39 43 44 45 47 61 64 68 70 71 72 73 101 102 106 120 121);
my %TolerateTitleTooLong = map { $_ => undef } qw(39 44 45 47 49 60 67 68 69 73 74 75 80 81 99 105 106 109 113 122 126 131 143 145 147 173 327);

Expand Down
Loading