Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_build/
6 changes: 3 additions & 3 deletions conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
VERSION="Fulcrum Protocol Reference 1.5.1"
VERSION="Fulcrum Protocol Reference 1.6.0"

# -- Project information -----------------------------------------------------

project = 'Electrum Cash Protocol'
copyright = '2016-2019, Neil Booth, 2020-2024, Calin Culianu'
copyright = '2016-2019, Neil Booth, 2020-2025, Calin Culianu'
author = 'Neil Booth, Calin Culianu, Electrum Cash protocol devs'

# The full version including branding
Expand Down Expand Up @@ -58,7 +58,7 @@
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
language = 'en'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
Expand Down
25 changes: 23 additions & 2 deletions protocol-basics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Two standards `JSON RPC 1.0
<http://www.jsonrpc.org/specification_v1>`_ and `JSON RPC 2.0
<http://www.jsonrpc.org/specification>`_ are specified; use of version
2.0 is encouraged but not required. Server support for batch requests
*is* implemented in Fulcrum as of version 1.6.0.
*is* implemented in Fulcrum as of Fulcrum version 1.6.0.

.. note::
A client or server should only indicate JSON RPC 2.0 by
Expand Down Expand Up @@ -154,7 +154,7 @@ block)

* ``height`` is the height of the block it is in.

3. Next, with mempool transactions in any order, append a similar
3. Next, with mempool transactions in a :ref:`canonical order <mempoolorder>`, append a similar
string for those transactions, but where **height** is ``-1`` if the
transaction has at least one unconfirmed input, and ``0`` if all
inputs are confirmed.
Expand Down Expand Up @@ -371,3 +371,24 @@ serialized input. So for example if the transaction's input serialized and hashe

Then possible prefixes would be either: :const:`"a"` (4 bit prefix of the above hash), :const:`"ab"` (8 bit prefix of the above hash),
:const:`"abc"` (12 bit prefix of the above hash), or :const:`"abcd"` (16 bit prefix of the above hash).


.. _mempoolorder:

Mempool Transaction Ordering
----------------------------

The protocol specifies a canonical ordering for mempool transactions. This ordering is not necessarily topological
ordering, but is something simpler. The mempool ordering in this protocol is specified as follows: mempool transactions
are sorted in ascending order using the following pseudo-code comparator function (where :const:`a` and :const:`b` are
mempool transactions to be compared)::

(a.hasUnconfirmedParents, a.txHash) < (b.hasUnconfirmedParents, b.txHash)

That is, transactions are sorted such that all transactions with no unconfirmed parents appear as a grouping before
all transactions with unconfirmed parents, and within each grouping, they are sorted by their transaction hash (as a
string).
Comment on lines +389 to +390

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note the txid is in network byte-order here, not the human-readable form

@cculianu cculianu Oct 24, 2025

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review here.

In Fulcrum, internally, I keep the hashes as bytes but in human-readable byte order always (to avoid having to reverse them when presenting them to RPCs or in human-readable form) -- Electron Cash on BCH also assumes this now. This kind of throws a wrench into the works for me to have to change this... why are you keeping them in memory in non-human readable form anyway? It's just wasted cycles to do that since internally you don't really care about exact hash value you just care about communicating to the client (in human readable hex form) and to the daemon (again, in the same ordering).

Hmm... :/


Note that the only reason the hash is "reversed" when stringified in bitcoind anyway is due to a historical quirk of sorts -- the hashes (sometimes) were uint256 values treated as a little-endian integer (as is the case with a block hash). They ended up getting "reversed" so they print nicely because humans read numbers in big endian order.

But most hashes are never internally treated as integers anymore so.. the whole reversing-them-to-print is kind of nonsensical in the first place... but since that stupidity is enforced in the RPC interface and when printing hashes.. better to keep them in memory in the "ready to print" and "ready to send to RPC" form when communicating with bitcoind, clients, etc, if you ask me.


