Skip to content
Title: getblocktemplatelight
Type: API/RPC
Version: 1.0.2
Status: Draft
Created: 2020-04-28
Authors: freetrader <freetrader@tuta.io>
         Calin Culianu <calin.culianu@gmail.com>
         Dagur Valberg Johannsson <dagurval@pvv.ntnu.no>
         BigBlockIfTrue <info@bitcoinlogo.eu>
License: CC0-1.0
Comments-URI: https://gitlab.com/bitcoin-cash-node/bitcoin-cash-node/-/merge_requests/284
Comments-Summary: BCHN internal review comments.

getblocktemplatelight

Abstract

A set of RPC calls are proposed to implement a faster, lighter getblocktemplate [1,2] mechanism, referred to below by the abbreviation 'GBTL' (for "getblocktemplate light").

Motivation

Significant time in obtaining block templates and submitting block candidates can be saved by exchanging more concise transaction data (in the form of Merkle branch hashes instead of the full list of transaction id hashes) and caching these template "jobs" in a way that allows submission of far less data once a block has been mined.

The submitted block can be reconstructed from a submitted valid header and a job id identifying the transaction hashes which are stored on disk or in memory.

At the time of writing, getblocktemplatelight is the de facto standard in parts of the Chinese mining community. This document is a formalization of this protocol (see also Appendix A).

Terms and conventions

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 RFC 2119.

Specification

Two new RPC calls are introduced: getblocktemplatelight and submitblocklight.

getblocktemplatelight

This call returns concise information that can be used by a miner to construct a valid block header based on a chosen coinbase transaction.

GBTL-RETURN-VALUES-REQ-1

The getblocktemplatelight RPC call SHALL return

  1. a job id (JSON string) not exceeding 128 bytes. The exact job id structure is implementation-dependent.

  2. a list of Merkle path hashes to allow miner to quickly construct a valid header by computing the Merkle root once he decides on a coinbase transaction.

NOTE: The first element of the Merkle path list will be a transaction hash (the first transaction is hashed with the future coinbase transaction). Refer to Appendix B for information on how the Merkle root is computed. Implementations are allowed to impose more severe size restrictions on the size of the job id string, for example the Bitcoin Cash Node implementation uses 40 characters.

GBTL-INPUT-ADDITIONAL-TXS-1

The getblocktemplate call SHALL support an optional input argument consisting of a JSON array of strings which contain hex encoded transactions that must be included in the future block in addition to the transactions proposed by the software.

NOTE! Such additional transactions are not validated by the software. It is the responsibility of the miner to ensure such transactions are valid, do not conflict with each other, and do not conflict with any transaction in the mempool. If he fails to do so, an invalid block could be generated.

GBTL-INPUT-ADDITIONAL-TXS-2

If the additional_txs contain data that cannot be deserialized as a transaction, the software shall raise RPC_DESERIALIZATION_ERROR (code -22).

Optionally, it should provide an indication of which of the additional_txs failed to deserialize.

GBTL-JOB-ID-REQ-1

The job id generated by getblocktemplate SHALL uniquely identify the invariant block header data and non-coinbase transactions included in the block.

NOTE: this means that repeated calls to getblocktemplatelight may return the same job id as long as the template header information and the proposed set of transaction (resulting in a given Merkle path) has not changed.

GBTL-JOB-PERSIST-REQ-1

The running software SHALL persist an implementation-defined number of jobs, at least in memory but optionally they can be stored on disk (this is up to an implementation - see GBTL-JOB-PERSIST-REQ-2).

For each job, the full list of transactions (excluding future coinbase) SHALL be stored to allow quick reassembly of the block once a miner submits a valid header using the submitblocklight call.

(optional) GBTL-JOB-PERSIST-REQ-2

An implementation-defined number of jobs SHOULD persist across a stop-start cycle of the node software (implementing this requires some form of persistent storage of jobs).

(optional) GBTL-JOB-PERSIST-REQ-3

An implementation-defined number of jobs SHOULD persist across a power cycle of the node (also requires persistent storage of jobs).

(optional) GBTL-JOB-PERSIST-REQ-4

The number of jobs to persist (in memory or disk) SHOULD be configurable.

(optional) GBTL-JOB-PERSIST-REQ-5

The storage location of jobs persisted on disk SHOULD be configurable.

(optional) GBTL-JOB-CLEAN-REQ-1

If an implementation persists jobs on disk for some time, then it SHOULD offer a configurable mechanism for them to be automatically deleted in order to conserve disk space.

submitblocklight

This call submits a serialized block (consisting of only header plus a single coinbase transaction) and a job id (encoded as a string) which is used by the software to look up the remaining transactions, complete the block and submit it to the network.

The table below gives information about the serialized block data that is expected.

Field Name Type Size Encoding Purpose
header block header 80 bytes standard, see [5] The header of the block being provided
txn_count compactSize uint variable (1) standard, see [6] The number of transactions in the block (must be 1 in this case)
coinbase raw transaction variable (2) standard, see [7,8] The coinbase of the block being provided

