Skip to content

Overview

A block is a collection of transactions that have been committed to the blockchain as a bundle. The transactions do not necessarily have to be related to one another and, generally, are only associated by virtue of when they were submitted to the Nexa network.

Every block contains one coinbase transaction, followed by zero or more additional transactions. The coinbase transaction is created by the miner of the block and provides an opportunity for them to receive the block reward for successfully mining a block, along with any fees collected from the transactions in the block. For more information, see Mining.

Block Header

Blocks are identified by the double SHA-256 hash of their header. Since the block header contains the root of a Merkle Tree of the transactions in the block, this means the hash is ultimately dependent on both the block header and the full contents of all of its component transactions.

Block headers serve an important intermediary role in the creation and transmission of blocks. They are a fixed-width (80-byte) representation of the entire block. With a block header, you can:

  1. Calculate the hash of the block.
    • The double SHA-256 hash of the block header.
  2. Confirm the proof of work was executed correctly.
  3. Determine the relative location of the block in the blockchain.
    • Using the previous block hash contained in the header

Since validation of all the transactions in the block can be expensive, the ability to perform these checks on the block before downloading and validating its transactions helps make denial-of-service attacks on the network significantly more expensive for attackers.

Block Header Format

Field Length Format Description
previous block hash 32 bytes block hash(LE) The hash of the block immediately preceding this block in the blockchain.
target 4 bytes compressed target(LE) The target that the block hash must be below to be valid. This value is determined by the timestamps of previously mined blocks. See Target for more information.
ancestor hash 32 bytes block hash(LE) The hash of a specific ancestor block (see ancestorHash spec.
merkle tree root hash 32 bytes merkle root(LE) The merkle tree root of the transactions in the block.
transaction filter hash 32 bytes MUST BE ZERO(LE) Currently defined as 0, this will be populated with the hash of a probabilistic data structure that summarizes the transactions in the block
timestamp 4 bytes unix timestamp(LE) The epoch timestamp of the block in seconds.
height variable varint Current height of this block in the blockchain (genesis block is height 0).
chain work 32 bytes uint256(LE) The cumulative expected work in the blockchain, including this block
size 8 bytes uint64(LE) Block size in bytes, excluding the nonce
transaction count variable varint Number of transactions in the block
fee pool amount variable varint (MUST BE 0) Currently defined as 0, this will be the current value of satoshis in a fee pool
UTXO commitment variable bytes byte vector (MUST BE LENGTH 0) Currently defined as a vector of length zero, this will be a commitment to the current UTXO data set
Miner Data variable bytes byte vector (MUST BE LENGTH 0) Currently defined as a vector of length zero, this will be a structure where miners make well-defined statements
nonce variable bytes byte vector of length less than or equal to 16 bytes A random value that is repeatedly changes during block mining in order to achieve the proof-of-work requirements.

Specific Field Descriptions/Caveats

Size field

Note that the size field is the size of the serialized block, without the nonce field. Or, since the nonce field is serialized as an array and is therefore preceded with a 1 byte length field.

size = serializedLengthOf(block) - (nonce.length + 1)

Compressed Target Format

Within the block header, the target uses a special floating-point representation that helps keep the size of the block header small. While the difficulty adjustment algorithm attempts to calculate the ideal target (i.e. the value the block hash must be "less than"), it undergoes a lossy conversion when put in the block header:

Field Length Format Description
exponent 1 byte byte Used to calculate the offset for the signficand. The actual exponent is 8 * (exponent - 3).
significand 3 byte bytes The significand, or mantissa, of the value.

Ultimately, the target is equal to:

significand * 2(8 * (exponent - 3))

Byte Vector Format

Vectors are serialized with a prefix byte specifying the length of the vector, and then the bytes of the vector.

Block Hash

The first thing to note is that unlike Bitcoin and Bitcoin Cash the mining puzzle solution (Proof-of-work problem) is separated out from the block hash. This was done because the Nexa mining puzzle is both computationally expensive and algorithmically expensive (that is, more work to implement). There is no need for all that if you just want to get a probabilistically unique identifier for a block.

Block Hash Algorithm

In the following algorithm description "sha256()" refers to the SHA-256 cryptographic hash algorithm. This algorithm operates over an array of bytes. Any argument provided is serialized using the standard Nexa/Bitcoin Cash/Bitcoin serialization algorithm (HASH variant). Within the context of serialization, the "||" operator denotes byte array concatenation.

The algorithm is as follows:

  1. SHA-256 the "miniheader", which is hashprevblock and nbits.

    miniheaderhash = sha256(hashprevblock || nbits)
    

  2. SHA-256 the rest of the stuff. Here is the list:

    extheaderhash = sha256(hashAncestor || hashTxFilter || hashMerkleRoot || nTime || ((uint64_t)height) || chainWork || size || txCount || feePoolAmt || utxoCommitment || minerData || nonce)
    

  3. (Note that the "size" field is the size of the block without the nonce, see above)

  4. The block hash is the SHA-256 of these two hashes:

blockhash = SHA256( miniHeaderHash ||  extendedHeaderHash)

Coinbase Transaction

The coinbase transaction provides a mechanism for miners to:

  • Receive payment for mining.
  • Include a message, known as the "coinbase message" within the block.

The coinbase transaction MUST have no inputs and be the first transaction in the block. The last output of the coinbase transaction MUST be an OP_RETURN (data carrier) script.

The satoshis that appear in the outputs of the coinbase transaction are collected from two places: the block reward and transactions fees. Transaction fees are often required by the network for transactions to be relayed across the network. Satoshis provided as inputs to a transaction, but not consumed by its outputs, are collected by the coinbase transaction as implicit inputs.

The last output is required to begin with OP_RETURN, followed by a push of the block height, and finally the coinbase message (which can be whatever data is desired). The block height encoded as a minimally-encoded script number (see transaction scripts).

Block Size

The maximum block size for blocks varies based on prior block sizes. For more information see Adaptive Block Size.