Certain concepts in the protocol such as the :ref:`status hash <status>` make use of this ordering. Additionally,
certain methods, such as :func:`blockchain.scripthash.get_mempool` and :func:`blockchain.scripthash.get_history` may
return a list of transactions from the mempool in this order.
61 changes: 39 additions & 22 deletions protocol-changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Protocol Changes
================

This documents lists changes made by protocol version.
This document lists changes made by protocol version.

Version 1.0
===========
Expand Down Expand Up @@ -150,18 +150,6 @@ Removed methods
Version 1.4.1
=============

Changes
-------

* :func:`blockchain.block.header` and :func:`blockchain.block.headers` now
truncate AuxPoW data (if using an AuxPoW chain) when *cp_height* is
nonzero. AuxPoW data is still present when *cp_height* is zero.
Non-AuxPoW chains are unaffected.


Version 1.4.1
=============

New methods
-----------

Expand Down Expand Up @@ -270,19 +258,48 @@ Version 1.5.2
New methods
-----------

* :func:`blockchain.header.get` to retrieve a block header by its hash.
* :func:`blockchain.scripthash.get_first_use` and :func:`blockchain.address.get_first_use` to retrieve
the first occurrence of a script hash or address on the block chain.
* :func:`blockchain.transaction.get_confirmed_blockhash` to retrieve the block hash of the block that
contains a particular transaction.
* :func:`daemon.passthrough` to forward RPC requests directly through to the bitcoin daemon (disabled by default).
* :func:`blockchain.header.get` to retrieve a block header by its hash.
* :func:`blockchain.scripthash.get_first_use` and :func:`blockchain.address.get_first_use` to retrieve
the first occurrence of a script hash or address on the block chain.
* :func:`blockchain.transaction.get_confirmed_blockhash` to retrieve the block hash of the block that
contains a particular transaction.
* :func:`daemon.passthrough` to forward RPC requests directly through to the bitcoin daemon (disabled by default).

Version 1.5.3
=============

New methods
-----------

* :func:`blockchain.rpa.get_history` and :func:`blockchain.rpa.get_mempool` to retrieve transactions matching a certain RPA (reusable payment address) prefix.
* :func:`blockchain.reusable.get_history` and :func:`blockchain.reusable.get_mempool` which are compatibility-versions of the above for legacy clients.
* :func:`server.features` added a new optional key, :const:`"rpa"`.
* :func:`blockchain.rpa.get_history` and :func:`blockchain.rpa.get_mempool` to retrieve transactions matching a certain RPA (reusable payment address) prefix.
* :func:`blockchain.reusable.get_history` and :func:`blockchain.reusable.get_mempool` which are compatibility-versions of the above for legacy clients.
* :func:`server.features` added a new optional key, :const:`"rpa"`.

Version 1.6.0
=============

Changes
-------

* The status of a scripthash has its definition tightened in a backwards-compatible way: mempool txs now have a
:ref:`canonical ordering <mempoolorder>` specified for the calculation (previously their order was unspecified).
* :func:`blockchain.estimatefee` changed to allow for an optional second argument, *mode*.
* :func:`blockchain.scripthash.get_mempool`, :func:`blockchain.scripthash.get_history`,
:func:`blockchain.address.get_mempool`, and :func:`blockchain.address.get_history` previously did not define an
order for mempool transactions. We now mandate a :ref:`canonical ordering <mempoolorder>`.
* :func:`blockchain.block.headers` now returns headers as a list, instead of a single concatenated hex string
* :func:`server.features` now may return an additional optional boolean key, `broadcast_package` to indicate the
server provides :func:`blockchain.transaction.broadcast_package`.

New methods
-----------

* :func:`blockchain.transaction.broadcast_package` to broadcast a package of transactions via `submitpackage`
(BTC only).
* :func:`mempool.get_info` to get more detailed and general relayfee info.

Deprecated methods
------------------

* :func:`blockchain.relayfee`. Switch to :func:`mempool.get_info`.

Loading