Notes:

(1) Since the value of this field must be 1, its size is effectively fixed at 1 byte.

(2) The coinbase field has an enforced minimum size of 100 bytes. Also, block construction typically reserves some space for the coinbase. For example, in the Bitcoin Cash Node software a maximum of 1000 bytes are reserved for the coinbase by default - this should be taken into account when a larger coinbase needs to be included.

GBTL-SUBMIT-CHECK-REQ-1

Upon receiving a job id and serialized block data, the software SHALL verify that the job information is available or raise an error with a message indicating that the job data could not be found.

GBTL-SUBMIT-CHECK-REQ-2

Upon receiving a job id and serialized block data, the software SHALL verify that it only contains a single transaction which must be a coinbase transaction or else an RPC error is raised with a message indicating that the block must only contain a single coinbase transaction.

GBTL-SUBMIT-PROCESS-REQ-1

After validating the preconditions of job and block data, the software SHALL reassemble the entire block from the list of transactions stored for the job and subject the block for further processing (as a newly found block would be - same as is done by submitblock).

Rationale

The maximum length of the job id has been chosen as 128 characters in order to fit a hex representation of a SHA512 hash value. In practice implementations may use shorter job ids based on whatever they see fit.

Considerations for future improvement

  1. An additional safety feature related to this could be added to validate additional transactions passed to getblocktemplatelight (see Note under GBTL-INPUT-ADDITIONAL-TXS-REQ-1).

Reference implementation

A C++ reference implementation is available in Bitcoin Cash Node merge request 281.

Example outputs

$ bitcoin-cli getblocktemplatelight
{
  "capabilities": [
    "proposal"
  ],
  "version": 536870912,
  "previousblockhash": "0000000000000000042c6826483e2685eaef05e5453629c942d80ff181b7ee56",
  "job_id": "99316ebfef1808a7c7280bcebcf5a1695469e28e",
  "merkle": [
    "001c508a25ba65ba917dd9149cb33cb50eb7806fceed1f03ee72d8765e0b12da",
    "7aa030049cc0886263a524f4b3480e129881ed338a4058c428d8207d55248f75",
    "ddaca54ad69f000fd936f8e18a72a48475a600523157d998a3237dc7b6714855",
    "2db245d92e7a2ce758ffc5c92227ea71fe5600d4a03b6242214bfd8f422f343c",
    "aa3c9c1d0cbc276c2ef59037fdb444cc6f8957c6ff705444bf632d61b8671f74",
    "6841ab7320310b44028e1993247da489612eff893fe935af31db21701867a072",
    "7de33d790ceca3d21b3e53c7aa7ca463aac248c4497b26b38ae935ce200e72c4",
    "e05b643007ba1722c0660f7c650dc174f67c3058061c83897f46b7e23dfb08b2",
    "415b3a646bd8ebc7faffebc7bb282067e3e0ebc3025c828ae90dfeceed58253b",
    "7c5982ab62e5608ad138d2fb81b8ed7d155cf604dc38113463bda51249a1df0f",
    "32589d2dec148272240bee5410cff8111b895c36e907a9fabbc29978f646fde3"
  ],
  "coinbaseaux": {
    "flags": ""
  },
  "coinbasevalue": 625822167,
  "longpollid": "0000000000000000042c6826483e2685eaef05e5453629c942d80ff181b7ee56109391",
  "target": "0000000000000000046ae3000000000000000000000000000000000000000000",
  "mintime": 1588182851,
  "mutable": [
    "time",
    "job_id",
    "merkle",
    "prevblock"
  ],
  "noncerange": "00000000ffffffff",
  "sigoplimit": 640000,
  "sizelimit": 32000000,
  "curtime": 1588193732,
  "bits": "18046ae3",
  "height": 632977
}

Appendices

Appendix A - Historical context

This specification is based on an adaptation by Bitcoin Cash Node of a concept originally implemented by BTC.com (at least as far as we know). The original implementation is available at [3].

Bitcoin Unlimited has previously released a similar feature (in v1.4.0.0 of its client) consisting of two RPC calls called getminingcandidate and submitminingsolution [9].

There is an ASCII diagram with additional explanations of the Merkle branch construction in the Bitcoin Cash Node source code [4].

Appendix B - Computation of Merkle root from coinbase + branch

Below is pseudo-code for the computation of the Merkle root from a coinbase transaction and the Merkle branch hashes provided by the getblocktemplatelight command.

define sha256d( s ) := sha256( sha256( s ) )

let cb_hash = sha256d( coinbase_raw_tx )

// merkle_branch_hashes are the ordered list of hashes of the
// `merkle` output field of `getblocktemplatelight`
hashes = [ cb_hash ].append( merkle_branch_hashes )

loop while length( hashes ) > 1:
    hashes[0] = sha256d( concatenate( hashes[0], hashes[1] ) )
    delete hashes[1]

merkle_root = hashes[0]

References

This document is licensed under the Creative Commons CC0 1.0 Universal license.