You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
765 lines
20 KiB
765 lines
20 KiB
=================
|
|
Electrum Protocol
|
|
=================
|
|
|
|
Until now there was no written specification of the Electrum protocol
|
|
that I am aware of; this document is an attempt to fill that gap. It
|
|
is intended to be a reference for client and server authors alike.
|
|
[Since writing this I learnt there has been a skeleton protocol
|
|
description on docs.github.io].
|
|
|
|
I have attempted to ensure what is written is correct for the three
|
|
known server implementations: electrum-server, jelectrum and
|
|
ElectrumX, and also for Electrum clients of the 2.x series. We know
|
|
other clients exist but I am not aware of the source of any being
|
|
publicly available.
|
|
|
|
|
|
Message Stream
|
|
--------------
|
|
|
|
Clients and servers communicate using JSON RPC over an unspecified
|
|
underlying stream transport protocol, typically TCP or SSL.
|
|
|
|
`JSON RPC 1.0`_ and `JSON RPC 2.0`_ are specified; use of version 2.0
|
|
is encouraged but not required. Server support of batch requests is
|
|
encouraged for version 1.0 but not required. Clients making batch
|
|
requests should limit their size depending on the nature of their
|
|
query, because servers will limit response size as an anti-DoS
|
|
mechanism.
|
|
|
|
RPC calls and responses are separated by newlines in the stream. The
|
|
JSON specification does not permit control characters within strings,
|
|
so no confusion is possible there. However it does permit newlines as
|
|
extraneous whitespace between elements; client and server MUST NOT use
|
|
newlines in such a way.
|
|
|
|
If using JSON RPC 2.0's feature of parameter passing by name, the
|
|
names shown in the protocol versions's description MUST be used.
|
|
|
|
A server advertising support for a particular protocol version MUST
|
|
support each method documented for that protocol version, unless the
|
|
method is explicitly marked optional. It may support other methods or
|
|
additional parameters with unspecified behaviour. Use of additional
|
|
parameters is discouraged as it may conflict with future versions of
|
|
the protocol.
|
|
|
|
Notifications
|
|
-------------
|
|
|
|
Some methods are subscriptions, which will respond with notifications
|
|
when the thing subscribed to changes. The `method` of the
|
|
notification is the same as the method of the subscription, and the
|
|
`params` of the notification (and their names) are given in the
|
|
documentation of the method.
|
|
|
|
|
|
Protocol Negotiation
|
|
--------------------
|
|
|
|
It is desirable to have a way to enhance and improve the protocol
|
|
without forcing servers and clients to upgrade at the same time.
|
|
Protocol negotiation is not implemented in any client or server at
|
|
present to the best of my knowledge, so care is needed to ensure
|
|
current clients and servers continue to operate as expected.
|
|
|
|
Protocol versions are denoted by "m.n" strings, where *m* is the major
|
|
version number and *n* the minor version number. For example: "1.5".
|
|
|
|
A party to a connection will speak all protocol versions in a range,
|
|
say from `protocol_min` to `protocol_max`. This min and max may be
|
|
the same. When a connection is made, both client and server must
|
|
initially assume the protocol to use is their own `protocol_min`.
|
|
|
|
The client should send a `server.version` RPC call as early as
|
|
possible in order to negotiate the precise protocol version; see its
|
|
description for more detail. All responses received in the stream
|
|
from and including the server's response to this call will use the
|
|
negotiated protocol version.
|
|
|
|
|
|
Protocol Version 1.0
|
|
--------------------
|
|
|
|
server.version
|
|
==============
|
|
|
|
Identifies the client to the server.
|
|
|
|
server.version(**client_name**, **protocol_version**)
|
|
|
|
**client_name**
|
|
|
|
An optional string identifying the connecting client software.
|
|
|
|
**protocol_verion**
|
|
|
|
Optional. The value passed is ignored.
|
|
|
|
**Response**
|
|
|
|
A string identifying the server software.
|
|
|
|
**Example**::
|
|
|
|
server.version("2.7.11", "1.0")
|
|
|
|
|
|
blockchain.address.get_balance
|
|
==============================
|
|
|
|
Return the confirmed and unconfirmed balances of a bitcoin address.
|
|
|
|
blockchain.address.get_balance(**address**)
|
|
|
|
**address**
|
|
|
|
The address as a Base58 string.
|
|
|
|
**Response**
|
|
|
|
A dictionary with keys *confirmed* and *unconfirmed*. The value of
|
|
each is the appropriate balance in coin units as a string.
|
|
|
|
**Response Example**::
|
|
|
|
{
|
|
"confirmed": "1.03873966",
|
|
"unconfirmed": "0.236844"
|
|
}
|
|
|
|
|
|
blockchain.address.get_history
|
|
==============================
|
|
|
|
Return the confirmed and unconfirmed history of a bitcoin address.
|
|
|
|
blockchain.address.get_history(**address**)
|
|
|
|
**address**
|
|
|
|
The address as a Base58 string.
|
|
|
|
**Response**
|
|
|
|
A list of confirmed transactions in blockchain order, with the
|
|
output of *blockchain.address.get_mempool* appended to the list.
|
|
Each transaction is a dictionary with keys *height* and *tx_hash*.
|
|
*height* is the integer height of the block the transaction was
|
|
confirmed in, and *tx_hash* the transaction hash in hexadecimal.
|
|
|
|
**Response Examples**
|
|
|
|
::
|
|
|
|
[
|
|
{
|
|
"height": 200004,
|
|
"tx_hash": "acc3758bd2a26f869fcc67d48ff30b96464d476bca82c1cd6656e7d506816412"
|
|
},
|
|
{
|
|
"height": 215008,
|
|
"tx_hash": "f3e1bf48975b8d6060a9de8884296abb80be618dc00ae3cb2f6cee3085e09403"
|
|
}
|
|
]
|
|
|
|
::
|
|
|
|
[
|
|
{
|
|
"fee": 20000,
|
|
"height": 0,
|
|
"tx_hash": "9fbed79a1e970343fcd39f4a2d830a6bde6de0754ed2da70f489d0303ed558ec"
|
|
}
|
|
]
|
|
|
|
|
|
blockchain.address.get_mempool
|
|
==============================
|
|
|
|
Return the unconfirmed transactions of a bitcoin address.
|
|
|
|
blockchain.address.get_mempool(**address**)
|
|
|
|
**address**
|
|
|
|
The address as a Base58 string.
|
|
|
|
**Response**
|
|
|
|
A list of mempool transactions in arbitrary order. Each
|
|
transaction is a dictionary with keys *height* , *tx_hash* and
|
|
*fee*. *tx_hash* the transaction hash in hexadecimal, *height* is
|
|
`0` if all inputs are confirmed, and `-1` otherwise, and *fee* is
|
|
the transaction fee in minimum coin units as an integer.
|
|
|
|
**Response Examples**
|
|
|
|
::
|
|
|
|
[
|
|
{
|
|
"tx_hash": "45381031132c57b2ff1cbe8d8d3920cf9ed25efd9a0beb764bdb2f24c7d1c7e3",
|
|
"height": 0,
|
|
"fee": 24310
|
|
}
|
|
]
|
|
|
|
|
|
blockchain.address.get_proof
|
|
============================
|
|
|
|
This method is optional and deprecated, and hence its response will
|
|
not be described here.
|
|
|
|
blockchain.address.get_proof(**address**)
|
|
|
|
**address**
|
|
|
|
The address as a Base58 string.
|
|
|
|
|
|
blockchain.address.listunspent
|
|
==============================
|
|
|
|
Return an ordered list of UTXOs sent to a bitcoin address.
|
|
|
|
blockchain.address.listunspent(**address**)
|
|
|
|
**address**
|
|
|
|
The address as a Base58 string.
|
|
|
|
**Response**
|
|
|
|
A list of unspent outputs in blockchain order. Each transaction
|
|
is a dictionary with keys *height* , *tx_pos*, *tx_height* and
|
|
*value* keys. *height* is the integer height of the block the
|
|
transaction was confirmed in, *tx_hash* the transaction hash in
|
|
hexadecimal, *tx_pos* the zero-based index of the output in the
|
|
transaction's list of outputs, and *value* its integer value in
|
|
minimum coin units (satoshis in the case of Bitcoin).
|
|
|
|
**Response Example**
|
|
|
|
::
|
|
|
|
[
|
|
{
|
|
"tx_pos": 0,
|
|
"value": 45318048,
|
|
"tx_hash": "9f2c45a12db0144909b5db269415f7319179105982ac70ed80d76ea79d923ebf",
|
|
"height": 437146
|
|
},
|
|
{
|
|
"tx_pos": 0,
|
|
"value": 919195,
|
|
"tx_hash": "3d2290c93436a3e964cfc2f0950174d8847b1fbe3946432c4784e168da0f019f",
|
|
"height": 441696
|
|
}
|
|
]
|
|
|
|
|
|
blockchain.address.subscribe
|
|
============================
|
|
|
|
Subscribe to a bitcoin address.
|
|
|
|
blockchain.address.subscribe(**address**)
|
|
|
|
**address**
|
|
|
|
The address as a Base58 string.
|
|
|
|
**Response**
|
|
|
|
The *status* [1]_ of the address.
|
|
|
|
**Notifications**
|
|
|
|
As this is a subcription, the client will receive a notification
|
|
when the status of the address changes. The parameters are:
|
|
|
|
[**address**, **status**]
|
|
|
|
.. [1] To calculate the *status* of an address, order confirmed
|
|
transactions touching the address by height (and position in
|
|
the block if there are more than one in a block). Form a
|
|
string that is the concatenation of strings 'tx_hash:height:'
|
|
for each transaction in order. *tx_hash* is the transaction
|
|
hash in hexadecimal, *height* the height of the block it is in.
|
|
Next, with mempool transactions in any order, append a string
|
|
that is the same, but where *height* is `-1` if the transaction
|
|
has at least one unconfirmed input, and `0` if all inputs are
|
|
confirmed. The *status* is the **sha256** hash of this string
|
|
expressed as a hexadecimal string.
|
|
|
|
|
|
blockchain.block.get_header
|
|
===========================
|
|
|
|
Return the *deserialized header* [2]_ of the block at the given height.
|
|
|
|
blockchain.block.get_header(**height**)
|
|
|
|
**height**
|
|
|
|
The height of the block, an integer.
|
|
|
|
**Response**
|
|
|
|
.. [2] The *deserialized header* of a block is a dictionary like
|
|
so::
|
|
|
|
{
|
|
"block_height": <integer>,
|
|
'version': <integer>,
|
|
'prev_block_hash': <hexadecimal string>,
|
|
'merkle_root': <hexadecimal string>,
|
|
'timestamp': <integer>,
|
|
'bits': <integer>,
|
|
'nonce': <integer>
|
|
}
|
|
|
|
|
|
blockchain.block.get_chunk
|
|
==========================
|
|
|
|
Return a concatenated chunk of block headers. A chunk consists of a
|
|
fixed number of block headers over which difficulty is constant, and
|
|
at the end of which difficulty is retargeted.
|
|
|
|
In the case of Bitcoin a chunk is 2,016 headers, each of 80 bytes,
|
|
and chunk 5 is the block headers from height 10,080 to 12,095
|
|
inclusive. When encoded as hexadecimal, the response string is twice
|
|
as long, so for Bitcoin it is 322,560 bytes long, making this a
|
|
bandwidth-intensive request.
|
|
|
|
blockchain.block.get_chunk(**index**)
|
|
|
|
**index**
|
|
|
|
The zero-based index of the chunk, an integer.
|
|
|
|
**Response**
|
|
|
|
The binary block headers, as hexadecimal strings, in order
|
|
concatenated together.
|
|
|
|
|
|
blockchain.estimatefee
|
|
======================
|
|
|
|
Return the estimated transaction fee per kilobyte for a transaction to
|
|
be confirmed within a certain number of blocks.
|
|
|
|
blockchain.block.get_chunk(**number**)
|
|
|
|
**number**
|
|
|
|
The number of blocks to target for confirmation.
|
|
|
|
**Response**
|
|
|
|
The estimated transaction fee in coin units per kilobyte, as a
|
|
floating point number. If the daemon does not have enough
|
|
information to make an estimate, the integer `-1` is returned.
|
|
|
|
**Example Response**
|
|
|
|
::
|
|
|
|
0.00101079
|
|
|
|
|
|
blockchain.headers.subscribe
|
|
============================
|
|
|
|
Subscribe to receive block headers when a new block is found.
|
|
|
|
blockchain.headers.subscribe()
|
|
|
|
**Response**
|
|
|
|
The *deserialized header* [2]_ of the current block.
|
|
|
|
**Notification Parameters**
|
|
|
|
As this is a subcription, the client will receive a notification
|
|
when a new block is found. The parameters are:
|
|
|
|
[**header**]
|
|
|
|
|
|
blockchain.numblocks.subscribe
|
|
==============================
|
|
|
|
Subscribe to receive the block height when a new block is found. This
|
|
subscription is deprecated in favour of *blockchain.headers.subscribe*
|
|
which provides more detailed information.
|
|
|
|
blockchain.numblocks.subscribe()
|
|
|
|
**Response**
|
|
|
|
The height of the current block, an integer
|
|
|
|
**Notification Parameters**
|
|
|
|
As this is a subcription, the client will receive a notification
|
|
when a new block is found. The parameters are:
|
|
|
|
[**height**]
|
|
|
|
|
|
blockchain.relayfee
|
|
===================
|
|
|
|
Return the minimum fee a low-priority tx must pay in order to be accepted
|
|
to the daemon's memory pool.
|
|
|
|
blockchain.relayfee()
|
|
|
|
**Response**
|
|
|
|
The fee in coin units as a floating point number.
|
|
|
|
**Example Responses**
|
|
|
|
::
|
|
|
|
1e-05
|
|
|
|
::
|
|
|
|
0.0
|
|
|
|
blockchain.transaction.broadcast
|
|
================================
|
|
|
|
Broadcast a transaction to the network.
|
|
|
|
blockchain.transaction.broadcast(**raw_tx**)
|
|
|
|
**raw_tx**
|
|
|
|
The raw transaction as a hexadecimal string.
|
|
|
|
**Response**
|
|
|
|
Unfortunately the protocol version 1.0 API does not obey the JSON
|
|
specification for the response; this will be fixed in a future
|
|
version of the protocol.
|
|
|
|
If the daemon accepts the transaction, return the transaction hash
|
|
as a hexadecimal string. If the daemon rejects the transaction, the
|
|
server must not return an error, but instead return the error
|
|
message string as the result. The client needs to determine if an
|
|
error occurred by comparing the result to the expected transaction
|
|
hash.
|
|
|
|
**Response Examples**
|
|
|
|
::
|
|
|
|
'a76242fce5753b4212f903ff33ac6fe66f2780f34bdb4b33b175a7815a11a98e'
|
|
|
|
::
|
|
|
|
'258: txn-mempool-conflict'
|
|
|
|
|
|
blockchain.transaction.get
|
|
==========================
|
|
|
|
Return a raw transaction.
|
|
|
|
blockchain.transaction.get(**tx_hash**, **height**)
|
|
|
|
**tx_hash**
|
|
|
|
The transaction hash as a hexadecimal string.
|
|
|
|
**height**
|
|
|
|
The height at which it was confirmed, an integer. This parameter
|
|
is optional and ignored; it is recommended that clients do not
|
|
send it as it will be removed in a future protocol version.
|
|
|
|
**Response**
|
|
|
|
The raw transaction as a hexadecimal string.
|
|
|
|
|
|
blockchain.transaction.get_merkle
|
|
=================================
|
|
|
|
Return the markle branch to a confirmed transaction given its hash
|
|
and height.
|
|
|
|
blockchain.transaction.get(**tx_hash**, **height**)
|
|
|
|
**tx_hash**
|
|
|
|
The transaction hash as a hexadecimal string.
|
|
|
|
**height**
|
|
|
|
The height at which it was confirmed, an integer.
|
|
|
|
**Response**
|
|
|
|
A dictionary with keys *block_height*, *merkle* and *pos*.
|
|
*block_height* is the height of the block the transaction was
|
|
confirmed in. *merkle* is a list of transaction hashes the current
|
|
hash is paired with, recursively, in order to trace up to obtain
|
|
merkle root of the block, deepest pairing first. *pos* is the
|
|
0-based index of the position of the transaction in the ordered list
|
|
of transactions in the block.
|
|
|
|
**Response Examples**
|
|
|
|
::
|
|
|
|
{
|
|
"merkle":
|
|
[
|
|
"713d6c7e6ce7bbea708d61162231eaa8ecb31c4c5dd84f81c20409a90069cb24",
|
|
"03dbaec78d4a52fbaf3c7aa5d3fccd9d8654f323940716ddf5ee2e4bda458fde",
|
|
"e670224b23f156c27993ac3071940c0ff865b812e21e0a162fe7a005d6e57851",
|
|
"369a1619a67c3108a8850118602e3669455c70cdcdb89248b64cc6325575b885",
|
|
"4756688678644dcb27d62931f04013254a62aeee5dec139d1aac9f7b1f318112",
|
|
"7b97e73abc043836fd890555bfce54757d387943a6860e5450525e8e9ab46be5",
|
|
"61505055e8b639b7c64fd58bce6fc5c2378b92e025a02583303f69930091b1c3",
|
|
"27a654ff1895385ac14a574a0415d3bbba9ec23a8774f22ec20d53dd0b5386ff",
|
|
"5312ed87933075e60a9511857d23d460a085f3b6e9e5e565ad2443d223cfccdc",
|
|
"94f60b14a9f106440a197054936e6fb92abbd69d6059b38fdf79b33fc864fca0",
|
|
"2d64851151550e8c4d337f335ee28874401d55b358a66f1bafab2c3e9f48773d"
|
|
],
|
|
"block_height": 450538,
|
|
"pos": 710
|
|
}
|
|
|
|
|
|
blockchain.utxo.get_address
|
|
===========================
|
|
|
|
Return the address paid to by a UTXO. This method is optional and
|
|
deprecated.
|
|
|
|
blockchain.utxo.get_address(**tx_hash**, **index**)
|
|
|
|
**tx_hash**
|
|
|
|
The transaction hash as a hexadecimal string.
|
|
|
|
**index**
|
|
|
|
The zero-based index of the UTXO in the transaction.
|
|
|
|
**Response**
|
|
|
|
A Base58 address string, or *null*. If the transaction doesn't
|
|
exist, the index is out of range, or the output is not paid to an
|
|
address, *null* must be returned. If the output is spent *null* may
|
|
be returned.
|
|
|
|
|
|
server.banner
|
|
=============
|
|
|
|
Return a banner to be shown in the Electrum console.
|
|
|
|
server.banner()
|
|
|
|
The return value is a string.
|
|
|
|
|
|
server.donation_address
|
|
=======================
|
|
|
|
Return a server donation address.
|
|
|
|
server.donation_address()
|
|
|
|
The return value is a string.
|
|
|
|
|
|
server.peers.subscribe
|
|
======================
|
|
|
|
Return a list of peer servers. Despite the name this is not a
|
|
subscription and the server must send no notifications.
|
|
|
|
server.peers.subscribe()
|
|
|
|
**Response**
|
|
|
|
An array of peer servers. Each entry is a triple like
|
|
|
|
["107.150.45.210", "e.anonyhost.org", ["v1.0", "p10000", "t", "s995"]]
|
|
|
|
The first element is the IP address, the second is the host name
|
|
(which might also be an IP address), and the third is a list of
|
|
server features. Each feature and starts with a letter. 'v'
|
|
indicates the server maximum protocol version, 'p' its pruning limit
|
|
and is omitted if it does not prune, 't' is the TCP port number, and
|
|
's' is the SSL port number. If a port is not given for 's' or 't'
|
|
the default port for the coin network is implied. If 's' or 't' is
|
|
missing then the server does not support that transport.
|
|
|
|
|
|
Version 1.1 (provisional)
|
|
-------------------------
|
|
|
|
This protocol version is the same as version `1.0` except for the
|
|
following changes:
|
|
|
|
* improved semantics of `server.version` to aid protocol negotiation
|
|
* deprecated methods `blockchain.address.get_proof`,
|
|
`blockchain.utxo.get_address` and `blockchain.numblocks.subscribe`
|
|
have been removed.
|
|
* method `blockchain.transaction.get` no longer takes a *height*
|
|
argument
|
|
* method `blockchain.transaction.broadcast` returns errors like any
|
|
other JSON RPC call. A *tx_hash* result is only returned on
|
|
success.
|
|
* new methods `server.features` and `server.add_peer`
|
|
|
|
|
|
server.version
|
|
==============
|
|
|
|
Identify the client and inform the server the range of understood
|
|
protocol versions.
|
|
|
|
server.version(**client_name**, **protocol_version** = ["1.1", "1,1"])
|
|
|
|
**client_name**
|
|
|
|
An optional string identifying the connecting client software.
|
|
|
|
**protocol_verion**
|
|
|
|
Optional with default value ["1.1", "1,1"].
|
|
|
|
It must be a pair [`protocol_min`, `protocol_max`], each of which is
|
|
a string.
|
|
|
|
The server should use the highest protocol version both support:
|
|
|
|
protocol_version_to_use = min(client.protocol_max, server.protocol_max)
|
|
|
|
If this is below the value
|
|
|
|
min(client.protocol_min, server.protocol_min)
|
|
|
|
then there is no protocol version in common and the server must close
|
|
the connection. Otherwise it should send a response appropriate for
|
|
that protocol version.
|
|
|
|
**Response**
|
|
|
|
A string
|
|
|
|
"m.n"
|
|
|
|
identifying the server and the protocol version that will be used
|
|
for future communication.
|
|
|
|
**Example**
|
|
|
|
::
|
|
|
|
server.version('2.7.11', ["1.0", "2.0"])
|
|
|
|
|
|
server.add_peer
|
|
===============
|
|
|
|
This call is intended for a new server to get itself into the server's
|
|
peers list.
|
|
|
|
server.add_peer(**features**)
|
|
|
|
* **features**
|
|
|
|
The same information as a call to the client server's
|
|
**server.features** RPC call would return.
|
|
|
|
|
|
server.features
|
|
===============
|
|
|
|
Get a list of features and services supported by the server.
|
|
|
|
server.features()
|
|
|
|
**Response**
|
|
|
|
A dictionary of keys and values. Each key represents a feature or
|
|
service of the server, and the value gives additional information.
|
|
|
|
The following features MUST be reported by the server. Additional
|
|
key-value pairs may be returned.
|
|
|
|
* **hosts**
|
|
|
|
An dictionary, keyed by host name, that this server can be reached
|
|
at. Normally this will only have a single entry; other entries can
|
|
be used in case there are other connection routes (e.g. Tor).
|
|
|
|
The value for a host is itself a dictionary, with the following
|
|
optional keys:
|
|
|
|
* **ssl_port**
|
|
|
|
An integer. Omit or set to *null* if SSL connectivity is not
|
|
provided.
|
|
|
|
* **tcp_port**
|
|
|
|
An integer. Omit or set to *null* if TCP connectivity is not
|
|
provided.
|
|
|
|
A server should ignore information provided about any host other
|
|
than the one it connected to.
|
|
|
|
* **genesis_hash**
|
|
|
|
The hash of the genesis block. This is used to detect if a peer is
|
|
connected to one serving a different network.
|
|
|
|
* **server_version**
|
|
|
|
A string that identifies the server software. Should be the same as
|
|
the response to **server.version** RPC call.
|
|
|
|
* **protocol_max**
|
|
* **protocol_min**
|
|
|
|
Strings that are the minimum and maximum Electrum protcol versions
|
|
this server speaks. The maximum value should be the same as what
|
|
would suffix the letter **v** in the IRC real name. Example: "1.1".
|
|
|
|
* **pruning**
|
|
|
|
An integer, the pruning limit. Omit or set to *null* if there is no
|
|
pruning limit. Should be the same as what would suffix the letter
|
|
**p** in the IRC real name.
|
|
|
|
**Example Response**
|
|
|
|
::
|
|
|
|
{
|
|
"genesis_hash": "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
|
|
"hosts": {"14.3.140.101": {"tcp_port": 51001, "ssl_port": 51002}},
|
|
"protocol_max": "1.0",
|
|
"protocol_min": "1.0",
|
|
"pruning": null,
|
|
"server_version": "ElectrumX 1.0.1"
|
|
}
|
|
|
|
.. _JSON RPC 1.0: http://json-rpc.org/wiki/specification
|
|
.. _JSON RPC 2.0: http://json-rpc.org/specification
|
|
|