# # Transactions Root Hash

The `transactionsRoot`

field in the block header contains the root hash of the Merkle tree (opens new window) of transactions of the block. The root hash is the proof that the block contains all the transactions in the proper order.

The transactions root hash in the block header has the following purposes:

- To prove the integrity of transactions in the block without presenting all transactions.
- To sign the block header only, separately from its transactions.

⚠️

`transactionsRoot`

is enabled by feature #15 “Ride V4, VRF, Protobuf, Failed transactions”.

## # transactionsRoot Calculation

The hash of each transaction in the block is calculated. For example:

H

_{A}= hash(T_{A})H

_{B}= hash(T_{B})etc.

Each pair of adjacent hashes is concatenated, and the hash is calculated for each resulting concatenation:

H

_{AB}= hash(H_{A}+ H_{B})If the last hash does not have a pair, it is concatenated with the zero byte hash:

H

_{GH}= hash(H_{G}+ hash(0))Step 2 is repeated until the root hash is obtained:

H

_{ABCDEFGH}The root hash is written in the

`transactionsRoot`

field.

If the block is empty, then

`transactionsRoot`

= hash(0).

Waves blockchain uses BLAKE2b-256 (opens new window) hashing function.

## # Proof of Transaction in Block

Let's suppose that side 1 stores the full blockchain data and side 2 stores the block headers only.

To prove that the block contains a given transaction, side 1 provides the following data:

`T`

: Transaction to check.`merkleProofs`

: Array of sibling hashes of the Merkle tree, bottom-to-top.`index`

: Index of the transaction in the block.

For example, for the T_{D} transaction:

`merkleProofs`

= [ H_{C}, H_{AB}, H_{EFGH}]`index`

= 3

Side 2 checks the proof:

It calculates the hash of the transaction being checked (all the transaction data is hashed, including the signature):

H

_{D}= hash(T_{D})It concatenates the current hash with the corresponding hash of the

`merkleProofs`

array and calculates the hash of concatenation.`index`

determines in which order to concatenate the hashes:• If the

`n`

th bit of`index`

from the end is 0, then the order is: the current hash + the`n`

th hash of the`merkleProofs`

array (proof hash is on the right). • If the`n`

th bit is 1, the order is: the`n`

th hash of the`merkleProofs`

array + the current hash (proof hash is on the left).For example,

`index`

= 3_{10}= 11_{2}, thus:•

`merkleProofs`

[0] = H_{C}is on the left, •`merkleProofs`

[1] = H_{AB}is on the left, •`merkleProofs`

[2] = H_{EFGH}is on the right.It repeates Step 2 until the root hash is obtained:

H

_{ABCDEFGH}It compares the root hash obtained with the already known

`transactionsRoot`

from the block header. If the hashes match, then the transaction exists in the block.

## # Tools

The following Node API methods accept transaction IDs and provide the proof that the transaction is in a block for each transaction:

`GET /transactions/merkleProof`

`POST /transactions/merkleProof`

The methods are described in the Transaction article.

You can check a transaction on the same blockchain without using a root hash, since the Waves node stores the full blockchain data, including all transactions. Use the following built-in Ride function:

```
transactionHeightById(id: ByteVector): Int|Unit
```

The function returns the block height if the transaction with the specified `id`

exists. Otherwise, it returns `unit`

. See the function description in the Blockchain functions article.

To check a transaction in a block on the external blockchain you can use the following built-in Ride function:

```
createMerkleRoot(merkleProofs: List[ByteVector], valueBytes: ByteVector, index: Int): ByteVector
```

This function is applicable if the external blockchain uses the same algorithm for calculating the root hash of transactions (for instance, external blockchain is Waves-based). The `createMerkleRoot`

function calculates the root hash from the transaction hash and sibling hashes of the Merkle tree (see Steps 1–3). To check a transaction in a block, compare the calculated root hash with the `transactionsRoot`

value in the block header. See the function description in the Verification functions article.