# Besu documentation
> Official Besu documentation: public Ethereum networks, permissioned / private networks, APIs, configuration, and operations.
This file contains all documentation content in a single document following the llmstxt.org standard.
## Data storage formats
Besu offers two formats for storing the world state, [Bonsai Tries](#bonsai-tries) and [Forest of Tries](#forest-of-tries).
## Bonsai Tries
Bonsai Tries is a data storage layout policy designed to reduce storage requirements and increase read performance. This is the default for Besu.
Bonsai stores leaf values in a trie log, separate from the branches of the trie. Bonsai stores nodes by the location of the node instead of the hash of the node. Bonsai can access the leaf from the underlying storage directly using the account key. This greatly reduces the disk space needed for storage and allows for less resource-demanding and faster read performance. Bonsai inherently prunes orphaned nodes and old branches.
To run a node with Bonsai Tries data storage format, use the command line option [`--data-storage-format=BONSAI`](../reference/options.md#data-storage-format).

:::caution important
Do not run an [archive node](node-sync.md#archive-nodes) with Bonsai Tries.
Bonsai is designed for retrieving recent data only.
:::
:::tip
You can read more about Bonsai in [Consensys' Guide to Bonsai Tries](https://consensys.io/blog/bonsai-tries-guide).
:::
## Forest of Tries
Forest of Tries, also called forest mode, is another method of representing the world state, and is more suitable for [archive nodes](node-sync.md#archive-nodes).
In forest mode, each node in the trie is saved in a key-value store by hash. For each block, the world state is updated with new nodes, leaf nodes, and a new state root. Old leaf nodes remain in the underlying data store. Data is accessed and stored by hash, which increases the size of the database and increases the resources and time needed to access account data.

:::warning
Forest pruning using the `--pruning-enabled` option is no longer supported.
We recommend using [Bonsai Tries](#bonsai-tries) to save disk space.
:::
## Forest of Tries vs. Bonsai Tries
### Storage estimates
Mainnet storage requirements change over time as the chain grows.
Use the following estimates as a reference point, not fixed minimum requirements.
| Data storage format | Sync mode | Node type | Mainnet storage estimate |
|---------------------|-----------|--------------|---------------------------|
| Bonsai | [Snap](node-sync.md#snap-synchronization) | [Full node](node-sync.md#full-nodes) | ~1.14 TB |
| Forest | [Full](node-sync.md#full-synchronization) | [Archive node](node-sync.md#archive-nodes) | ~12 TB |
The Bonsai snap sync estimate is based on May 2026 burn-in results for the Besu 26.5.0
release cycle on AWS `m8g.2xlarge` instances.
By default, snap sync prunes historical block data for PoW blocks, retaining only the headers and the genesis block.
Downloading full PoW blocks (by setting [`--snapsync-synchronizer-pre-checkpoint-headers-only-enabled=false`](../reference/options.md#snapsync-synchronizer-pre-checkpoint-headers-only-enabled)) increases disk usage.
Forest mode uses significantly more memory than Bonsai, and we do not recommend using it on Mainnet.
### Accessing data
Forest mode must go through all the branches by hash to read a leaf value. Bonsai can access the leaf from the underlying storage directly using the account key. Bonsai will generally read faster than forest mode, particularly if the blocks are more recent.
However, Bonsai becomes increasingly more resource-intensive the further in history you try to read data. To prevent this, you can limit how far Bonsai looks back while reconstructing data. The default limit Bonsai looks back is 512. To change the parameter, use the [`--bonsai-historical-block-limit`](../reference/options.md#bonsai-historical-block-limit) option. This might directly impact [JSON-RPC API](../reference/api/index.md) queries.
:::note
Using `--bonsai-historical-block-limit` doesn't affect the size of the database being stored, only how far back to load. This means there is no "safe minimum" value to use with this option.
:::
---
## Events and logs
Transaction mining causes smart contracts to emit events and write logs to the blockchain.
The smart contract address is the link to the logs and the blockchain includes the logs, but contracts cannot access logs. Log storage is cheaper than contract storage (that is, it costs less gas) so storing and accessing the required data in logs reduces the cost. For example, use logs to display all transfers made using a specific contract, but not the current state of the contract.
A Dapp front end can either access logs using the [JSON-RPC API filter methods](../how-to/use-besu-api/access-logs.md) or subscribe to logs using the [RPC Pub/Sub API](../how-to/use-besu-api/rpc-pubsub.md#logs).
Use [`admin_generateLogBloomCache`](../reference/api/admin.md#admin_generatelogbloomcache) to improve log retrieval performance.
## Topics
Log entries contain up to four topics. The first topic is the [event signature hash](#event-signature-hash) and up to three topics are the indexed [event parameters](#event-parameters).
```json title="A log entry for an event with one indexed parameter"
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x84",
"blockHash": "0x5fc573d76ec48ec80cbc43f299ebc306a8168112e3a4485c23e84e9a40f5d336",
"transactionHash": "0xcb52f02342c2498df82c49ac26b2e91e182155c8b2a2add5b6dc4c249511f85a",
"transactionIndex": "0x0",
"address": "0x42699a7612a82f1d9c36148af9c77354759b210b",
"data": "0x",
"topics": [
"0x04474795f5b996ff80cb47c148d4c5ccdbe09ef27551820caa9c2f8ed149cce3",
"0x0000000000000000000000000000000000000000000000000000000000000001"
]
}
```
## Event parameters
Up to three event parameters can have the `indexed` attribute. Logs store these indexed parameters as `topics`. Indexed parameters are searchable and filterable.
Topics are 32 bytes. If an indexed argument is an array (including `string` and `byte` datatypes), the log stores the keccak-256 hash of the parameter as a topic.
Log `data` includes non-indexed parameters but is difficult to search or filter.
A Solidity contract storing one indexed and one non-indexed parameter and has an event emitting the value of each parameter:
```solidity
pragma solidity ^0.5.1;
contract Storage {
uint256 public valueIndexed;
uint256 public valueNotIndexed;
event Event1(uint256 indexed valueIndexed, uint256 valueNotIndexed);
function setValue(uint256 _valueIndexed, uint256 _valueNotIndexed) public {
valueIndexed = _valueIndexed;
valueNotIndexed = _valueNotIndexed;
emit Event1(_valueIndexed, _valueNotIndexed);
}
}
```
A log entry created by invoking the contract in the previous example with `valueIndexed` set to 5 and `valueNotIndexed` set to 7:
```json
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x4d6",
"blockHash": "0x7d0ac7c12ac9f622d346d444c7e0fa4dda8d4ed90de80d6a28814613a4884a67",
"transactionHash": "0xe994022ada94371ace00c4e1e20663a01437846ced02f18b3f3afec827002781",
"transactionIndex": "0x0",
"address": "0x43d1f9096674b5722d359b6402381816d5b22f28",
"data": "0x0000000000000000000000000000000000000000000000000000000000000007",
"topics": [
"0xd3610b1c54575b7f4f0dc03d210b8ac55624ae007679b7a928a4f25a709331a8",
"0x0000000000000000000000000000000000000000000000000000000000000005"
]
}
```
## Event signature hash
The first topic in a log entry is always the event signature hash. The event signature hash is a keccak-256 hash of the event name and input argument types, with argument names ignored. For example, the event `Hello(uint256 worldId)` has the signature hash `keccak('Hello(uint256)')`. The signature identifies to which event log topics belong.
A Solidity contract with two different events:
```solidity
pragma solidity ^0.5.1;
contract Storage {
uint256 public valueA;
uint256 public valueB;
event Event1(uint256 indexed valueA);
event Event2(uint256 indexed valueB);
function setValue(uint256 _valueA) public {
valueA = _valueA;
emit Event1(_valueA);
}
function setValueAgain(uint256 _valueB) public {
valueB = _valueB;
emit Event2(_valueB);
}
}
```
The event signature hash for event 1 is `keccak('Event1(uint256)')` and the event signature hash for event 2 is `keccak('Event2(uint256)')`. The hashes are:
- `04474795f5b996ff80cb47c148d4c5ccdbe09ef27551820caa9c2f8ed149cce3` for event 1
- `06df6fb2d6d0b17a870decb858cc46bf7b69142ab7b9318f7603ed3fd4ad240e` for event 2.
:::tip
You can use a library keccak (sha3) hash function, such as provided in [Web3.js](https://web3js.readthedocs.io/en/v1.2.11/web3-utils.html?highlight=sha3#sha3), or an online tool, such as https://emn178.github.io/online-tools/keccak_256.html, to generate event signature hashes.
:::
Log entries from invoking the Solidity contract in the previous example:
```json
[
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x84",
"blockHash": "0x5fc573d76ec48ec80cbc43f299ebc306a8168112e3a4485c23e84e9a40f5d336",
"transactionHash": "0xcb52f02342c2498df82c49ac26b2e91e182155c8b2a2add5b6dc4c249511f85a",
"transactionIndex": "0x0",
"address": "0x42699a7612a82f1d9c36148af9c77354759b210b",
"data": "0x",
"topics": [
"0x04474795f5b996ff80cb47c148d4c5ccdbe09ef27551820caa9c2f8ed149cce3",
"0x0000000000000000000000000000000000000000000000000000000000000001"
]
},
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x87",
"blockHash": "0x6643a1e58ad857f727552e4572b837a85b3ca64c4799d085170c707e4dad5255",
"transactionHash": "0xa95295fcea7df3b9e47ab95d2dadeb868145719ed9cc0e6c757c8a174e1fcb11",
"transactionIndex": "0x0",
"address": "0x42699a7612a82f1d9c36148af9c77354759b210b",
"data": "0x",
"topics": [
"0x06df6fb2d6d0b17a870decb858cc46bf7b69142ab7b9318f7603ed3fd4ad240e",
"0x0000000000000000000000000000000000000000000000000000000000000002"
]
}
]
```
## Topic filters
[Filter options objects](../reference/api/eth/filter.md#eth_newfilter) have a `topics` key to filter logs by topics.
Topics are order-dependent. A transaction with a log containing topics `[A, B]` matches with the following topic filters:
- `[]` - Match any topic
- `[A]` - Match A in first position
- `[[null], [B]]` - Match any topic in first position AND B in second position
- `[[A],[B]]` - Match A in first position AND B in second position
- `[[A, C], [B, D]]` - Match (A OR C) in first position AND (B OR D) in second position.
The following filter option object returns log entries for the [Event Parameters example contract](#event-parameters) with `valueIndexed` set to 5 or 9:
```json
{
"fromBlock": "earliest",
"toBlock": "latest",
"address": "0x43d1f9096674b5722d359b6402381816d5b22f28",
"topics": [
["0xd3610b1c54575b7f4f0dc03d210b8ac55624ae007679b7a928a4f25a709331a8"],
[
"0x0000000000000000000000000000000000000000000000000000000000000005",
"0x0000000000000000000000000000000000000000000000000000000000000009"
]
]
}
```
---
## Genesis file
The genesis file defines the first block in the chain, and the first block defines which chain you want to join.
For Ethereum Mainnet and public testnets (for example, Sepolia) the genesis configuration definition is in Besu and used when specifying a public network using the [`--network`](../reference/options.md#network) command line option.
For private networks, [create a JSON genesis file](https://consensys.net/blog/quorum/hyperledger-besu-how-to-create-an-ethereum-genesis-file/), then specify the genesis file using the [`--genesis-file`](../reference/options.md#genesis-file) command line option.
The genesis file specifies the [network-wide settings](../reference/genesis-items.md), such as those for a [free gas network](../../private-networks/how-to/configure/free-gas.md), so all nodes in a network must use the same genesis file.
:::note
You can specify node-level settings on the command line or in the [node configuration file](../how-to/configure-besu/index.md).
:::
```json title="Example IBFT 2.0 genesis file"
{
"config": {
"chainId": 2018,
"berlinBlock": 0,
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
}
},
"nonce": "0x0",
"timestamp": "0x58ee40ba",
"extraData": "0xf83ea00000000000000000000000000000000000000000000000000000000000000000d5949811ebc35d7b06b3fa8dc5809a1f9c52751e1deb808400000000c0",
"gasLimit": "0x1fffffffffffff",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb": {
"balance": "0xad78ebc5ac6200000"
}
}
}
```
---
## Network ID and chain ID
Ethereum networks have two identifiers, a network ID and a chain ID. Although they often have the same value, they have different uses.
Peer-to-peer communication between nodes uses the _network ID_, while the transaction signature process uses the _chain ID_.
:::note
[EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md) introduced using the chain ID as part of the transaction signing process to protect against transaction replay attacks.
:::
For most networks, including Mainnet and the public testnets, the network ID and the chain ID are the same, with the network ID defaulting to the chain ID, as specified in the genesis file.
```json title="Chain ID in the genesis file"
{
"config": {
"chainID": 1981
},
...
}
```
Besu sets the chain ID (and by default the network ID) automatically, using either the [`--genesis-file`](../reference/options.md#genesis-file) option or when specifying a network using the [`--network`](../reference/options.md#network) option. The following table lists the available networks and their chain and network IDs.
| Network | Chain | Chain ID | Network ID | Type |
| --------- | ----- | -------- | ---------- | ----------- |
| `mainnet` | ETH | 1 | 1 | Production |
| `hoodi` | ETH | 560048 | 560048 | Test |
| `sepolia` | ETH | 11155111 | 11155111 | Test |
| `dev` | ETH | 1337 | 2018 | Development |
| `ephemery`| ETH | [dynamic](https://github.com/ephemery-testnet/ephemery-genesis/releases) | [dynamic](https://github.com/ephemery-testnet/ephemery-genesis/releases) | Test |
| `lukso` | Lukso | 4201 | 4201 | Production |
| `linea_mainnet` | Linea | 59144 | 59144 | Production |
| `linea_sepolia`| Linea |59141 | 59141 | Test |
:::info
The following networks and testnets are deprecated: ETC (Ethereum Classic) and Mordor.
:::
## Specify a different network ID
Usually the network ID is the same as the chain ID, but if you want to separate specific nodes from the rest of the network so they can't connect or synchronize with other nodes, you can override the default network ID for those nodes using the [`--network-id`](../reference/options.md#network-id) option.
## Start a new chain with a new chain ID
If you update the chain ID (or network ID) of existing nodes, they can no longer peer with other nodes in the network. Nodes need to have a matching [genesis file](genesis-file.md), including the chain ID, in order to peer. In this case, you're effectively running two chains that can't communicate with each other.
To change a chain ID and start a new chain:
1. Stop all your nodes using ctrl+c in each terminal window.
2. Update the [genesis file](genesis-file.md) with the new chain ID.
3. Make sure all nodes have the same genesis file.
4. Delete the old data directory or point to a new location for each node.
5. [Restart the nodes](../../private-networks/tutorials/ibft/index.md#6-start-the-first-node-as-the-bootnode).
:::danger Warning
Starting a new chain is starting from block zero.
This means when you start a new chain with a new chain ID, you lose all previous data.
:::
---
## Node clients
Ethereum's Proof of Stake (PoS) protocol leverages two separate P2P networks supporting
separate clients. Execution clients gossip transactions over their network, enabling them to manage
their local transaction pool. Consensus clients gossip blocks over their network, enabling consensus
and chain growth. A validator node also runs the [validator client](#validator-clients).
:::info
As as result of [the 2022 Merge](https://ethereum.org/en/upgrades/merge/), Ethereum Mainnet
transitioned from Proof of Work (PoW) to [PoS](proof-of-stake/index.md) consensus.
:::
## Execution and consensus clients
Under PoS, a full Ethereum Mainnet node is a combination of an execution client (previously called
an [Eth1 client](https://blog.ethereum.org/2022/01/24/the-great-eth2-renaming/)) and a
consensus client (previously called an
[Eth2 client](https://blog.ethereum.org/2022/01/24/the-great-eth2-renaming/)). The consensus client
uses the [Engine API](../how-to/use-engine-api.md) to communicate with the execution client.

### Execution clients
Execution clients, such as Besu, manage the execution layer, including executing transactions and
updating the world state. Execution clients serve [JSON-RPC API](../reference/engine-api.md)
requests and communicate with each other P2P.
Besu is an execution client that you can run with:
- [Any consensus client on Mainnet](../get-started/connect/mainnet.md).
- [Any consensus client on a testnet](../get-started/connect/testnet.md).
- [Teku on Mainnet](../tutorials/besu-teku-mainnet.md).
- [Teku on a testnet](../tutorials/besu-teku-testnet.md).
### Consensus clients
The consensus client (also known as the beacon node, CL client or, formerly, the Eth2 client)
implements the PoS consensus algorithm, which enables the network to achieve agreement based on
validated data from the execution client. Consensus clients serve
[REST API](https://docs.teku.consensys.net/reference/rest) requests and
communicate with each other P2P.
Consensus clients, such as [Teku](https://docs.teku.consensys.net/en/latest/) contain beacon node
implementations. The beacon node is the primary link to the [Beacon Chain] (i.e. the consensus layer).
A consensus client can run without the (bundled) validator to keep up with the head of the chain,
allowing the node to stay synced.
#### Validator clients
To operate a validator node, node operators must also run a validator client and deposit the
[required ETH](https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/#validators) into the
deposit contract. The validator client handles attestations and block proposal — i.e. performs
[validator duties](proof-of-stake/index.md) on the consensus layer.
The validator client may either be run
[in the same process](https://docs.teku.consensys.net/get-started/start-teku#start-the-clients-in-a-single-process)
as the beacon node or [separately](https://docs.teku.consensys.net/get-started/start-teku#run-the-clients-separately).
Validators earn rewards for performing
[validator duties](proof-of-stake/index.md), and
[fee recipients](https://docs.teku.consensys.net/reference/cli#validators-proposer-default-fee-recipient)
also earn rewards for the inclusion of execution layer transactions.
[Beacon Chain]: https://ethereum.org/en/upgrades/beacon-chain/
[Teku]: https://docs.teku.consensys.net/en/stable/
[Run a node]: https://ethereum.org/en/developers/docs/nodes-and-clients/run-a-node/
---
## Node keys
# Node keys and node address
Each node has a private and public key pair, and a node address.
Besu uses the key pair as the node's network identity, and the node address as an
identifier for the node.
In QBFT and IBFT 2.0 private networks, node addresses are validator addresses.
## Node private key
When starting Besu, if the [`--node-private-key-file`](../reference/options.md#node-private-key-file) option is not specified and a `key` file does not exist in the data directory for the node, Besu generates a node private key and writes it to the `key` file.
If a `key` file does exist in the data directory when starting Besu, the node starts using the private key in the `key` file.
:::danger
The local private key file is not encrypted.
:::
:::tip HSM-backed node keys
For deployments that require hardware-backed key storage, use a security module
plugin, such as the [Besu HSM plugin](https://github.com/besu-eth/besu-hsm-plugin),
with the [`--security-module`](../reference/options.md#security-module)
option.
The plugin delegates node key operations to a Hardware Security Module (HSM)
instead of reading a local key file.
On public networks, this protects Besu's P2P node key.
It doesn't manage Ethereum account keys, transaction signing keys, or
proof of stake validator keys.
:::
## Node public key
The node public key displays in the log after starting Besu. Also referred to as the node ID, the node public key forms part of the enode URL of a node.
You can export the node public key, either to standard output or to a specified file, using the [`public-key export`](../reference/subcommands.md#public-key) subcommand.
## Node address
Besu generates the node address by creating a hash of the node public key and using the last 20 bytes of the hash as the node address. It is also displayed in the logs after starting Besu.
You can export the node address, either to standard output or to a specified file, using the [`public-key export-address`](../reference/subcommands.md#public-key) subcommand.
## Specify a custom node private key file
Use the [`--node-private-key-file`](../reference/options.md#node-private-key-file) option to specify a custom `key` file in any location.
If the `key` file exists, the node starts with the private key in the `key` file. If the `key` file does not exist, Besu generates a node private key and writes it to the `key` file.
For example, the following command either reads the node private key from `privatekeyfile` or writes a generated private key to `privatekeyfile`.
```bash
besu --node-private-key-file="/Users/username/privatekeyfile"
```
## Enode URL
The enode URL identifies a node for discovery v4.
For example, you can specify nodes by the enode URL using the [`--bootnodes`](../reference/options.md#bootnodes) option and the [`admin_addPeer`](../reference/api/admin.md#admin_addpeer) method.
:::tip
Besu supports [ENR URLs](#enr-url) for discovery v5 when the early access option
[`--Xv5-discovery-enabled`](../reference/options.md#xhelp) is set to `true`.
:::
The enode URL format is `enode://@[?discport=]` where:
- `` is the node public key, excluding the initial 0x.
- `` is the host and TCP port the bootnode is listening on for P2P discovery. Specify the host and TCP port using the [`--p2p-host`](../reference/options.md#p2p-host) and [`--p2p-port`](../reference/options.md#p2p-port) options. The default host is `127.0.0.1` and the default port is `30303`.
:::note
Standard Ethereum enode URLs allow hostnames as IP addresses only, however Besu provides [domain name support](#domain-name-support) in private permissioned networks.
:::
- If the TCP listening and UDP discovery ports differ, the UDP port is specified as query parameter `discport`.
:::info
If the node public key is `0xc35c3ec90a8a51fd5703594c6303382f3ae6b2ecb9589bab2c04b3794f2bc3fc2631dabb0c08af795787a6c004d8f532230ae6e9925cbbefb0b28b79295d615f`, the host is `10.3.58.6`, the TCP listening port is `30303`, and the UDP discovery port is `30301`, then the enode URL is `enode://c35c3ec90a8a51fd5703594c6303382f3ae6b2ecb9589bab2c04b3794f2bc3fc2631dabb0c08af795787a6c004d8f532230ae6e9925cbbefb0b28b79295d615f@10.3.58.6:30303?discport=30301`
If the [`--p2p-host`](../reference/options.md#p2p-host) or [`--p2p-port`](../reference/options.md#p2p-port) options are not specified and the node public key is `0xc35c3ec90a8a51fd5703594c6303382f3ae6b2ecb9589bab2c04b3794f2bc3fc2631dabb0c08af795787a6c004d8f532230ae6e9925cbbefb0b28b79295d615f`, then the enode URL is `enode://c35c3ec90a8a51fd5703594c6303382f3ae6b2ecb9589bab2c04b3794f2bc3fc2631dabb0c08af795787a6c004d8f532230ae6e9925cbbefb0b28b79295d615f@127.0.0.1:30303`
:::
The enode URL displays when starting a Besu node. Use the [`net_enode`](../reference/api/net.md#net_enode) JSON-RPC API method to get the enode URL of the node.
The enode advertised to other nodes during discovery is the external IP address and port, as defined by [`--nat-method`](../how-to/connect/specify-nat.md).
### Domain name support
:::caution
Enode URL domain name support is an early access feature that you can use in private [permissioned networks](../../private-networks/concepts/permissioning.md) only.
:::
To use domain names in enode URLs:
- Configure DNS reverse lookup.
- Enable DNS support using the early access option `--Xdns-enabled`.
```bash title="Example enode URL using a domain name"
enode://c35c3ec90a8a51fd5703594c6303382f3ae6b2ecb9589bab2c04b3794f2bc3fc2631dabb0c08af795787a6c004d8f532230ae6e9925cbbefb0b28b79295d615f@mydomain.dev.example.net:30301
```
:::tip
If deploying Besu using Kubernetes in private permissioned networks, use the `--Xdns-enabled` and `--Xdns-update-enabled` options to ensure that Besu can connect to a container after restarting even if the IP address of the container changes.
Use the [`--Xhelp`](../reference/options.md#xhelp) command line option to view early access options and their descriptions.
:::
If nodes are not connecting as expected, set the [log level to TRACE](../reference/api/admin.md#admin_changeloglevel) to help troubleshoot the issue.
## ENR URL
The Ethereum Node Record, or ENR URL, identifies a node for [discovery v5](https://github.com/ethereum/devp2p/tree/master/discv5).
For example, you can specify nodes by the ENR URL using the [`--bootnodes`](../reference/options.md#bootnodes) option
or in the [`v5Bootnodes`](../reference/genesis-items.md#discovery-configuration-items) discovery setting in the genesis file.
The [`admin_nodeInfo`](../reference/api/admin.md#admin_nodeinfo) method returns the ENR URL in the `enr` field.
:::tip Early access feature
To use ENR URLs (discovery v5), set the early access option `--Xv5-discovery-enabled` to `true`.
:::
Unlike [enode URLs](#enode-url), ENR URLs can advertise additional node information, including IPv4 and IPv6 addresses.
See [EIP-778](https://eips.ethereum.org/EIPS/eip-778) for the full specification.
---
## Node synchronization
Besu supports two [node types](#node-types) and two [synchronization modes](#sync-modes) on public networks.
## Node types
### Full nodes
A full node consists of an
[execution and consensus client](node-clients.md#execution-and-consensus-clients),
and stores a local copy of the blockchain.
With a full node, you can check current balances, sign and send transactions, and look at current
dapp data.
Full nodes can guarantee the latest state of the blockchain (and some older states). However, they
can't serve the network with all data requests (for example, the balance of an account at an old
block).
Run a full node using [snap synchronization](#snap-synchronization).
### Archive nodes
An archive node is a node that also stores the intermediary state of every account and contract
for every block since the genesis block.
Archive nodes can do everything full nodes do, and they can also access historical state data.
This means that archive nodes require more disk space than full nodes.
Run an archive node using [full synchronization](#full-synchronization).
:::caution important
Do not run an archive node with the [Bonsai Tries](data-storage-formats.md#bonsai-tries)
data storage format.
Bonsai is designed for retrieving recent data only.
:::
## Sync modes
The following table summarizes the recommended public network sync modes:
| Sync mode | Recommended use | Besu version requirement |
|-------------------------------|-----------------|--------------------------|
| [Snap](#snap-synchronization) | Full nodes on Mainnet and public testnets. | 22.4.0 or later |
| [Full](#full-synchronization) | Archive nodes on smaller networks. Not recommended on Mainnet. | Any |
:::warning Checkpoint sync
Checkpoint sync is deprecated.
When you select checkpoint sync, Besu performs snap sync instead.
:::
:::info Private network syncing
Private networks might require different sync configurations.
See [Node synchronization for private networks](../../private-networks/concepts/node-sync-private.md)
for more information.
:::
:::note Troubleshooting
Besu must connect with other peers to sync with the network.
If your node is having trouble peering, try [troubleshooting peering](../how-to/troubleshoot/peering.md).
:::
### Snap synchronization
Snap sync is the default sync mode for all named [networks](../reference/options.md#network)
except `dev`.
You can enable snap sync using [`--sync-mode=SNAP`](../reference/options.md#sync-mode).
You need Besu version 22.4.0 or later to use snap sync.
By default, [Snap sync prunes historical block data](../how-to/pre-merge-history-expiry.md) for
[pre-merge](https://ethereum.org/en/roadmap/merge/) PoW blocks, retaining only the
headers and the genesis block.
:::note
To download the full PoW block history, set
[`--snapsync-synchronizer-pre-checkpoint-headers-only-enabled`](../reference/options.md#snapsync-synchronizer-pre-checkpoint-headers-only-enabled)
to `false`. However, this will increase the sync time and disk space usage.
:::
Instead of downloading the [state trie](data-storage-formats.md) node by node, snap
sync downloads as many leaves of the trie as possible, and reconstructs the trie locally.
To enable serving snap sync data to other nodes, set
[`--snapsync-server-enabled`](../reference/options.md#snapsync-server-enabled) to `true`.
You can restart Besu during a snap sync in case of hardware or software problems. The sync resumes
from the last valid world state and continues to download blocks starting from the last downloaded
block.
See [how to read the Besu metrics charts](../how-to/monitor/understand-metrics.md) when using
snap sync.
### Full synchronization
Full sync is the default sync mode for the [`dev` network](../reference/options.md#network).
You can enable full sync using [`--sync-mode=FULL`](../reference/options.md#sync-mode).
Use full sync with [Forest of Tries](data-storage-formats.md#forest-of-tries) to run an
[archive node](#archive-nodes).
Full sync starts from the genesis block and reprocesses all transactions.
You can optionally [download and sync pre-merge Ethereum history](../how-to/era1-file-full-sync.md)
from ERA1 archive files instead of relying on peered nodes for the data.
:::caution important
Do not run full sync with the [Bonsai Tries](data-storage-formats.md#bonsai-tries)
data storage format.
Bonsai is designed for retrieving recent data only.
:::
## Sync times
To sync with a public network, Besu runs two processes in parallel: the world state sync and the
blockchain download.
While the world state syncs, Besu downloads and imports the blockchain in the background.
The blockchain download time depends on CPU, the network, Besu's peers, and disk speed.
The blockchain download generally takes longer than the world state sync. Besu must catch up to the
current chain head and sync the world state to participate on Mainnet.
The following table shows estimates for each sync mode on Mainnet.
All times are hardware dependent.
| Sync mode | Storage format | Node type | Mainnet sync time |
|-----------|----------------|--------------|-------------------|
| Snap | [Bonsai](data-storage-formats.md#bonsai-tries) | Full node | ~12-16 hours |
| Full | [Forest](data-storage-formats.md#forest-of-tries) | Archive node | ~weeks |
The Bonsai snap sync estimate is based on May 2026 burn-in results for the Besu 26.5.0
release cycle on AWS `m8g.2xlarge` instances.
The observed sync time range includes differences in peer sets and disk speed.
By default, snap sync prunes historical block data for pre-merge PoW blocks.
Downloading full PoW blocks could double the download time.
Full sync takes significantly more time than snap sync, and we do not recommend using it on Mainnet.
See the [storage estimates](data-storage-formats.md#storage-estimates) for the different sync modes and node types.
:::note
Testnets take significantly less time and space to sync.
:::
---
## Parallel transaction execution
Besu supports parallel transaction execution, using an optimistic approach to parallelize
transactions within a block.
This optional feature is available when using the [Bonsai Tries](data-storage-formats.md#bonsai-tries) data storage format.
This page provides an [overview of the parallelization mechanism](#parallelization-mechanism-overview),
and [metrics](#metrics) that highlight Besu's improved performance.
## Parallelization mechanism overview
When [parallel transaction execution is enabled](../reference/options.md#bonsai-parallel-tx-processing-enabled), Besu initially executes all transactions within a
block in parallel, operating under the optimistic assumption that they can all be executed
concurrently without conflict.
This parallel execution runs in the background, and Besu proceeds to sequentially process the
transactions without waiting for the parallel execution to complete.
The following flowchart outlines the transaction execution flow:
```mermaid
graph TD;
X(Start parallel execution as background process) --> A(Start sequential processing);
A --> B{{Is transaction completed by background process?}};
B --> |Yes| C{{Conflict check}};
C --> |No conflict| D(Apply background state modifications);
C --> |Conflict detected| E(Replay transaction using background cache);
B --> |No| F(Execute transaction sequentially);
D --> G(End sequential processing);
E --> G;
F --> G;
```
Besu first determines if a transaction has been completed by the background parallel execution:
- **Completed:** If the transaction is completed, Besu examines whether there are any conflicts with
previously executed transactions.
- **No conflict:** If no conflict is detected, Besu directly applies the state modifications
generated in the background to the block, avoiding re-execution.
- **Conflict detected:** If a conflict is detected, Besu replays the transaction, using a cache of
background reads to improve efficiency.
- **Not completed:** If the transaction is not completed, Besu executes it sequentially within the
block to ensure its completion, independent of the background execution.
### Conflict detection strategy
Besu's conflict detection strategy uses the *accumulator*, a
[Bonsai Tries](data-storage-formats.md#bonsai-tries) feature that tracks addresses and slots touched
or modified during block or transaction execution.
:::tip
You can read more about Bonsai Tries in [Consensys' Guide to Bonsai Tries](https://consensys.io/blog/bonsai-tries-guide).
:::
If a slot, code, or anything else related to an account is modified, the Bonsai accumulator keeps
track of this information.
This strategy leverages Bonsai's storage benefits, only keeping track of block-to-block state diffs
in Besu storage.
The following flowchart outlines how Besu detects conflicts and imports transactions into the block:
```mermaid
graph TD;
A(Start block import) --> B(Fetch block's touched addresses);
B --> C{{For each transaction}};
C -->|Next transaction| D(Fetch transaction's touched addresses);
D --> E{{Compare addresses}};
E -->|Conflict detected| F(Replay transaction using cached data);
E -->|No conflict| G(Apply transaction result directly – no replay);
F --> H{{Attempt to read from cache}};
H -->|Data found in cache| I(Continue replay using cached data);
H -->|Data not found in cache| J(Fetch data from disk);
I --> K(Transaction replay complete);
J --> K;
K --> L(Apply transaction changes);
G --> L;
L --> M{{More transactions?}};
M -->|Yes| C;
M -->|No| N(End block import);
```
Besu takes what the accumulator tracks at the block and transaction level, compares the
transaction's list of touched addresses to the block's list, and checks for conflicts.
In particular:
1. Besu identifies conflicts by checking whether a transaction has interacted with accounts modified
by the block (that is, modified by previous transactions).
2. If a conflict is detected, Besu replays the transaction using cached data or data fetched from disk.
3. Each time a transaction is added to the block, Besu incorporates the transaction's tracked list
into the block's list.
:::info Note
Unchanged accounts read by the block are excluded from the conflict check.
:::
The following flowchart outlines how Besu maintains the lists of tracked addresses:
```mermaid
graph TD;
A(Start) --> B(Fetch block's touched addresses);
B --> C{{Check each address}};
C -->|Unchanged| D(Mark as read);
C -->|Modified| E(Add to block's tracked addresses);
D --> F{{Next address}};
E --> F;
F -->|More addresses?| C;
F -->|No more| G(Fetch transaction's touched addresses);
G --> H{{For each transaction address}};
H -->|From, sender, etc.| I(Add to transaction's tracked addresses);
I --> J{{Next address}};
J -->|More addresses?| H;
J -->|No more| K{{Compare block and transaction addresses}};
K -->|Conflict detected| L(Conflict is detected);
K -->|No conflict| M(Proceed with transaction);
L --> N(End);
M --> N;
```
Besu's conflict detection strategy is intentionally simple to minimize edge cases.
With this approach to parallel transaction execution,
[approximately 40% of transactions do not require replay](#metrics).
In the future, the conflict detection strategy may be refined to reduce false positives.
You can enable parallel transaction execution using the [`--bonsai-parallel-tx-processing-enabled`](../reference/options.md#bonsai-parallel-tx-processing-enabled) option.
## Metrics
Parallel transaction execution uses Besu's resources more efficiently than traditional
sequential execution, significantly improving performance.
The following metrics were collected on nodes running on Azure Virtual Machines (Standard D8as v5–8 vCPUs, 32
GiB memory), with Teku and Nimbus as consensus layer (CL) clients:
- **Block processing time** - With Teku as CL client, block processing time improves by at least 25%.
The 50th percentile decreases from 282 ms to 207 ms and the 95th
percentile decreases from 479 ms to 393 ms.
With Nimbus as CL client, block processing improves by approximately 45%, with the 50th percentile
at 155 ms, and the 95th percentile at 299 ms.
Besu running with Nimbus has better performance than with Teku because Nimbus has less overhead on
Besu, meaning less context switching and fewer cache misses.
- **Execution throughput** - Benchmarking against mainnet big blocks shows a significant increase in
execution throughput (measured in megagas per second, Mgas/s) compared to sequential processing.
These results were collected on the following hardware:
- CPU: AMD EPYC 4344P, 8 cores/16 threads, 3.8 GHz base / 5.3 GHz boost
- RAM: 64 GB DDR5 5200 MHz
- Storage: 2x 960 GB NVMe SSD
The following table shows the throughput results:
| Metric | Throughput |
|--------|-----------|
| Minimum | 194.55 Mgas/s |
| Maximum | 445.99 Mgas/s |
| Average | 348.17 Mgas/s |
| 50th percentile | 352.57 Mgas/s |
| 95th percentile | 404.93 Mgas/s |
| 99th percentile | 418.13 Mgas/s |
- **Parallel transactions** - Parallel transaction execution introduces two new metrics, which
indicate that approximately 40% of transactions are parallelized using this feature:
- `besu_block_processing_parallelized_transactions_counter_total` - The number of transactions
executed in parallel.
- `besu_block_processing_conflicted_transactions_counter_total` - The number of transactions that
encountered conflicts and were therefore executed sequentially.
- **Sync time** - Snap synchronization time is approximately 27 hours and 5 minutes, with block import
time approximately 6 ms on average.
- **CPU profiling** - The new payload call time decreases from 251.68 ms to 172.04 ms on average,
with notable improvements in SLOAD operation times.
During the faster block processing time, Besu uses more CPU and more disk accesses in parallel
(higher IOPS).
However, when these metrics are averaged on different monitoring tools, the resource usage looks the same as
with sequential execution.
Overall, parallel transaction execution improves Besu performance with almost no resource usage
overhead.
---
## Attestations
Ethereum's move to [proof of stake consensus](./index.md) has brought many changes to the way the network operates. An important aspect of proof of stake is the need for validators to provide attestations in a timely and accurate manner. However, missed attestations have become a common occurrence among validators, leading to a loss of rewards and earnings. This page explores the context behind missing attestations.
## What are attestations?
Every epoch (6.4 minutes), a validator proposes an attestation to the network. The attestation is for a specific slot (every 12 seconds) in the epoch. The attestation votes in favor of the validator's view of the chain, in particular, the most recent justified block and the first block in the current epoch (known as _source_ and _target_ checkpoints). This information is collected for all participating validators, enabling the network to reach consensus about the state of the blockchain.
Honest nodes have 1/3 \* `SECONDS_PER_SLOT` (4 seconds) from the start of the slot to either receive the block or decide there was no block produced and attest to an “empty” or “skip” slot. Once this time has elapsed, attesters should broadcast their attestation reflecting their local view of the chain.
See the [official specification](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/validator.md#attesting) for more information about attestations.
## Attestation rewards
Around 85% of validators' rewards come from making attestations. Although committee and slot assignments for attesting are randomized, every active validator will be selected to make exactly one attestation each epoch.
Attestations receive rewards only if they're included in Beacon Chain blocks. An attestation contains three votes. Each vote is eligible for a reward, subject to the following conditions:
- Getting attestations included with the correct source checkpoint within 5 slots
- Getting attestations included with the correct target checkpoint within 32 slots
- Getting attestations included with the correct head within 1 slot immediately
Each of these duties carries a reward rate, a portion of the entire "weight denominator," or the sum of weighted rewards for each attestation. The remaining weights relate to participating in sync committees and proposing blocks (excluding any tips/MEV, the bulk of block rewards). The following table (from [Upgrading Ethereum](https://eth2book.info/bellatrix/part2/incentives/rewards/)) breaks down these weights for cumulative rewards:
| Name | Percentage | Value |
| ---------------------- | ---------- | ------------ |
| `TIMELY_SOURCE_WEIGHT` | 21.9% | `uint64(14)` |
| `TIMELY_TARGET_WEIGHT` | 40.6% | `uint64(26)` |
| `TIMELY_HEAD_WEIGHT` | 21.9% | `uint64(14)` |
| `SYNC_REWARD_WEIGHT` | 3.1% | `uint64(2)` |
| `PROPOSER_WEIGHT` | 12.5% | `uint64(8)` |
| `WEIGHT_DENOMINATOR` | 100% | `uint64(64)` |
## Incorrect attestations
If you have attestations with incorrect head votes, your node might be experiencing slow block imports. However, block producers can also be slow to publish blocks, resulting in a majority of validators getting the head vote wrong. A \<100% head vote doesn't necessarily imply a problem with your node.
In case of a slowdown, identify whether the issue is with the beacon node or the execution client. Block timing logs can be helpful in determining this.
If you're using [Teku](https://docs.teku.consensys.net/) as a consensus layer client, identify late blocks (the block didn't get to Teku in time) with the following kind of log:
```bash
Late Block Import *** Block: c2b911533a8f8d5e699d1a334e0576d2b9aa4caa726bde8b827548b579b47c68 (4765916) proposer 6230 arrival 3475ms, pre-state_retrieved +5ms, processed +185ms, execution_payload_result_received +1436ms, begin_importing +0ms, transaction_prepared +0ms, transaction_committed +0ms, completed +21ms
```
The time of arrival indicates how much time elapsed after the start of the slot before your node received the block. In this example, the block arrived after 3475ms, which is slower than optimal, but still enough time for Teku to create an attestation 4 seconds into the slot.
Typically, delayed arrivals occur when the block producer is slow in generating the block. It's also possible that the block was published on time but took longer to propagate to your node through peer-to-peer gossip. If delayed arrivals are a recurring issue, it might be a problem with your node, such as an incorrect system clock, network issues, or a reduction in the number of peers.
## Conclusion
Attestations are complicated. Rewards can be impacted by:
- The contents of a block (how long it takes to compute).
- The hardware processing that block (execution speed).
- How long it takes for the block to arrive to Besu from the consensus layer.
- The arrival time of the block from other consensus layer peers. Besu and your consensus layer client have no control over how late into a slot they receive blocks.
- General network latency.
- The status of either Besu or the consensus layer client.
[Monitoring](../../how-to/monitor/index.md) your validator carefully for uptime, execution speed, and a valid consensus layer connection will help you explore attestation performance for your node.
## References
- [Upgrading Ethereum](https://eth2book.info/bellatrix/part2/incentives/rewards/)
- [Understanding Attestation Misses](https://www.symphonious.net/2022/09/25/understanding-attestation-misses/)
- [Block production in Ethereum after the Merge](https://notes.ethereum.org/DaWh-02HQ4qftum1xdphkg?view#Broadcast-attestation)
- [Ethereum Consensus Specs](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/validator.md#attesting)
---
## Proof of stake consensus
[The Merge](https://ethereum.org/en/upgrades/merge/) transitioned Ethereum Mainnet to [Proof of Stake
(PoS)](https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/) consensus.
Under Ethereum's PoS, you must run a [full node](../node-clients.md#execution-and-consensus-clients) and
[stake 32 ETH](https://ethereum.org/en/staking/) to become a validator.
:::note
To operate a full node on Mainnet, you must run a beacon node, i.e. a consensus client and an execution client.
To become a validator, you must also run a validator client (either [in the same process as the
beacon node](https://docs.teku.consensys.net/get-started/start-teku#start-the-clients-in-a-single-process)
or [separately](https://docs.teku.consensys.net/get-started/start-teku#run-the-clients-separately)).
:::
PoS is preferred over Proof of Work and Proof of Authority as a consensus mechanism because it is
more secure, requires less energy, and lowers the barrier to entry.
The PoS mechanism randomly chooses validators to propose or validate blocks on the [Beacon
Chain](https://ethereum.org/en/upgrades/beacon-chain/) in defined time frames.
Proposers are responsible for proposing new consensus blocks, and non-proposing validators are
responsible for validating (attesting to) proposed blocks.
Validators earn rewards for proposing and
attesting to consensus blocks eventually included in the Beacon Chain, and penalized for malicious behavior.
[Attestations](./attestations.md) make up the bulk of validator rewards (~85%).
Validators also receive transaction fees for included blocks.
Each consensus block contains an execution payload, which contains a list of transactions and other data required to execute and validate the payload.
When a node validates a consensus block, its [consensus client](../node-clients.md#consensus-clients) processes the block and sends the execution payload to the [execution client](../node-clients.md#execution-clients), which:
1. Assembles a block on the execution layer.
2. Verifies pre-conditions.
3. Executes transactions.
4. Verifies post-conditions.
5. Sends the validity result back to the consensus client.
If the block is valid, the execution client includes it in the execution chain and stores the new state in execution state storage.
If a consensus block receives attestations backed by enough staked ETH, the block is included in the Beacon Chain. In the case of competing chains, the chain with the highest number of validator votes is selected.
---
## Transaction pool
All nodes maintain a transaction pool to store pending transactions before processing.
Transaction pools are categorized into the following two types:
* [Layered](#layered-transaction-pool) - Recommended for public blockchain networks.
* [Sequenced](#sequenced-transaction-pool) - Recommended for private blockchain networks.
You can use specific [options](../../reference/options.md#tx-pool) and
[methods](../../reference/api/txpool.md) to configure and monitor the transaction pool.
## Layered transaction pool
The [layered transaction pool](https://github.com/besu-eth/besu/pull/5290) is the default
transaction pool implementation.
The implementation separates the pool into layers according to value and executability of the transactions.
The first layer keeps only the highest-value transactions that can feasibly go into the next block.
The other two layers ensure Besu always has a backlog of transactions to fill blocks, maximizing the amount of fees.
Layered pools have additional parameters that allow you to limit and configure the number of transactions
in different layers, enabling them to handle high volumes and sort transactions at a faster speed.
With the layered transaction pool, Besu produces more profitable blocks more quickly, with more
denial-of-service protection, and using less CPU than with the legacy transaction pool.
If you previously configured transaction pool behavior, upgrade to the layered transaction pool by:
- Removing the [`--tx-pool-retention-hours`](../../reference/options.md#tx-pool-retention-hours)
option, which is not applicable because old transactions will expire when the memory cache is full.
- Replacing the [`--tx-pool-limit-by-account-percentage`](../../reference/options.md#tx-pool-limit-by-account-percentage)
option with [`--tx-pool-max-future-by-sender`](../../reference/options.md#tx-pool-max-future-by-sender)
to limit the number of sequential transactions, instead of percentage of transactions, from a single
sender kept in the pool.
- Removing the [`--tx-pool-max-size`](../../reference/options.md#tx-pool-max-size) option,
which is not applicable because the layered pool is limited by memory size instead of the number
of transactions.
To configure the maximum memory capacity, use [`--tx-pool-layer-max-capacity`](../../reference/options.md#tx-pool-layer-max-capacity).
You can opt out of the layered transaction pool implementation by setting the
[`--tx-pool`](../../reference/options.md#tx-pool) option to `sequenced`.
### Transient invalid pending transactions
Transient invalid pending transactions cannot be included in the current block but might be included in a future one.
This can happen due to issues like insufficient balance in the sender's wallet or a gas price below the minimum.
These conditions could resolve in the future.
:::note
Invalid pending transactions where conditions can't be resolved in the future (for example, invalid nonce)
are immediately dropped from the transaction pool.
:::
The layered transaction pool uses a scoring system to avoid repeatedly evaluating transient invalid pending
transactions, which can block the evaluation of valid ones. Each pending transaction starts with a score of
`127` and is penalized over time, with the score decreasing to a minimum of -128.
This score determines the transaction's rank in the pool, pushing invalid transactions lower so they are
evaluated only after non-penalized or less penalized ones.
The [`--tx-pool-min-score`](../../reference/options.md#tx-pool-min-score) option, which accepts a value
between `-128` and `127`, instructs the transaction pool to remove pending transactions when their score falls
below the specified value. By default, the value is `-128`, meaning the pending transaction will remain in the
pool with the lowest score and will only be selected after all other pending transactions have been processed.
### Dropping transactions
When the layered transaction pool is full, it accepts and retains local transactions in preference to remote transactions,
unless [`--tx-pool-no-local-priority`](../../reference/options.md#tx-pool-no-local-priority) is enabled.
If the transaction pool is full of local transactions, Besu drops the oldest local transactions first.
That is, a full transaction pool continues to accept new local transactions by first dropping remote transactions and
then by dropping the oldest local transactions.
## Sequenced transaction pool
In the sequenced transaction pool, transactions are processed strictly in the order they are received.
Although sequenced transaction pools lack the flexibility of layered pools, they help maintain a
consistent and transparent transaction order, which is often useful in private blockchains.
You can select the sequenced transaction pool by setting [`--tx-pool=sequenced`](../../reference/options.md#tx-pool).
If you set the enterprise configuration profile using [`--profile=enterprise`](../../how-to/configure-besu/profile.md#enterpriseprivate-profile) or [`--profile=private`](../../how-to/configure-besu/profile.md#enterpriseprivate-profile), the `sequenced` transaction pool is set by default.
The sequenced transaction pool suits enterprise environments because it functions like a first-in-first-out (FIFO) queue and processes transactions in the order of submission, regardless of the sender.
When the pool reaches capacity, the newer transactions are evicted first, reducing the likelihood of a nonce gap and avoiding the need to resubmit older transactions.
## Replacing pending transactions
You can replace a pending transaction with a transaction that has the same sender and nonce but a higher gas price.
### Legacy transactions
If sending a [legacy](types.md#frontier-transactions) or [`ACCESS_LIST`](types.md#access_list-transactions) transaction,
the old transaction is replaced if the new transaction has a gas price higher than the existing gas price by the percentage
specified by [`--tx-pool-price-bump`](../../reference/options.md#tx-pool-price-bump).
### `EIP1559` transactions
If sending an [`EIP1559` transaction](types.md#eip1559-transactions), the old transaction is replaced if one of the following is true:
- The new transaction's effective gas price is higher than the existing gas price by the percentage specified by
[`--tx-pool-price-bump`](../../reference/options.md#tx-pool-price-bump) AND the new effective priority fee is greater than
or equal to the existing priority fee.
- The new transaction's effective gas price is equal to the existing gas price AND the new effective priority fee is higher than
the existing priority fee by the percentage specified by [`--tx-pool-price-bump`](../../reference/options.md#tx-pool-price-bump).
### `BLOB` transactions
If sending a [`BLOB` transaction](types.md#blob-transactions), the old transaction is replaced if BOTH of the following are true:
- The new transaction's gas price is higher than the existing gas price by the percentage specified by
[`--tx-pool-price-bump`](../../reference/options.md#tx-pool-price-bump).
- The new transaction's maximum fee per blob gas is higher than the existing maximum fee per blob gas by the percentage specified by
[`--tx-pool-blob-price-bump`](../../reference/options.md#tx-pool-blob-price-bump).
### Free gas networks
In [free gas networks](../../../private-networks/how-to/configure/free-gas.md), the transaction pool price bump is `0` by default,
so replacement transactions can use the same gas price as the pending transaction.
If [`zeroBaseFee`](../../reference/genesis-items.md) is not set, you can set
[`--tx-pool-price-bump`](../../reference/options.md#tx-pool-price-bump) to require a higher gas price when replacing transactions
that use a nonzero gas price.
---
## Transaction types
You can interact with the Besu JSON-RPC API using different transaction types (specified by the `transactionType` parameter).
The following API objects use a unique format for each `transactionType`:
- [Pending transaction object](../../reference/api/txpool.md#txpool_besupendingtransactions)
- [Transaction object](../../reference/api/eth/transaction.md#eth_gettransactionbyhash)
- [Transaction call object](../../reference/api/eth/execute.md#eth_call)
- [Transaction receipt object](../../reference/api/eth/transaction.md#eth_gettransactionreceipt)
## `FRONTIER` transactions
Transactions with type `FRONTIER` are _legacy transactions_ that use the transaction format existing before typed transactions were introduced in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718). They contain the parameters `chainId`, `nonce`, `gasPrice`, `gasLimit`, `to`, `value`, `data`, `v`, `r`, and `s`. Legacy transactions don't use [access lists](#access_list-transactions) or incorporate [EIP-1559 fee market changes](#eip1559-transactions).
## `ACCESS_LIST` transactions
Transactions with type `ACCESS_LIST` are transactions introduced in [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930). They contain, along with the [legacy parameters](#frontier-transactions), an `accessList` parameter, which specifies an array of addresses and storage keys that the transaction plans to access (an _access list_). `ACCESS_LIST` transactions must specify an access list, and they don't incorporate [EIP-1559 fee market changes](#eip1559-transactions).
Use the [`eth_createAccessList`](../../reference/api/eth/execute.md#eth_createaccesslist) API to simulate a transaction which returns the addresses and storage keys that may be used to send the real transaction, and the approximate gas cost.
## `EIP1559` transactions
Transactions with type `EIP1559` are transactions introduced in [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md). EIP-1559 addresses the network congestion and overpricing of transaction fees caused by the historical fee market, in which users send transactions specifying a gas price bid using the `gasPrice` parameter, and miners choose transactions with the highest bids.
`EIP1559` transactions don't specify `gasPrice`, and instead use an in-protocol, dynamically changing _base fee_ per gas. At each block, the base fee per gas is adjusted to address network congestion as measured by a gas target.
`EIP1559` transactions contain, along with the [`accessList`](#access_list-transactions) parameter and [legacy parameters](#frontier-transactions) except for `gasPrice`, a `maxPriorityFeePerGas` parameter, which specifies the maximum fee the sender is willing to pay per gas above the base fee (the maximum _priority fee_ per gas), and a `maxFeePerGas` parameter, which specifies the maximum total fee (base fee + priority fee) the sender is willing to pay per gas.
An `EIP1559` transaction always pays the base fee of the block it's included in, and it pays a priority fee as priced by `maxPriorityFeePerGas` or, if the base fee per gas + `maxPriorityFeePerGas` exceeds `maxFeePerGas`, it pays a priority fee as priced by `maxFeePerGas` minus the base fee per gas. The base fee is burned, and the priority fee is paid to the miner that included the transaction. A transaction's priority fee per gas incentivizes miners to include the transaction over other transactions with lower priority fees per gas.
`EIP1559` transactions must specify both `maxPriorityFeePerGas` and `maxFeePerGas`. They must not specify `gasPrice`.
## `BLOB` transactions
Shard blob transactions introduced in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) enable scaling the
Ethereum network by allowing large amounts of data (blobs) to be included that cannot be directly accessed or
processed by the Ethereum Virtual Machine (EVM).
When the network includes a blob-carrying transaction in a block, the transaction doesn't actually contain
the blob data itself. Instead, it contains a commitment to this data. The EVM can verify this commitment to
ensure the data's availability and integrity without directly accessing the data.
:::info
A commitment is a type of cryptographic proof that securely and verifiably confirms the existence and integrity
of large data blobs.
:::
This mechanism significantly reduces the computational and storage burden on the Ethereum network while ensuring
that the data is available for those who need it (for example, rollups or other layer 2 solutions that rely on data
availability for their security and operation).
Blobs are temporarily stored by consensus clients such as Teku, and blocks on the execution layer permanently store
the reference to the blob.
:::tip
Configure the maximum number of blobs per block and transaction using the
[`--max-blobs-per-block`](../../reference/options.md#max-blobs-per-block) and
[`--max-blobs-per-transaction`](../../reference/options.md#max-blobs-per-transaction) CLI options.
:::
### View blob transaction costs
Use the [`eth_blobBaseFee`](../../reference/api/eth/fee.md#eth_blobbasefee) method to view the current base
fee per blob gas in wei.
You can also use [`eth_feeHistory`](../../reference/api/eth/fee.md#eth_feehistory) to view the historical
blob transaction cost details.
---
## Transaction validation
For each transaction submitted and added to a block, Besu checks the following:
- The nonce is high enough.
- Permissions are correct.
- The transaction is well formed.
- The sender is valid.
- There is a sufficient account balance.
- The chain ID is correct.
- The gas limit is high enough.
The following diagram illustrates when Besu validates transactions (indicated by a check mark):

Besu repeats the set of transaction pool validations after propagating the transaction. Besu repeats the same set of validations when importing the block that includes the transaction, except the nonce must be exactly right when importing the block.
When adding the transaction to a block, Besu performs an additional validation to check that the transaction gas limit is less than the remaining block gas limit. After creating a block, the node imports the block and then repeats the transaction pool validations.
:::info
The transaction is only added if the entire transaction gas limit is less than the remaining gas for the block. The total gas used by the transaction is not relevant to this validation. That is, if the total gas used by the transaction is less than the remaining block gas, but the transaction gas limit is more than the remaining block gas, the transaction is not added.
:::
---
## Connect to a network overview
# Connect to a network
This section provides information on connecting Besu to a public Ethereum network.
:::note
Besu is also compatible with [Linea](https://docs.linea.build/get-started/how-to/run-a-node/besu), the Ethereum L2.
:::
---
## Connect to Mainnet
:::info
As a [Proof of Stake network](../../concepts/proof-of-stake/index.md), running a full Ethereum node requires both [an execution client and a consensus client](../../concepts/node-clients.md#execution-and-consensus-clients).
:::
Run Besu as an [execution client](../../concepts/node-clients.md#execution-clients) with any [consensus client](../../concepts/node-clients.md#consensus-clients) on Ethereum Mainnet.
If you're using [Teku] as a consensus client, you can follow the [Besu and Teku Mainnet tutorial](../../tutorials/besu-teku-mainnet.md).
## Prerequisites
- [Besu installed](../install/binary-distribution.md).
- A consensus client installed. For example, [Teku](https://docs.teku.consensys.net/en/latest/).
## Steps
### 1. Generate the shared secret
Run the following command:
```bash
openssl rand -hex 32 | tr -d "\n" > jwtsecret.hex
```
You will specify `jwtsecret.hex` when starting Besu and the consensus client. This is a shared JWT secret the clients use to authenticate each other when using the [Engine API](../../how-to/use-engine-api.md).
### 2. Generate validator keys
If you're running the consensus client as a beacon node only, skip to the [next step](#3-start-besu).
If you're also running the consensus client as a validator client, have a funded Ethereum address ready (32 ETH and gas fees for each validator).
Generate validator keys for one or more validators using the [Staking Launchpad](https://launchpad.ethereum.org/en/).
:::info
Save the password you use to generate each key pair in a `.txt` file. You should also have a `.json` file for each validator key pair.
:::
### 3. Start Besu
Run the following command or specify the options in a [configuration file](../../how-to/configure-besu/index.md):
```bash
besu \
--rpc-http-enabled=true \
--rpc-http-host=0.0.0.0 \
--rpc-ws-enabled=true \
--rpc-ws-host=0.0.0.0 \
--host-allowlist=,127.0.0.1,localhost \
--engine-host-allowlist=,127.0.0.1,localhost \
--engine-rpc-enabled \
--engine-jwt-secret=
```
Specify:
- The path to the `jwtsecret.hex` file generated in [step 1](#1-generate-the-shared-secret) using the [`--engine-jwt-secret`](../../reference/options.md#engine-jwt-secret) option.
- The IP address of your Besu node using the [`--host-allowlist`](../../reference/options.md#host-allowlist) and [`--engine-host-allowlist`](../../reference/options.md#engine-host-allowlist) options.
Also, in the command:
- [`--rpc-http-enabled`](../../reference/options.md#rpc-http-enabled) enables the HTTP JSON-RPC service.
- [`--rpc-http-host`](../../reference/options.md#rpc-http-host) is set to `0.0.0.0` to allow remote RPC connections.
- [`--rpc-ws-enabled`](../../reference/options.md#rpc-ws-enabled) enables the WebSocket JSON-RPC service.
- [`--rpc-ws-host`](../../reference/options.md#rpc-ws-host) is set to `0.0.0.0` to allow remote RPC connections.
- [`--engine-rpc-enabled`](../../reference/options.md#engine-rpc-enabled) enables the [Engine API](../../reference/engine-api.md).
You can modify the option values and add other [command line options](../../reference/options.md) as needed.
### 4. Start the consensus client
Refer to your consensus client documentation to configure and start the consensus client.
:::info
If you're running a validator client, make sure you set a fee recipient address.
:::
If you're using Teku, follow the [Besu and Teku Mainnet tutorial](../../tutorials/besu-teku-mainnet.md#5-start-teku).
### 5. Wait for the clients to sync
After starting Besu and the consensus client, your node starts syncing and connecting to peers.
```bash
{"@timestamp":"2023-02-03T04:43:49,555","level":"INFO","thread":"main","class":"DefaultSynchronizer","message":"Starting synchronizer.","throwable":""}
{"@timestamp":"2023-02-03T04:43:49,556","level":"INFO","thread":"main","class":"SnapSyncDownloader","message":"Starting sync","throwable":""}
{"@timestamp":"2023-02-03T04:43:49,559","level":"INFO","thread":"main","class":"Runner","message":"Ethereum main loop is up.","throwable":""}
{"@timestamp":"2023-02-03T04:43:53,106","level":"INFO","thread":"Timer-0","class":"DNSResolver","message":"Resolved 2409 nodes","throwable":""}
{"@timestamp":"2023-02-03T04:45:04,803","level":"INFO","thread":"nioEventLoopGroup-3-10","class":"SnapWorldStateDownloader","message":"Downloading world state from peers for pivot block 16545859 (0x616ae3c4cf85f95a9bce2814a7282d75dc2eac36
cb9f0fcc6f16386df70da3c5). State root 0xa7114541f42c62a72c8b6bb9901c2ccf4b424cd7f76570a67b82a183b02f25dc pending requests 0","throwable":""}
{"@timestamp":"2023-02-03T04:46:04,834","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.08%, Peer count: 8","throwable":""}
{"@timestamp":"2023-02-03T04:48:01,840","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.23%, Peer count: 8","throwable":""}
{"@timestamp":"2023-02-03T04:49:09,931","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.41%, Peer count: 11","throwable":""}
{"@timestamp":"2023-02-03T04:50:12,466","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.61%, Peer count: 10","throwable":""}
{"@timestamp":"2023-02-03T04:51:20,977","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.75%, Peer count: 10","throwable":""}
{"@timestamp":"2023-02-03T04:51:28,985","level":"INFO","thread":"EthScheduler-Services-29 (importBlock)","class":"ImportBlocksStep","message":"Block import progress: 180400 of 16545859 (1%)","throwable":""}
```
```bash
2022-03-21 20:43:24.355 INFO - Syncing *** Target slot: 76092, Head slot: 2680, Remaining slots: 73412, Connected peers: 8
2022-03-21 20:43:36.363 INFO - Syncing *** Target slot: 76093, Head slot: 2879, Remaining slots: 73214, Connected peers: 10
2022-03-21 20:43:48.327 INFO - Syncing *** Target slot: 76094, Head slot: 3080, Remaining slots: 73014, Connected peers: 8
2022-03-21 20:44:00.339 INFO - Syncing *** Target slot: 76095, Head slot: 3317, Remaining slots: 72778, Connected peers: 6
2022-03-21 20:44:12.353 INFO - Syncing *** Target slot: 76096, Head slot: 3519, Remaining slots: 72577, Connected peers: 9
```
If you're running the consensus client as a beacon node only, you're all set. If you're also running the consensus client as a validator client, ensure your clients are fully synced before submitting your staking deposit in the next step. Syncing Besu can take several days.
### 6. Stake ETH
Stake your ETH for one or more validators using the [Staking Launchpad](https://launchpad.ethereum.org/en/).
You can check your validator status by searching your Ethereum address on the [Beacon Chain explorer](https://beaconcha.in/). It may take up to multiple days for your validator to be activated and start proposing blocks.
[Teku]: https://docs.teku.consensys.net/en/stable/
---
## Connect to a testnet
Run Besu as an [execution client](../../concepts/node-clients.md#execution-clients) with any consensus client on the [Hoodi](https://github.com/eth-clients/hoodi), [Sepolia](https://github.com/eth-clients/sepolia), or [Ephemery](https://github.com/ephemery-testnet/ephemery-resources) testnet.
If you're using [Teku](https://docs.teku.consensys.net/en/latest/) as a consensus client, you can follow the [Besu and Teku testnet tutorial](../../tutorials/besu-teku-testnet.md).
:::note
- Sepolia is a permissioned network and you can't run a validator client on it without
[requesting to become a validator](https://notes.ethereum.org/zvkfSmYnT0-uxwwEegbCqg) first. You can connect
your consensus client using the beacon node only, without any validator duties.
- Ephemery is a single network that resets to the genesis block after a set period. The network focuses on
short-term, intensive testing use cases. This approach avoids issues like insufficient testnet funds, inactive
validators, and state bloat that long-running testnets face.
:::
## Prerequisites
- [Besu installed](../install/binary-distribution.md).
- A consensus client installed. For example, [Teku](https://docs.teku.consensys.net/en/latest/).
## Steps
### 1. Generate the shared secret
Run the following command:
```bash
openssl rand -hex 32 | tr -d "\n" > jwtsecret.hex
```
You will specify `jwtsecret.hex` when starting Besu and the consensus client. This is a shared JWT secret the clients use to authenticate each other when using the [Engine API](../../how-to/use-engine-api.md).
### 2. Generate validator keys
If you're running the consensus client as a beacon node only, skip to the [next step](#3-start-besu).
If you're also running the consensus client as a validator client, create a test Ethereum address
(you can do this in [MetaMask](https://support.metamask.io/configure/accounts/how-to-add-accounts-in-your-wallet/)).
Fund this address with testnet ETH (32 ETH and gas fees for each validator) using a faucet. See the faucets for the relevant testnet:
- [Hoodi](https://github.com/eth-clients/hoodi)
- [Sepolia](https://github.com/eth-clients/sepolia)
- [Ephemery](https://ephemery-faucet.pk910.de/)
:::note
If you can't get testnet ETH using the faucet, you can ask for help on the [EthStaker Discord](https://discord.gg/ethstaker).
:::
Generate validator keys for one or more validators using the [Hoodi Staking Launchpad](https://hoodi.launchpad.ethereum.org/), [Ephemery Staking Launchpad](https://launchpad.ephemery.dev/), or [request to become validator on Sepolia](https://notes.ethereum.org/zvkfSmYnT0-uxwwEegbCqg).
:::info
Save the password you use to generate each key pair in a `.txt` file. You should also have a `.json` file for each validator key pair.
:::
### 3. Start Besu
Run the following command or specify the options in a [configuration file](../../how-to/configure-besu/index.md):
```bash
besu \
--network=hoodi \
--rpc-http-enabled=true \
--rpc-http-host=0.0.0.0 \
--rpc-http-cors-origins="*" \
--rpc-ws-enabled=true \
--rpc-ws-host=0.0.0.0 \
--host-allowlist="*" \
--engine-host-allowlist="*" \
--engine-rpc-enabled \
--engine-jwt-secret=
```
```bash
besu \
--network=sepolia \
--rpc-http-enabled=true \
--rpc-http-host=0.0.0.0 \
--rpc-http-cors-origins="*" \
--rpc-ws-enabled=true \
--rpc-ws-host=0.0.0.0 \
--host-allowlist="*" \
--engine-host-allowlist="*" \
--engine-rpc-enabled \
--engine-jwt-secret=
```
```bash
besu \
--network=ephemery \
--rpc-http-enabled=true \
--rpc-http-host=0.0.0.0 \
--rpc-http-cors-origins="*" \
--rpc-ws-enabled=true \
--rpc-ws-host=0.0.0.0 \
--host-allowlist="*" \
--engine-host-allowlist="*" \
--engine-rpc-enabled \
--engine-jwt-secret=
```
Specify the path to the `jwtsecret.hex` file generated in [step 1](#1-generate-the-shared-secret) using the [`--engine-jwt-secret`](../../reference/options.md#engine-jwt-secret) option.
You can modify the option values and add other [command line options](../../reference/options.md) as needed.
### 4. Start the consensus client
Refer to your consensus client documentation to configure and start the consensus client.
:::info
If you're running a validator client, make sure you set a fee recipient address.
:::
If you're using Teku, follow the [Besu and Teku testnet tutorial](../../tutorials/besu-teku-testnet.md#5-start-teku).
### 5. Wait for the clients to sync
After starting Besu and the consensus client, your node starts syncing and connecting to peers.
```bash
{"@timestamp":"2023-02-03T04:43:49,555","level":"INFO","thread":"main","class":"DefaultSynchronizer","message":"Starting synchronizer.","throwable":""}
{"@timestamp":"2023-02-03T04:43:49,556","level":"INFO","thread":"main","class":"FastSyncDownloader","message":"Starting sync","throwable":""}
{"@timestamp":"2023-02-03T04:43:49,559","level":"INFO","thread":"main","class":"Runner","message":"Ethereum main loop is up.","throwable":""}
{"@timestamp":"2023-02-03T04:43:53,106","level":"INFO","thread":"Timer-0","class":"DNSResolver","message":"Resolved 2409 nodes","throwable":""}
{"@timestamp":"2023-02-03T04:45:04,803","level":"INFO","thread":"nioEventLoopGroup-3-10","class":"SnapWorldStateDownloader","message":"Downloading world state from peers for pivot block 16545859 (0x616ae3c4cf85f95a9bce2814a7282d75dc2eac36
cb9f0fcc6f16386df70da3c5). State root 0xa7114541f42c62a72c8b6bb9901c2ccf4b424cd7f76570a67b82a183b02f25dc pending requests 0","throwable":""}
{"@timestamp":"2023-02-03T04:46:04,834","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.08%, Peer count: 8","throwable":""}
{"@timestamp":"2023-02-03T04:48:01,840","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.23%, Peer count: 8","throwable":""}
{"@timestamp":"2023-02-03T04:49:09,931","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.41%, Peer count: 11","throwable":""}
{"@timestamp":"2023-02-03T04:50:12,466","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.61%, Peer count: 10","throwable":""}
{"@timestamp":"2023-02-03T04:51:20,977","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.75%, Peer count: 10","throwable":""}
{"@timestamp":"2023-02-03T04:51:28,985","level":"INFO","thread":"EthScheduler-Services-29 (importBlock)","class":"FastImportBlocksStep","message":"Block import progress: 180400 of 16545859 (1%)","throwable":""}
```
```bash
2022-03-21 20:43:24.355 INFO - Syncing *** Target slot: 76092, Head slot: 2680, Remaining slots: 73412, Connected peers: 8
2022-03-21 20:43:36.363 INFO - Syncing *** Target slot: 76093, Head slot: 2879, Remaining slots: 73214, Connected peers: 10
2022-03-21 20:43:48.327 INFO - Syncing *** Target slot: 76094, Head slot: 3080, Remaining slots: 73014, Connected peers: 8
2022-03-21 20:44:00.339 INFO - Syncing *** Target slot: 76095, Head slot: 3317, Remaining slots: 72778, Connected peers: 6
2022-03-21 20:44:12.353 INFO - Syncing *** Target slot: 76096, Head slot: 3519, Remaining slots: 72577, Connected peers: 9
```
If you're running the consensus client as a beacon node only, you're all set. If you're also running the consensus client as a validator client, ensure your clients are fully synced before submitting your staking deposit in the next step. This can take several days.
### 6. Stake ETH
Stake your testnet ETH for one or more validators using the
[Hoodi Staking Launchpad](https://hoodi.launchpad.ethereum.org/) or
[Ephemery Staking Launchpad](https://launchpad.ephemery.dev/).
You can check your validator status by searching your Ethereum address on the
[Hoodi explorer](https://hoodi.etherscan.io/) or
[Ephemery explorer](https://explorer.ephemery.dev/). It may take up to multiple days
for your validator to be activated and start proposing blocks.
---
## Install binary distribution
## MacOS with Homebrew
### Prerequisites
- [Homebrew](https://brew.sh/)
- Java JDK
:::caution
Besu supports:
- MacOS High Sierra 10.13 or later versions.
- Java 25+. You can install Java using `brew install openjdk@25`. Alternatively, you can manually
install the [Java JDK](https://www.oracle.com/java/technologies/downloads).
:::
### Install (or upgrade) using Homebrew
To install Besu using Homebrew:
```bash
brew tap besu-eth/besu
brew install besu-eth/besu/besu
```
To upgrade an existing Besu installation using Homebrew:
```bash
brew upgrade besu-eth/besu/besu
```
:::note notes
- If you upgraded your MacOS version between installing and upgrading Besu, when running `brew upgrade besu-eth/besu/besu` you
might be prompted to reinstall command line tools with `xcode-select --install`.
- When upgrading Besu, you might be prompted to fix the remote branch names in Homebrew by using the command `brew tap --repair`.
:::
To display the Besu version and confirm installation:
```bash
besu --version
```
To display Besu command line help:
```bash
besu --help
```
## Linux / Unix
### Prerequisites
- [Java JDK 25+](https://www.oracle.com/java/technologies/downloads/)
:::note Linux open file limit
If synchronizing to Mainnet on Linux or other chains with large data requirements, increase the
maximum number of open files allowed using `ulimit`. If the open files limit is not high enough, a
`Too many open files` RocksDB exception occurs.
:::
:::tip
We recommend installing [jemalloc](https://jemalloc.net/) to reduce memory usage. If using Ubuntu, you
can install it with the command: `apt install libjemalloc-dev`.
:::
### Install from packaged binaries
Download the Besu [packaged binaries](https://github.com/besu-eth/besu/releases).
Unpack the downloaded files and change into the `besu-` directory.
Display Besu command line help to confirm installation:
```bash
bin/besu --help
```
### Upgrade Besu
See the [Upgrade Besu](../../how-to/upgrade-node.md#upgrade-on-linux) guide for instructions on upgrading Besu on Linux.
---
## Installation options
- [Docker image](run-docker-image.md)
- [Binaries](binary-distribution.md)
## Build from source
If you want to use the latest development version of Besu or a specific commit, build from source. Otherwise, use the [binary] or [Docker image] for more stable versions.
View the [Wiki] for instructions to install Besu from source.
[Wiki]: https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22154264/Building+from+source
[binary]: binary-distribution.md
[Docker image]: run-docker-image.md
---
## Run Besu from Docker image
# Run Besu from a Docker image
Besu provides a Docker image to run a Besu node in a Docker container.
Use this Docker image to run a single Besu node without installing Besu.
## Prerequisites
- [Docker](https://docs.docker.com/install/)
- MacOS or Linux
:::info
The Docker image doesn't run on Windows.
:::
## Default node for Mainnet
To run a Besu node in a container connected to the Ethereum Mainnet:
```bash
docker run hyperledger/besu:latest
```
:::note
https://hub.docker.com/r/hyperledger/besu/tags lists the available tags for the image.
If you previously pulled `latest`, Docker runs the cached version.
To ensure your image is up to date, pull the `latest` version again using `docker pull hyperledger/besu:latest`.
:::
## Expose ports
Expose ports for P2P discovery, GraphQL, metrics, and HTTP and WebSocket JSON-RPC. You need to expose the ports to use the default ports or the ports specified using [`--rpc-http-port`](../../reference/options.md#rpc-http-port), [`--p2p-port`](../../reference/options.md#p2p-port), [`--rpc-ws-port`](../../reference/options.md#rpc-ws-port), [`--metrics-port`](../../reference/options.md#metrics-port), [`--graphql-http-port`](../../reference/options.md#graphql-http-port), and [`--metrics-push-port`](../../reference/options.md#metrics-push-port) options.
To run Besu exposing local ports for access:
```bash
docker run -p :8545 -p :8546 -p :30303 hyperledger/besu:latest --rpc-http-enabled --rpc-ws-enabled
```
:::note
The examples on this page expose TCP ports only. To expose UDP ports, specify `/udp` at the end of the argument for the `-p` Docker subcommand option:
```bash
docker run -p :/udp
```
See the [`docker run -p` documentation](https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port--p---expose).
:::
To enable JSON-RPC HTTP calls to `127.0.0.1:8545` and P2P discovery on `127.0.0.1:13001`:
```bash
docker run -p 8545:8545 -p 13001:30303 hyperledger/besu:latest --rpc-http-enabled
```
## Start Besu
:::danger
Don't mount a volume at the default data path (`/opt/besu`). Mounting a volume at the default data path interferes with the operation of Besu and prevents Besu from safely launching.
To run a node that maintains the node state (key and database), [`--data-path`](../../reference/options.md#data-path) must be set to a location other than `/opt/besu` and a storage volume mounted at that location.
When running in a Docker container, [`--nat-method`](../../how-to/connect/specify-nat.md) must be set to `DOCKER` or `AUTO` (default). Don't set [`--nat-method`](../../how-to/connect/specify-nat.md) to `NONE` or `UPNP`.
:::
You can specify [Besu environment variables](../../reference/options.md#specify-options) with the Docker image instead of the command line options.
```bash title="Example"
docker run -p 30303:30303 -p 8545:8545 -e BESU_RPC_HTTP_ENABLED=true -e BESU_NETWORK=sepolia hyperledger/besu:latest
```
:::caution Unsupported address type exception
When running Besu from a Docker image, you might get the following exception:
```bash
Unsupported address type exception when connecting to peer {}, this is likely due to ipv6 not being enabled at runtime.
```
This happens when the IPv6 support in Docker is disabled while connecting to an IPv6 peer, preventing outbound communication. IPv6 is disabled by default in Docker.
[Enable IPv6 support in Docker](https://docs.docker.com/config/daemon/ipv6/) to allow outbound IPv6 traffic and allow connection with IPv6 peers.
:::
### Run a node for testing
To run a node that mines blocks at a rate suitable for testing purposes with WebSocket enabled:
```bash
docker run -p 8546:8546 --mount type=bind,source=/,target=/var/lib/besu hyperledger/besu:latest --rpc-ws-enabled --network=dev --data-path=/var/lib/besu
```
### Run a node on Sepolia testnet
To run a node on Sepolia:
```bash
docker run -p 30303:30303 --mount type=bind,source=/,target=/var/lib/besu hyperledger/besu:latest --network=sepolia --data-path=/var/lib/besu
```
### Run a node on Ethereum Mainnet
To run a node on Ethereum Mainnet with the HTTP JSON-RPC service enabled:
```bash
docker run -p 8545:8545 --mount type=bind,source=/,target=/var/lib/besu -p 30303:30303 hyperledger/besu:latest --rpc-http-enabled --data-path=/var/lib/besu
```
## Stop Besu and clean up resources
When done running nodes, you can shut down the node container without deleting resources or you can delete the container after stopping it. Run `docker container ls` and `docker volume ls` to get the container and volume names.
To stop a container:
```bash
docker stop
```
To delete a container:
```bash
docker rm
```
## Upgrade Besu
See the [Upgrade Besu](../../how-to/upgrade-node.md#upgrade-on-docker) guide for instructions on upgrading Besu on Docker.
---
## Migrate to Besu
Migrate from a different Ethereum [execution client](../concepts/node-clients.md#execution-clients) to Besu to contribute to [client diversity](https://clientdiversity.org/).
To migrate from a different client, [configure Besu as an execution client](connect/mainnet.md#3-start-besu) and connect your [consensus client](../concepts/node-clients.md#consensus-clients) to Besu instead of your original execution client.
To minimize downtime while [Besu syncs](../concepts/node-sync.md) and avoid downtime penalties, you can sync Besu with a new consensus layer instance. Once Besu has fully synced you can connect it to your existing consensus client.
Find guides to switch from specific clients on the [client diversity website](https://clientdiversity.org/#switch).
---
## Start Besu
Nodes can connect to Ethereum Mainnet, [Linea](https://docs.linea.build/get-started/how-to/run-a-node), and their respective public testnets.
Use the [`besu`](../reference/options.md) command with the required command line options to start a node.
## Prerequisites
[Besu installed](install/binary-distribution.md)
## Local block data
When connecting to a network other than the network previously connected to, you must either delete the local block data or use the [`--data-path`](../reference/options.md#data-path) option to specify a different data directory.
To delete the local block data, delete the `database` directory in the `besu/build/distribution/besu-` directory.
## Genesis configuration
Besu specifies the genesis configuration, and sets the network ID and bootnodes when connecting to [ETH testnets](#run-a-node-on-an-ethereum-testnet), and [Mainnet](#run-a-node-on-ethereum-mainnet).
When you specify [`--network=dev`](../reference/options.md#network), Besu uses the development network genesis configuration, which is intended for local development and testing. A node started with [`--network=dev`](../reference/options.md#network) has an empty bootnodes list by default.
The genesis files defining the genesis configurations are in the [Besu source files](https://github.com/besu-eth/besu/tree/master/config/src/main/resources).
To define a genesis configuration, create a genesis file (for example, `genesis.json`) and specify the file using the [`--genesis-file`](../reference/options.md#genesis-file) option.
## Syncing and storage
By default, Besu syncs to the current state of the blockchain using [snap sync](../concepts/node-sync.md#snap-synchronization) in:
- Networks specified using [`--network`](../reference/options.md#network) except for the `dev` development network.
- Ethereum Mainnet.
We recommend using [snap sync](../concepts/node-sync.md#snap-synchronization) for a faster sync, by starting Besu with [`--sync-mode=SNAP`](../reference/options.md#sync-mode).
By default, Besu stores data in the [Bonsai Tries format](../concepts/data-storage-formats.md#bonsai-tries).
## Run a node on an Ethereum testnet
To run a node on [Hoodi](https://github.com/eth-clients/hoodi) specifying a data directory:
```bash
besu --network=hoodi --data-path=/
```
Where `` and `` are the path and directory to save the Hoodi chain data to.
To run a node on [Sepolia](https://github.com/eth-clients/sepolia) specifying a data directory:
```bash
besu --network=sepolia --data-path=/
```
Where `` and `` are the path and directory to save the Sepolia chain data to.
To run a node on [Ephemery](https://github.com/ephemery-testnet/ephemery-resources?tab=readme-ov-file) specifying a data directory:
```bash
besu --network=ephemery --data-path=/
```
Where `` and `` are the path and directory to save the Ephemery chain data to.
See the [guide on connecting to a testnet](connect/testnet.md) for more information.
## Run a node on Ethereum Mainnet
To run a node on the Ethereum Mainnet:
```bash
besu
```
To run a node on Mainnet with the HTTP JSON-RPC service enabled and available for localhost only:
```bash
besu --rpc-http-enabled
```
See the [guide on connecting to Mainnet](connect/mainnet.md) for more information.
## Confirm node is running
If you started Besu with the [`--rpc-http-enabled`](../reference/options.md#rpc-http-enabled) option, use [cURL](https://curl.haxx.se/) to call [JSON-RPC API methods](../reference/api/index.md) to confirm the node is running.
- `eth_chainId` returns the chain ID of the network.
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' localhost:8545/ -H "Content-Type: application/json"
```
- `eth_syncing` returns the starting, current, and highest block.
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' localhost:8545/ -H "Content-Type: application/json"
```
For example, after connecting to Mainnet, `eth_syncing` will return something similar to:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"startingBlock": "0x0",
"currentBlock": "0x2d0",
"highestBlock": "0x66c0"
}
}
```
---
## System requirements
Determine public network system requirements by checking CPU and disk space requirements using [Prometheus](../how-to/monitor/metrics.md). Grafana provides a [sample dashboard](https://grafana.com/grafana/dashboards/10273) for Besu.
:::tip
CPU requirements are highest when syncing to the network and typically reduce after the node is synchronized to the chain head.
:::
## Java distribution and installation
Besu requires an installation of Java 25+ to run.
We currently recommend two Java distributions, [OpenJDK 25](https://jdk.java.net/25/) and
[OpenJ9](https://www.eclipse.org/openj9/), though you can experiment based on your needs.
OpenJDK is the default for many Java users and is balanced in performance and garbage collection.
OpenJ9 consumes less memory and system resources, but can have worse performance on some setups.
If you have more than 32GB RAM (for Besu and your [consensus client](../concepts/node-clients.md#consensus-clients)), use OpenJDK.
If you have less RAM:
* If you're on Linux (or Unix-based) and your CPU is x86-64 bit architecture (like Intel), use OpenJ9.
* If you're on ARM-64 CPU architecture (Mac M-series, Raspberry Pi), use OpenJDK.
If you have OpenJDK installed or need a fresh installation of OpenJ9, you can pick up the OpenJ9
docker image, or install the OpenJ9 JDK using the following steps:
1. Get the [binaries](https://github.com/ibmruntimes/semeru25-certified-binaries/releases) corresponding to
your OS architecture.
For example:
```bash
wget https://github.com/ibmruntimes/semeru25-certified-binaries/releases/download/jdk-25.0.3.0/ibm-semeru-certified-jdk_x64_linux_25.0.3.0.tar.gz
```
2. Uncompress the binaries:
```bash
tar -xvf YOUR_J9_IMAGE.tar.gz
```
```bash
tar -xvf ibm-semeru-certified-jdk_x64_linux_25.0.3.0.tar.gz
```
3. Move the binaries to `bin` directory:
```bash
sudo cp -r YOUR_IMAGE/ /usr/bin/
```
```bash
sudo cp -r jdk-25.0.3+9/ /usr/bin/
```
4. Specify OpenJ9 for Java on your machine:
```bash
sudo update-alternatives --install "/usr/bin/java" "java" "/usr/bin/YOUR_IMAGE" 1
sudo update-alternatives --config java (and choose OpenJ9)
```
```bash
sudo update-alternatives --install "/usr/bin/java" "java" "/usr/bin/jdk-25.0.3+9/bin/java"
```
Change your `JAVA_HOME` to OpenJ9 (if using the JDK implementation), where `jdk-install-dir` is
the installation location you specified:
```bash
export JAVA_HOME=jdk-install-dir
```
```bash
export JAVA_HOME=/usr/bin/jdk-25.0.3+9
```
## Java Virtual Machine size
For Mainnet and testnets, the minimum [Java Virtual Machine (JVM) memory requirement is 8 GB](../how-to/configure-java/manage-memory.md).
JVM memory requirements are highest when syncing, but will reduce after the node is synchronized to the chain head. Monitor your system to determine your actual JVM memory needs.
## Disk space
The disk space required for syncing a Besu node depends on the
[sync mode](../concepts/node-sync.md#sync-modes) and
[data storage format](../concepts/data-storage-formats.md) used.
Using snap sync with Bonsai on Mainnet requires about 1.14 TB.
See the current [Mainnet storage estimates](../concepts/data-storage-formats.md#storage-estimates) for more information.
## Disk type
Use [local SSD storage](https://cloud.google.com/compute/docs/disks) for high throughput nodes (validators and RPC nodes). Read-only nodes can use a lower performance setup.
You can use local SSDs through [SCSI interfaces](https://en.wikipedia.org/wiki/SCSI). For higher performance in production settings, we recommend upgrading to [NVMe interfaces](https://cloud.google.com/compute/docs/disks/local-ssd#performance).
## Reference environment
Recent Mainnet Bonsai snap sync measurements used AWS `m8g.2xlarge` instances with 8 vCPUs,
30 GiB memory, and a 1.9 TB Amazon EBS data volume.
Performance test nodes used provisioned disk IOPS and throughput.
Using a larger instance or faster disk while synchronizing can reduce sync time.
After the node is synchronized, you can reduce the instance size based on observed CPU, memory,
and disk I/O usage.
:::warning
If you are using a more recent release than 26.5.0, resource requirements may have increased.
:::
---
## Reduce storage for Bonsai Tries
When using the [Bonsai Tries](../concepts/data-storage-formats.md#bonsai-tries) data storage format,
[`--bonsai-limit-trie-logs-enabled`](../reference/options.md#bonsai-limit-trie-logs-enabled) is
enabled by default.
When enabled, this feature can reduce database growth by more than 3 GB each week on Mainnet.
:::note
If [`--sync-mode=FULL`](../reference/options.md#sync-mode) is set, the
[`--bonsai-limit-trie-logs-enabled`](../reference/options.md#bonsai-limit-trie-logs-enabled)
option is disallowed and must be set to `false`.
:::
## Limit and prune trie logs
If you're running Besu without
[`--bonsai-limit-trie-logs-enabled`](../reference/options.md#bonsai-limit-trie-logs-enabled),
you might have a backlog of redundant trie logs.
You can prune these using the following instructions.
:::note
Ensure you are using Besu version 24.6.0 or later.
If you are using an older version, upgrade Besu or refer to the older version of the documentation.
:::
:::caution
The following commands are examples.
Before executing these example commands on your node, modify them to apply to your node's configuration.
:::
1. Stop Besu.
1. (Optional) Run the Besu trie log prune command. Specify the Bonsai Trie data storage format and the data directory for your Besu database:
```bash
sudo /usr/local/bin/besu/bin/besu --data-storage-format=BONSAI --data-path=/var/lib/besu --sync-mode=SNAP storage trie-log prune
```
1. Start Besu.
1. Look for `Limit trie logs enabled: retention: 512; prune window: 30000` in your Besu configuration printout at startup.
### Prune outdated trie logs
When you start Besu with
[`--bonsai-limit-trie-logs-enabled`](../reference/options.md#bonsai-limit-trie-logs-enabled), it
continuously prunes the unnecessary trie log data, removing it one block at a time.
This process begins after an initial reduction in the database size during startup.
Enabling `--bonsai-limit-trie-logs-enabled` on a long-running node does not immediately clear your backlog of trie logs in the same way resyncing does.
Instead of resyncing, you can run an offline command to immediately prune old trie logs.
To run the offline command, you must shut down Besu for a minimal period.
If the `--bonsai-limit-trie-logs-enabled` option is enabled, you do not need to run the offline command again after initially running it.
For minimal downtime, we recommend running the offline command before restarting Besu with `--bonsai-limit-trie-logs-enabled`.
If you are following the guides by [Somer Esat](https://someresat.medium.com/guide-to-staking-on-ethereum-ubuntu-teku-f09ecd9ef2ee) or [CoinCashew](https://www.coincashew.com/coins/overview-eth/guide-or-how-to-setup-a-validator-on-eth2-mainnet/part-i-installation/step-3-installing-execution-client/besu), you have set the following options in your `besu.service` or `execution.service` systemd file:
```bash
...
ExecStart=/usr/local/bin/besu/bin/besu \
...
--sync-mode=SNAP \
--data-path="/var/lib/besu" \
--data-storage-format=BONSAI \
...
```
To prune trie logs, the command should look similar to the following:
```bash
sudo /usr/local/bin/besu/bin/besu --data-storage-format=BONSAI --data-path=/var/lib/besu --sync-mode=SNAP storage trie-log prune
```
The logs should look similar to the following:
```bash
2024-02-02 05:45:41.162+00:00 | main | INFO | KeyPairUtil | Attempting to load public key from /data/besu/key
...
2024-02-02 05:45:43.433+00:00 | main | INFO | TrieLogSubCommand | Estimating trie logs size before pruning...
2024-02-02 05:45:43.837+00:00 | main | INFO | TrieLogSubCommand | Estimated trie logs size before pruning: 9 GiB
2024-02-02 05:46:09.863+00:00 | main | INFO | TrieLogHelper | Starting pruning: retain 512 trie logs, processing in 1 batches...
2024-02-02 05:46:09.918+00:00 | main | INFO | TrieLogHelper | Saving trie logs to retain in file /data/besu/database/trieLogsToRetain-1 (batch 1)...
2024-02-02 05:46:09.926+00:00 | main | INFO | TrieLogHelper | Obtaining trielogs from db, this may take a few minutes...
2024-02-02 05:46:10.100+00:00 | main | INFO | TrieLogHelper | Clear trie logs...
2024-02-02 05:46:10.155+00:00 | main | INFO | TrieLogHelper | Restoring trie logs retained from batch 1...
2024-02-02 05:46:10.222+00:00 | main | INFO | TrieLogHelper | Key(0): 0xcd50706da7f6f2db7f9d54f3589122760900d9ab2508c20a4ca40b496d930368
...
2024-02-02 05:46:10.336+00:00 | main | INFO | TrieLogHelper | Key(511): 0x238f9649b59616430ad7e43b8f3cf65bc97cac4aa54a3eddf3ad6ee666ce733e
2024-02-02 05:46:10.441+00:00 | main | INFO | TrieLogHelper | Deleting files...
2024-02-02 05:46:10.446+00:00 | main | INFO | TrieLogSubCommand | Finished pruning. Re-estimating trie logs size...
2024-02-02 05:46:11.023+00:00 | main | INFO | TrieLogSubCommand | Estimated trie logs size after pruning: 0 B (0 B estimate is normal when using default settings)
2024-02-02 05:46:11.023+00:00 | main | INFO | TrieLogSubCommand | Prune ran successfully. We estimate you freed up 9 GiB!
Prune ran successfully. We estimate you freed up 9 GiB!
```
If you are using a TOML configuration file, you can run a command similar to the following:
```bash
sudo /usr/local/bin/besu/bin/besu --config-file=besu-config.toml storage trie-log prune
```
## Troubleshoot
Troubleshoot common errors that can occur when using the trie log prune command to reduce your database size for Bonsai Tries.
To minimize errors, ensure your command specifies the following:
- [`--data-storage-format`](../reference/options.md#data-storage-format)
- [`--data-path`](../reference/options.md#data-path)
- [`--sync-mode`](../reference/options.md#sync-mode)
### Prune command for Mainnet
The prune command should look similar to the following:
```bash
sudo /usr/local/bin/besu/bin/besu --data-path=/var/lib/besu --data-storage-format=BONSAI --sync-mode=SNAP storage trie-log prune
```
Ensure you stop Besu before running the command.
### Subcommand not working
- `java.lang.IllegalArgumentException: Subcommand only works with data-storage-format=BONSAI`
The `--data-storage-format=BONSAI` might be missing.
To resolve, add the storage format.
The command should look similar to the following:
```bash
sudo /usr/local/bin/besu/bin/besu --data-storage-format=BONSAI --data-path=/var/lib/besu --sync-mode=SNAP storage trie-log prune
```
### Column handle not found for segment `TRIE_BRANCH_STORAGE`
- `java.lang.RuntimeException: Column handle not found for segment TRIE_BRANCH_STORAGE`
Ensure you specify `--data-path`.
Your command should look similar to the following:
```bash
sudo /usr/local/bin/besu/bin/besu --data-path=/var/lib/besu --data-storage-format=BONSAI --sync-mode=SNAP storage trie-log prune
```
### Database not detected
- `java.lang.IllegalArgumentException: Trying to retain more trie logs than chain length (0), skipping pruning`
Ensure you specify the correct `--data-path` for your node.
Your command should look similar to the following:
```bash
sudo /usr/local/bin/besu/bin/besu --data-path=/var/lib/besu --data-storage-format=BONSAI --sync-mode=SNAP storage trie-log prune
```
### Cannot store generated private key
- `java.lang.IllegalArgumentException: Cannot store generated private key`
Ensure you specify the correct `--data-path` for your node.
Your command should look similar to the following:
```bash
sudo /usr/local/bin/besu/bin/besu --data-path=/var/lib/besu --data-storage-format=BONSAI --sync-mode=SNAP storage trie-log prune
```
### Valid keypair not provided
- `java.lang.IllegalArgumentException: Supplied file does not contain valid keyPair pair.`
Check your file permissions and try running a `sudo` command to resolve the issue:
```bash
sudo /usr/local/bin/besu/bin/besu --data-storage-format=BONSAI --data-path=/var/lib/besu storage --sync-mode=SNAP trie-log prune
```
### Column handle not found for segment `WORLD_STATE`
- `java.lang.RuntimeException: Column handle not found for segment WORLD_STATE`
Ensure you are using `--data-storage-format=BONSAI` instead of `--data-storage-format=FOREST` on an existing Bonsai database.
### Resource temporarily unavailable
- `org.hyperledger.besu.plugin.services.exception.StorageException: org.rocksdb.RocksDBException: While lock file: /data/besu/database/LOCK: Resource temporarily unavailable`
Check if Besu is already running.
You must shut down the Besu client before running the subcommand.
### Unable to change the sync mode
- `java.lang.IllegalStateException: Unable to change the sync mode when snap sync is incomplete, please restart with snap sync mode`
Check that you have specified `--sync-mode`.
The default is `--sync-mode=SNAP`.
### Cannot run trie log prune
- `java.lang.RuntimeException: No finalized block present, can't safely run trie log prune`
This message might appear if your node is relatively new or recently resynced.
To resolve this error, ensure that your node is fully synced and correctly configured to recognize finalized blocks.
### Block does not match stored chain data
- `org.hyperledger.besu.util.InvalidConfigurationException: Supplied genesis block does not match chain data stored in /data/besu.`
Check if you are running the command for a network other than Mainnet.
To specify a network, run a command that looks similar to the following:
```bash
sudo /usr/local/bin/besu/bin/besu --network=sepolia --sync-mode=SNAP --data-storage-format=BONSAI --data-path=/var/lib/besu storage trie-log prune
```
---
## Configure Besu
Besu comes with a [default configuration](#default-configuration) that is suitable for staking.
You can override the default values by specifying [options](../../reference/options.md) on the command line, as environment variables, or in a [TOML configuration file](#toml-configuration-file) that can be reused across node startups.
You can also use a [pre-configured profile](profile.md) for some common use cases or create and apply a [custom profile](profile.md#load-external-profiles).
## Configuration order of precedence
For options specified in multiple places, the order of precedence is as follows:
1. Command line
2. Environment variable
3. Configuration file specified by `--config-file`
4. [Pre-configured profile](profile.md) specified by `--profile`
5. Default values (used if no other configuration source is available)
For example, if you specify a `config.toml` configuration file and `staker` profile, and an option
is not found in the environment variables, Besu looks for it in `config.toml`.
If the option is not found in `config.toml`, Besu looks for it in `staker.toml`.
If the option is not found in `staker.toml`, Besu uses the default value for that option.
## TOML configuration file
:::note
The configuration file is used for node-level settings. You can specify network-wide settings in the [genesis file](../../concepts/genesis-file.md).
:::
Specify the configuration file using the [`--config-file`](../../reference/options.md#config-file) option.
The configuration file must be a valid TOML file composed of key/value pairs. Each key is the same as the corresponding command line option name without the leading dashes (`--`).
Values must conform to TOML specifications for string, numbers, arrays, and booleans. Specific differences between the command line and the TOML file format are:
- Comma-separated lists on the command line are string arrays in the TOML file.
- Enclose file paths, hexadecimal numbers, URLs, and <host:port> values in quotes.
Table headings are ignored in TOML files. If you specify a valid Besu option under a table heading in the configuration file, Besu ignores the table heading and reads the option in the same way it does for options not under table headings.
:::tip
The [options reference](../../reference/options.md) includes configuration file examples for each option.
:::
```toml title="Sample TOML configuration file"
# Valid TOML config file
data-path="/path/to/besudata" # Path
# Network
bootnodes=["enode://001@123:4567", "enode://002@123:4567", "enode://003@123:4567"]
p2p-host="1.2.3.4"
p2p-port=1234
max-peers=42
rpc-http-host="5.6.7.8"
rpc-http-port=5678
rpc-ws-host="9.10.11.12"
rpc-ws-port=9101
# Chain
genesis-file="/path/to/genesis.json" # Path to the custom genesis file
```
```bash title="Starting Besu with a configuration file"
besu --config-file=/home/me/me_node/config.toml
```
## Default configuration
The following tables describe important default values of Besu's configuration.
When using the default configuration, Besu is optimized for staking.
You can extend these defaults using a [profile](profile.md).
For example, extending the default configuration using the [staker profile](profile.md#staker-profile) directs Besu to use Mainnet, creating a staking-optimized node ready to run with a [validator and consensus client](../../concepts/node-clients.md#consensus-clients).
### Peering
|Configuration option|Default|Description|
|---------------------------|--------------------|------------------------------------------|
|[`discovery-enabled`](../../reference/options.md#discovery-enabled)|`true`|Besu assumes the node will automatically discover other Ethereum nodes using P2P.|
|[`p2p-enabled`](../../reference/options.md#p2p-enabled)|`true`|Besu assumes the node will connect P2P.|
|[`engine-rpc-enabled`](../../reference/options.md#engine-rpc-enabled)|`true`|The option's default value is `false`, but Besu enables the Engine API automatically on post-Merge networks. Using the default network (Mainnet), the Engine API is enabled.|
### Storage
|Configuration option|Default|Description|
|---------------------------|--------------------|------------------------------------------|
|[`data-storage-format`](../../reference/options.md#data-storage-format)|`BONSAI`|Besu uses [Bonsai Tries](../../concepts/data-storage-formats.md#bonsai-tries), the most space-efficient data storage format.|
### Sync
|Configuration option|Default|Description|
|---------------------------|--------------------|------------------------------------------|
|[`sync-mode`](../../reference/options.md#sync-mode)|`SNAP`|Besu syncs using [snap sync](../../concepts/node-sync.md#snap-synchronization), the most time-efficient sync method.|
:::note
You can see all default configuration values in the [options reference](../../reference/options.md).
:::
---
## Use a profile
You can load a profile to extend Besu's [default configuration](index.md#default-configuration), using the [`--profile`](../../reference/options.md#profile) option.
Profiles simplify the process of configuring Besu for common use cases. Besu provides the following pre-configured profiles:
- [Minimalist staker profile](#minimalist-staker-profile)
- [Staker profile](#staker-profile)
- [Enterprise/Private profile](#enterpriseprivate-profile)
- [Performance profiles](#performance-profiles)
Alternatively, you can customize and [load external profiles](#load-external-profiles).
:::note
Run `./besu --help` to view all available profiles.
:::
:::note
A configuration option specified in the configuration file or on the command line
[overrides the same option](index.md#configuration-order-of-precedence) set in the profile.
:::
## Minimalist staker profile
[`--profile=MINIMALIST_STAKER`](../../reference/options.md#profile) is optimized for stakers who
want to maximize their hardware value but don't want to serve full sets of data to their peers. See the
[minimalist staker profile on GitHub](https://github.com/besu-eth/besu/blob/main/config/src/main/resources/profiles/minimalist-staker.toml)
for the custom settings.
## Staker profile
[`--profile=STAKER`](../../reference/options.md#profile) is optimized for stakers who want to
maximize their hardware value while also serving full sets of data to their peers. See the
[staker profile on GitHub](https://github.com/besu-eth/besu/blob/main/config/src/main/resources/profiles/staker.toml)
for the custom settings.
## Enterprise/Private profile
`ENTERPRISE` and `PRIVATE` are aliases for the same profile. [`--profile=PRIVATE` / `--profile=ENTERPRISE`](../../reference/options.md#profile)
supports private network operators and enterprises by handling specific use cases that apply to
private network operators. See the [enterprise/private profile on
GitHub](https://github.com/besu-eth/besu/blob/main/config/src/main/resources/profiles/enterprise-private.toml)
for the custom settings.
When using this profile, set [`--sync-mode=FULL`](../../reference/options.md#sync-mode)
and [`--data-storage-format=FOREST`](../../reference/options.md#data-storage-format).
## Performance profiles
[`--profile=PERFORMANCE`](../../reference/options.md#profile) supports high-performance nodes by
increasing the RocksDB cache size and enabling parallel transaction execution.
[`--profile=PERFORMANCE_RPC`](../../reference/options.md#profile) supports high-performance RPC nodes by
increasing the RocksDB cache size and caching the last 2048 blocks.
:::note
The performance profiles use early access features.
:::
See the [performance profile](https://github.com/besu-eth/besu/blob/main/config/src/main/resources/profiles/performance.toml)
and [performance RPC profile](https://github.com/besu-eth/besu/blob/main/config/src/main/resources/profiles/performance-rpc.toml)
on GitHub for the custom settings.
## Load external profiles
You can use external profiles to create custom Besu bundles with various plugins and their default options.
Add external profiles to a `profiles` directory under the root Besu directory.
Run Besu with [`--profile`](../../reference/options.md#profile) set to the external profile
file name, without the `.toml` extension.
For example, to load the `profiles/custom_profile.toml` profile, run:
```bash
besu --profile=custom_profile
```
:::note
You can overwrite the directory in which to place external profiles using the `besu.profiles.dir`
system property.
:::
---
## High availability of JSON-RPC and RPC Pub/Sub APIs
To enable high availability to the [RPC Pub/Sub API over WebSocket](../use-besu-api/rpc-pubsub.md) or the [JSON-RPC API](../use-besu-api/json-rpc.md), run and synchronize more than one Besu node to the network. Use a load balancer to distribute requests across nodes in the cluster that are ready to receive requests.

:::tip
We don't recommend putting [bootnodes](../../../private-networks/how-to/configure/bootnodes.md) behind a load balancer.
:::
:::info
We recommend using load balancers over WebSockets because WebSockets are persistent connections associated with specific nodes. If you use load balancers configured in sticky mode over HTTP instead, the connection sticks to the associated node even when the node is congested and there is a lower load node available. If you use load balancers not configured in sticky mode over HTTP, the connections may switch from node to node, so some JSON-RPC requests may not provide expected results (for example, [`admin` methods](../../reference/api/admin.md), [`net_enode`](../../reference/api/net.md#net_enode), [`net_peerCount`](../../reference/api/net.md#net_peercount), and [`eth_syncing`](../../reference/api/eth/client.md#eth_syncing)).
:::
## Determine when a node is ready
Use the [readiness endpoint](../use-besu-api/json-rpc.md#readiness-and-liveness-endpoints) to determine when a node is ready.
:::note
The minimum number of peers and number of blocks from the best known block for determining if a node considered ready is deployment specific.
:::
## Transaction nonces
Besu obtains the nonce for the next transaction using [`eth_getTransactionCount`](../../reference/api/eth/state.md#eth_gettransactioncount). The nonce depends on the transactions in the [transaction pool](../../concepts/transactions/pool.md). If sending [`eth_getTransactionCount`](../../reference/api/eth/state.md#eth_gettransactioncount) and [`eth_sendRawTransaction`](../../reference/api/eth/submit.md#eth_sendrawtransaction) requests for a specific account to more than one node, the [`eth_getTransactionCount`](../../reference/api/eth/state.md#eth_gettransactioncount) results might be incorrect.
To get correct nonces when distributing requests across a cluster, either:
- Track the next nonce outside of the Besu node (as MetaMask does).
- Configure the load balancer in sticky mode to send requests from a specific account to a single node, unless that node is unavailable.
## Subscriptions
You can subscribe to events using:
- [RPC Pub/Sub over WebSockets](../use-besu-api/rpc-pubsub.md).
- [Filters over HTTP](../use-besu-api/access-logs.md).
We recommend using [RPC Pub/Sub over WebSocket](../use-besu-api/rpc-pubsub.md) because WebSockets connections associate with a specific node and do not require using the load balancer in sticky mode.
If using [filters over HTTP](../use-besu-api/access-logs.md), configure the load balancer in sticky mode to associate the subscription with a specific node.
## Recover from dropped subscriptions
Dropped subscriptions can occur because of:
- A disconnected WebSockets connection
- The removal of the node serving the subscription from the ready pool.
If there is a dropped subscription, missed events might occur while reconnecting to a different node. To recover dropped messages, create another subscription and follow the process for that [subscription type](../use-besu-api/rpc-pubsub.md#subscribe):
- [`newHeads`](#new-headers)
- [`logs`](#logs)
- [`newPendingTransactions`](#new-pending-transactions)
- [`droppedPendingTransactions`](#dropped-pending-transactions)
- [`syncing`](#syncing).
### New headers
To request information on blocks from the last block before the subscription dropped to the first block received from the new subscription, use [`eth_getBlockByNumber`](../../reference/api/eth/block.md#eth_getblockbynumber).
### Logs
To request logs from the block number of the last log received before the subscription dropped to the current chain head, use [`eth_getLogs`](../../reference/api/eth/filter.md#eth_getlogs).
### New pending transactions
To request all pending transactions for the new node, use [`txpool_besuTransactions`](../../reference/api/txpool.md#txpool_besutransactions).
:::note
Nodes do not all store the same pending transactions.
:::
### Dropped pending transactions
To request all pending transactions for the new node, use [`txpool_besuTransactions`](../../reference/api/txpool.md#txpool_besutransactions).
:::note
Nodes do not all store the same pending transactions.
:::
### Syncing
The syncing state of each node is specific to that node. To retrieve the syncing state of the new node, use [`eth_syncing`](../../reference/api/eth/client.md#eth_syncing).
---
## Sample load balancer configurations
## AWS
For AWS, we recommend the Classic Load Balancer. The Classic Load Balancer is the easiest to configure and work with. Register the Besu instances to the load balancer and use the [liveness endpoint](../use-besu-api/json-rpc.md#readiness-and-liveness-endpoints) for health checks.
For finer grain control, use the Application Load Balancer:
- Configure one target group with n nodes.
- Configure multiple listeners with one per port (for example, `30303`, `8545`) you are using and route to the target group.
- Use the [liveness endpoint](../use-besu-api/json-rpc.md#readiness-and-liveness-endpoints) for health checks.
- Register the Besu instances multiple times with different ports. This is like configuring microservices on Elastic Container Service (ECS) or Elastic Kubernetes Service (EKS).
### HTTPS redirection
With either AWS load balancer, you can add certificates using ACM (Amazon Certificate Manager), add them to the load balancers, and redirect all HTTP calls to HTTPS.
## Elastic Kubernetes Service
For Elastic Kubernetes Service (AWS Kubernetes service) use the same load balancer configuration as when running nodes in Kubernetes. Use labels to specify nodes for the load balanced group.
## Manual configurations
Where applicable, we strongly recommend using service discovery. That is, pair your load balancer configuration with something that dynamically detects new nodes and removed failed nodes.
For Nginx, use multiple upstreams (one for each port). Pair each upstream with a separate server block.
```conf title="Upstreams paired with server blocks"
upstream discovery_tcp_30303 {
server 10.0.1.1:30303;
server 10.0.1.2:30303;
}
upstream rpc_tcp_8545 {
server 10.0.1.1:8545;
server 10.0.1.2:8545;
}
server {
listen 30303;
server_name some.host;
location / {
proxy_pass http://discovery_tcp_30303;
}
}
server {
listen 8545;
server_name some.host;
location / {
proxy_pass http://rpc_tcp_8545;
}
}
...
```
For HAProxy, create multiple backend and frontend sets.
```text title="Multiple backend and frontend sets"
frontend discovery-tcp-30303
bind *:30303
acl ...
...
default_backend back-discovery-tcp-30303
frontend rpc-tcp-8545
bind *:8545
acl ...
...
default_backend back-rpc-tcp-8545
backend back-discovery-tcp-30303
balance leastconn
server node-01 10.0.1.1:30303 weight 1 check
server node-02 10.0.1.2:30303 weight 1 check
option ...
timeout server 600s
backend back-rpc-tcp-8545
balance leastconn
server node-01 10.0.1.1:8545 weight 1 check
server node-02 10.0.1.2:8545 weight 1 check
option ....
timeout server 600s
...
```
### HTTPS redirection
To add HTTPS capability, update the above server blocks to include the certificates and specific ciphers. If you require an HTTP to HTTPS redirection, add separate blocks to return a 301 code with the new URI.
---
## Install and update Java
There are many flavors of Java and the Java Virtual Machine (JVM) that work with Besu.
They might impact performance, start time, and more.
Consider the options carefully when installing Java on your host machine.
Currently, [we recommend Java 25](../../get-started/system-requirements.md#java-distribution-and-installation).
## Install Java
Download the version of Java you would like to install.
If you are running Besu outside a virtual environment, like Docker, you must have Java installed on
the host machine.
:::tip
Download [OpenJDK 25](https://jdk.java.net/25/).
:::
You can find platform-specific installation instructions with the download.
The following installation examples use OpenJDK.
### Install Java on Ubuntu
You can install OpenJDK on Ubuntu using the `apt-get` command.
1. Ensure `apt` libraries are installed and up-to-date:
```bash
sudo apt update && sudo apt upgrade -y
```
2. Confirm whether Java is already installed:
```bash
java -version
```
If a version is returned, and you would like to update, see how to [update Java on Ubuntu](#update-java-on-ubuntu).
3. If no version is returned, use `apt` to install the preferred version.
```bash
sudo apt-get install openjdk-25-jdk
```
4. Confirm the installation:
```bash
java -version
```
5. You might need to update your environment to make Java visible to Besu.
Edit the `.bashrc` file in your home directory (or create it if needed) and add the following
lines to the end of the file:
```text title=".bashrc"
export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))
export PATH=$PATH:$JAVA_HOME/bin
```
6. Save your changes and source the file:
```bash
source ~/.bashrc
```
7. Verify that you updated your environment:
```bash
echo $JAVA_HOME
echo $PATH
```
You should see the JDK versions output.
### Install Java on MacOS
You can install OpenJDK on MacOS using Homebrew.
1. With `brew` installed, run:
```bash
brew install openjdk@25
```
You can target another version if you prefer.
2. Confirm the installation:
```bash
java -version
```
The OpenJDK version you install should display.
If this command returns `command not found: java`, check your terminal logs.
Brew might prompt you to create a symlink or update your path variables within the logs in the
terminal output.
If so, run the prompts provided.
## Update Java
### Update Java on Ubuntu
To update Java on Ubuntu, uninstall the current versions and follow the instructions to
[install Java on Ubuntu](#install-java-on-ubuntu) with your target version.
If you started with this guide, you can uninstall Java using the following command:
```bash
sudo apt-get purge openjdk-\*
```
### Update Java on MacOS
You can update Java on MacOS using Homebrew.
1. List your Homebrew packages:
```bash
brew ls
```
2. To update the JDK version (for example, from 21 to 25), uninstall the old version and reinstall
the target version:
```bash
brew uninstall openjdk@21
brew install openjdk@25
```
:::note
If you installed a version of Java not using Homebrew, it is located at
`/Library/Java/JavaVirtualMachines` and can be safely deleted from that directory.
:::
3. To update point versions of Java, run the `upgrade` command:
```bash
brew upgrade openjdk
```
---
## Manage JVM memory
You can manage Java Virtual Machine (JVM) memory usage for Besu by modifying the maximum heap size.
By default, the JVM uses 25% of system RAM. For example, if you have 16 GB RAM installed, the JVM uses 4 GB by default.
On public networks, we recommend setting the maximum heap size to:
- 3 GB on an 8 GB RAM system.
- 5 GB on a 16 GB RAM system.
- 8 GB on a system with at least 24 GB RAM.
:::note
Setting a higher maximum heap size speeds up the sync period but doesn't have much impact after sync. Thus, we recommend setting it to 8 GB only when you have available RAM.
:::
You can set the maximum heap size using the `BESU_OPTS` environment variable and the `-Xmx` option. The following examples set the maximum heap size to 8 GB:
Set the variable for the whole shell before running Besu.
```bash
export BESU_OPTS=-Xmx8g
```
Set the variable only for the specific Besu command.
```bash
BESU_OPTS=-Xmx8g besu [Besu options]
```
```bash
[Service]
...
Environment="BESU_OPTS=-Xmx8g"
ExecStart=besu [Besu options]
...
```
## Manage the heap dump
Heap dump file generation is disabled by default. To enable it, set the `-XX:+HeapDumpOnOutOfMemoryError` Java option.
```bash
BESU_OPTS="-XX:+HeapDumpOnOutOfMemoryError"
```
When heap dump file generation is enabled, and an out-of-memory error occurs, the heap dump file is saved in the Besu runtime directory by default.
The heap dump file might be large and can saturate your drive. It can be up to the size of the allocated memory. For example, for 8 GB heap memory, the file can be up to 8 GB. Specify the directory where you want the dump to be saved using the `-XX:HeapDumpPath` Java option.
```bash
BESU_OPTS="-XX:HeapDumpPath=///"
```
## Default options
To reduce Besu memory footprint, the following G1GC Java options are enabled by default:
```bash
-XX:G1ConcRefinementThreads=2
-XX:G1HeapWastePercent=15
-XX:MaxGCPauseMillis=100
```
To run Besu without the default G1GC options, use the `besu-untuned` start script.
---
## Pass JVM options
To perform tasks such as attaching a debugger or configuring the garbage collector, pass Java Virtual Machine (JVM) options to Besu.
Besu passes the contents of the `BESU_OPTS` environment variable to the JVM. Set standard JVM options in the `BESU_OPTS` variable.
For Bash-based executions, you can set the variable for only the scope of the program execution by setting it before starting Besu.
```bash
BESU_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 \
besu --network=sepolia
```
---
## Configure ports
To enable communication you must expose Besu ports appropriately. The following shows an example port configuration for a Besu node on AWS.

When running Besu from the [Docker image](../../get-started/install/run-docker-image.md), [expose ports](../../get-started/install/run-docker-image.md#expose-ports).
:::info
If your nodes are running in AWS, ensure you have appropriate `SecurityGroups` to allow access to the required ports.
:::
:::tip
Besu supports [UPnP](specify-nat.md) for home or small office environments where a wireless router or modem provides NAT isolation.
:::
## P2P networking
To enable peer discovery, the P2P UDP port must be open for inbound connections.
Specify the P2P port using the [`--p2p-port`](../../reference/options.md#p2p-port) or
[`--p2p-port-ipv6`](../../reference/options.md#p2p-port-ipv6) option.
:::tip Early access feature
To use IPv6 addresses (discovery v5), set the early access option `--Xv5-discovery-enabled` to `true`.
:::
We also recommend opening the P2P TCP port for inbound connections. This is not strictly required because Besu attempts to open outbound TCP connections. But if no nodes on the network are accepting inbound TCP connections, nodes cannot communicate.
To specify the P2P host, set the [`--p2p-host`](../../reference/options.md#p2p-host) or [`--p2p-host-ipv6`](../../reference/options.md#p2p-host-ipv6) option.
By default, peer discovery listens on all available network interfaces.
If the device Besu is running on must bind to a specific network interface, specify the interface using the [`--p2p-interface`](../../reference/options.md#p2p-interface) or
[`--p2p-interface-ipv6`](../../reference/options.md#p2p-interface-ipv6) option.
## JSON-RPC API
To enable access to the [JSON-RPC API](../use-besu-api/json-rpc.md), open the HTTP JSON-RPC and WebSockets JSON-RPC ports to the intended users of the JSON-RPC API on TCP.
Specify the HTTP and WebSockets JSON-RPC ports using the [`--rpc-http-port`](../../reference/options.md#rpc-http-port) and [`--rpc-ws-port`](../../reference/options.md#rpc-ws-port) options. The defaults are `8545` and `8546`.
## Metrics
To enable [Prometheus to access Besu](../monitor/metrics.md), open the metrics port or metrics push port to Prometheus or the Prometheus push gateway on TCP.
Specify the ports for Prometheus and Prometheus push gateway using the [`--metrics-port`](../../reference/options.md#metrics-port) and [`--metrics-push-port`](../../reference/options.md#metrics-push-port) options. The defaults are `9545` and `9001`.
---
## Manage peers
Besu peer-to-peer (P2P) discovery happens periodically based on the number of peers in a
network and the node's [peer limit](#limit-peers).
The frequency of discovery isn't configurable, but you can:
- [Limit remote connections](#limit-remote-connections) in public networks.
- [Allowlist peers by IP subnet](#allowlist-peers) to create a private network of peers across public
networks.
- [Randomly prioritize connections](../../reference/options.md#random-peer-priority-enabled) in
small, stable networks.
:::info
You can use [`admin_addPeer`](../../reference/api/admin.md#admin_addpeer) to attempt a specific
connection, but this isn't P2P discovery.
:::
In private networks, we recommend
[using bootnodes](../../../private-networks/how-to/configure/bootnodes.md) to initially discover peers.
## P2P discovery process
The P2P discovery process requires [ports to be open to UDP and TCP traffic](configure-ports.md#p2p-networking).
If you have a firewall in place, keep those ports open to allow traffic in and out.
If you are running a node at home on your network, ensure that your router has those ports open.
The `discovery` stack uses UDP to keep peer discovery lightweight and quick.
It only allows a node to find peers and connect to them, without any additional overhead.
Once peers have bonded, the data exchange between them is complex and needs a fully featured
protocol to support error checking and retries, so the `devP2P` stack uses TCP.
Both stacks work in parallel: the `discovery` stack adds new peers to the network, and the `devP2P`
stack enables interactions and data flow between them.
In detail, the P2P discovery process is as follows:
1. When Besu starts up it advertises its presence and details (including the enode) using UDP before
establishing a formal connection with any peer (log messages look like `Enode URL enode://....`).
2. Besu attempts to connect to the network's bootnodes (a set of predefined nodes used to help
bootstrap discovery).
3. Once a connection with a bootnode is established using UDP (`ping/pong` handshake messages in the
debug and trace logs), Besu requests a list of neighbors (potential peers) from the bootnode
(`find node` messages in the debug and trace logs).
4. Besu attempts to connect to each peer using TCP, and get status information from them – such
as network details, what the peer believes to be the current chain head, and its list of neighbors.
From this point on any traffic to that peer is only done using TCP.
5. Depending on the [synchronization method](../../concepts/node-sync.md), a common block
(the pivot block) is selected that all connected peers (default of 5) have, and Besu syncs from
that block till it gets to chain head.
Log messages look like `Downloading world state from peers for pivot block .......`.
6. Besu repeats the same process for each peer in step 4, and any new peers that come along
(regardless of client).
The more peers Besu is connected to, the more confident it is of having an accurate view of the network.
## Limit peers
You can limit peers to reduce the bandwidth, CPU time, and disk access Besu uses to manage and respond to peers.
To reduce the maximum number of peers, use the [`--max-peers`](../../reference/options.md#max-peers) option. The default is 25.
## Allowlist peers
You can define specific IP subnets permitted to interact with the node using the [`--net-restrict`](../../reference/options.md#net-restrict) configuration. This restricts access to only those peers whose IP addresses fall within the allowed subnets. This is useful if you maintain a set of nodes and want to restrict which of those can connect to external nodes.
## Limit remote connections
Prevent eclipse attacks when using [`--sync-mode`](../../reference/options.md#sync-mode) and
[`--sync-min-peers`](../../reference/options.md#sync-min-peers) on public networks by enabling
the [remote connection limits](../../reference/options.md#remote-connections-limit-enabled).
In private and permissioned networks with only trusted peers, enabling the remote connection limits is unnecessary and might adversely affect the speed at which nodes can join the network. Limiting remote connections can cause a closed group of peers to form when the number of nodes in the network is slightly higher than [`--max-peers`](../../reference/options.md#max-peers). The nodes in this closed group are all connected to each other and can't accept more connections.
:::tip
You can use [`--random-peer-priority-enabled`](../../reference/options.md#random-peer-priority-enabled) to help prevent closed groups of peers in small, stable networks.
:::
## Monitor peer connections
JSON-RPC API methods to monitor peer connections include:
- [`net_peerCount`](../../reference/api/net.md#net_peercount).
- [`admin_peers`](../../reference/api/admin.md#admin_peers).
- [`debug_metrics`](../../reference/api/debug/state-node.md#debug_metrics).
Each peer entry returned by [`admin_peers`](../../reference/api/admin.md#admin_peers) includes a `protocols` section. Use the information in the `protocols` section to:
- Determine the health of peers. For example, an external process can use [`admin_peers`](../../reference/api/admin.md#admin_peers) and [`admin_removePeer`](../../reference/api/admin.md#admin_removepeer) to disconnect from peers that are stalled at a single difficulty for an extended period of time.
- Monitor node health. For example, if peers report increasing difficulties but the node is stuck at the same block number, the node may be on a different fork to most peers.
- Determine which protocol level peers are communicating with. For example, you can see if `"version": 65` is being used to reduce transaction sharing traffic.
## List node connections
The default logging configuration doesn't list node connection and disconnection messages. To enable listing them, set the [`--logging`](../../reference/options.md#logging) option to `DEBUG`. For more verbosity, set the option to `TRACE`.
The console logs connection and disconnection events when the log level is `DEBUG` or higher. If the message `Successfully accepted connection from ...` displays, connections are getting through the firewalls.
```bash title="Sample log output"
2018-10-16 12:37:35.479-04:00 | nioEventLoopGroup-3-1 | INFO | NettyP2PNetwork | Successfully accepted connection from 0xa979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c
```
## Disable discovery
To disable P2P discovery, set the [`--discovery-enabled`](../../reference/options.md#discovery-enabled) option to `false`.
With discovery disabled, peers can't open connections with the node unless they were previously discovered or manually peered (for example, using [`admin_addPeer`](../../reference/api/admin.md#admin_addpeer)). [Static nodes](static-nodes.md) can also open connections.
## Troubleshoot
If you encounter issues with peering, see the [troubleshoot peering documentation](../../how-to/troubleshoot/peering.md), which helps you identify and resolve common problems that can occur during the peering process.
---
## Specify NAT method
# Specify the NAT method
Use the [`--nat-method`](../../reference/options.md#nat-method) option to specify the NAT method. Options are: [`UPNP`](#upnp), [`DOCKER`](#docker), [`AUTO`](#auto), and [`NONE`](#none).
The [enode](../../concepts/node-keys.md#enode-url) advertised to other nodes during discovery is the external IP address and port. The [`admin_nodeInfo`](../../reference/api/admin.md#admin_nodeinfo) JSON-RPC API method returns the external address and port for the `enode` and `listenAddr` properties.
While Besu is running, the following are not supported:
- IP address changes
- Changing NAT methods. To change the NAT method, restart the node with the [`--nat-method`](../../reference/options.md#nat-method) option set.
## Auto
`AUTO` detects if Besu is running inside a Docker container.
If Besu is running in a Docker container, `AUTO` sets to [`DOCKER`](#docker).
If Besu is not running in a Docker container, `AUTO` sets to [`NONE`](#none).
`AUTO` is the default NAT method.
:::tip
If automatic detection fails, set the IP and ports in [`NONE`](#none) mode.
:::
## UPnP
Specify `UPNP` to quickly allow inbound peer connections without manual router configuration. Use UPnP in home or small office environments where a wireless router or modem provides NAT isolation.
UPnP automatically detects if a node is running in a UPnP environment and provides port forwarding. UPnP might introduce delays during node startup, especially on networks without a UPnP gateway device.
Use `UPNPP2PONLY` if you wish to enable UPnP only for p2p traffic.
:::tip
UPnP support is often disabled by default in networking firmware. If disabled by default, you must explicitly enable UPnP support.
:::
:::info
When the NAT method is set to `UPNP`, the advertised port is the same as the [listening port](../../reference/options.md#p2p-port).
:::
## Docker
Specify `DOCKER` to explicitly specify Besu is running inside a Docker container. If you specify `DOCKER`, you advertise the host IP address not the container IP address.
The host IP address is the advertised host specified in the [`docker run` command](https://docs.docker.com/engine/reference/commandline/run/#add-entries-to-container-hosts-file---add-host). If not specified in the `docker run` command, the advertised host defaults to the values for [`--p2p-host`](../../reference/options.md#p2p-host) and [`--p2p-port`](../../reference/options.md#p2p-port).
## None
Specify `NONE` to explicitly configure the external IP address and ports advertised using:
- [`--p2p-host`](../../reference/options.md#p2p-host) and [`--p2p-port`](../../reference/options.md#p2p-port) for the P2P service.
- [`--rpc-http-host`](../../reference/options.md#rpc-http-host) and [`--rpc-http-port`](../../reference/options.md#rpc-http-port) for the JSON-RPC HTTP service.
The P2P and JSON-RPC HTTP hosts and ports are advertised in the [`net_services`](../../reference/api/net.md#net_services) method.
:::tip
When the NAT method is set to `NONE`, the advertised port is the same as the [listening port](../../reference/options.md#p2p-port).
:::
---
## Configure static nodes
# Static nodes
Static nodes are a configured set of trusted nodes. Static nodes are exempt from [maximum peer](manage-peers.md#limit-peers) and [remote connection](manage-peers.md#limit-remote-connections) limits.
Besu periodically initiates a connection to any unconnected static node. To mitigate low peer count issues in small networks, we recommend using static nodes, or static nodes and bootnodes.
:::tip
Bootnodes and static nodes are both methods for finding peers. Depending on your use case, you can use only bootnodes, only static nodes, or both bootnodes and static nodes.
When connecting to bootnodes, Besu attempts to connect to all bootnodes at once, at startup.
When connecting to static nodes, Besu attempts to reconnect periodically, if the connection fails or is lost.
For example:
* You run multiple nodes on Mainnet, using bootnodes for discovery, but want to ensure your nodes are always connected to each other, using static nodes.
* You run a small network and want your nodes to reconnect if disconnected, using static nodes.
To find peers, configure one or more [bootnodes](../../../private-networks/how-to/configure/bootnodes.md). To configure a specific set of peer connections, use static nodes.
:::
## Configure static nodes
To configure a network of static nodes:
1. List the [enode URLs](../../concepts/node-keys.md#enode-url) of the nodes in the [`static-nodes.json` file](#static-nodesjson-file).
1. Save the `static-nodes.json` file in the data directory (specified by [`--data-path`](../../reference/options.md#data-path)) of each node. Alternatively, you can explicitly specify the static nodes file on the command line using [`--static-nodes-file`](../../reference/options.md#static-nodes-file).
1. Start Besu with discovery disabled using [`--discovery-enabled=false`](../../reference/options.md#discovery-enabled).
To update the list of static peers at run time, use the [`admin_addPeer`](../../reference/api/admin.md#admin_addpeer) and [`admin_removePeer`](../../reference/api/admin.md#admin_removepeer) JSON-RPC API methods.
:::note
Runtime modifications of static nodes are not persisted between runs. The `static-nodes.json` file is not updated by the `admin_addPeer` and `admin_removePeer` methods.
Nodes not in the list of the static nodes are not prevented from connecting. To prevent nodes from connecting, use [Permissioning](../../../private-networks/concepts/permissioning.md).
:::
:::tip
If the added peer does not appear in the peer list (returned by [`admin_peers`](../../reference/api/admin.md#admin_peers)), check the supplied [enode URL](../../concepts/node-keys.md#enode-url) is correct, the node is running, and the node is listening for TCP connections on the endpoint.
:::
### `static-nodes.json` file
The `static-nodes.json` file must be in the data directory (specified by [`--data-path`](../../reference/options.md#data-path)) and contain a JSON array of [enode URLs](../../concepts/node-keys.md#enode-url).
```json title="Example"
[
"enode://cea71cb65a471037e01508cebcc178f176f9d5267bf29507ea1f6431eb6a5dc67d086dc8dc54358a72299dab1161febc5d7af49d1609c69b42b5e54544145d4f@127.0.0.1:30303",
"enode://ca05e940488614402705a6b6836288ea902169ecc67a89e1bd5ef94bc0d1933f20be16bc881ffb4be59f521afa8718fc26eec2b0e90f2cd0f44f99bc8103e60f@127.0.0.1:30304"
]
```
:::note
Each node has a `static-nodes.json` file. We recommend each node in the network has the same `static-nodes.json` file.
:::
---
## Use client libraries
Dapps use client libraries, such as [web3.js](https://github.com/ethereum/web3.js/), [web3j](https://github.com/web3j/web3j), or [ethereumj](https://github.com/ethereum/ethereumj), to forward JSON-RPC requests to Besu. Any client library implementing core Ethereum RPC methods works with Besu.

Use client libraries to create signed transactions.
:::note
[Besu does not support key management inside the client](../send-transactions.md#use-wallets-for-key-management).
:::
---
## Use Hardhat
Developing for Besu using Hardhat is the same as developing for public Ethereum networks using Hardhat. Hardhat
supports Besu with the only difference being Besu does not support private key management.
You can therefore use a wallet provider, or specify your private key in the code.
## Private key management
### Use an HD wallet
To add the wallet provider, update the `hardhat.config.ts` file in the project directory. Replace:
- `` with the JSON-RPC endpoint (IP address and port) of a Besu node.
- `` with the list of words that make up your account's mnemonic.
- ` with your password if used.
- `` with your account's private key.
```js
module.exports = {
// See
// for more about customizing your Hardhat configuration!
networks: {
besuWallet: {
url: "",
accounts: {
mnemonic: "",
path: "m/44'/60'/0'/0",
initialIndex: 0,
count: 1,
passphrase: "",
},
},
},
};
```
### Specify your private key in code
:::danger
Ensure you do not commit private keys to source control like Github, always inject your keys at runtime as environment variables, or
use a vault or similar.
:::
```js
const provider = new ethers.JsonRpcApiProvider();
const wallet = new ethers.Wallet();
// connect the wallet to the provider
const signer = wallet.connect(provider);
```
## Start a Besu node
Start a Besu node with JSON-RPC enabled on the endpoint specified in the Hardhat configuration file.
## Deploy a contract
To deploy a contract onto the Besu network:
```bash
npx hardhat scripts run ./scripts/deploy_my_contract.ts --network besuWallet
```
---
## Import ERA1 files
When running [full sync](../concepts/node-sync.md#full-synchronization), node operators can optionally
nodes to bootstrap pre-merge Ethereum data without relying on peer-to-peer downloads.
ERA1 file import must be explicitly enabled by including the following command line options:
```bash
besu --era1-import-prepipeline-enabled --era1-data-uri= --era1-import-prepipeline-concurrency=1
```
In the command:
- [`--era1-import-prepipeline-enabled`](../reference/options.md#era1-import-prepipeline-enabled)
enables importing pre-merge blocks from ERA1 archive files before full synchronization begins.
This option only applies in `FULL` sync mode.
- [`--era1-data-uri`](../reference/options.md#era1-data-uri) specifies the location of the ERA1
files to be imported. Either a simple filesystem path (`/path/to/files/`), or an HTTP address
(`https://mainnet.era1.nimbus.team`). The default is
`https://mainnet.era1.nimbus.team`.
- [`--era1-import-prepipeline-concurrency`](../reference/options.md#era1-import-prepipeline-concurrency)
sets the number of parallel processes used to import ERA1 files. The default is `1`.
Increase only if you encounter slow file download speeds and your system can handle additional load.
After all ERA1 files are imported, Besu automatically continues with full synchronization to complete
syncing the rest of the chain.
---
## Monitor Besu
Monitoring helps you identify node and network issues. This section describes how to:
- [Collect Besu metrics](metrics.md) with Prometheus and visualize them in Grafana.
- [Understand the CPU and block time patterns](understand-metrics.md) you see while syncing.
- [Configure the log level and format](logging.md) you need for diagnosis.
- Profile a node with [Java Flight Recorder](java-flight-recorder.md) or [Pyroscope](pyroscope.md).
For an overview of monitoring Besu, view [this recording](https://www.youtube.com/watch?v=7BuutRe0I28&feature=youtu.be).
---
## Profile Besu with Java Flight Recorder
[Java Flight Recorder (JFR)](https://docs.oracle.com/javacomponents/jmc-5-4/jfr-runtime-guide/about.htm#JFRUH170) is a monitoring tool that collects information about the Java Virtual Machine (JVM) when Besu is running. Use the JFR as a tool to analyze Besu performance.
JFR records to a file that you inspect afterwards. To profile a node continuously instead, and view the results in Grafana, see [Profile with Pyroscope](pyroscope.md).
## Enable Java Flight Recorder
To enable JFR, set `BESU_OPTS` to the JFR tags as follows:
```bash
export BESU_OPTS=-XX:StartFlightRecording=disk=true,delay=15s,dumponexit=true,\
filename=/tmp/recording.jfr,maxsize=1024m,maxage=1d,\
settings=profile,path-to-gc-roots=true
```
:::tip
When recording, cleanly exiting Besu results in better data. If not possible to cleanly exit, the file may be missing some information not flushed to disk.
:::
Inspect the file written to `/tmp/recording.jfr` with tools such as [Mission Control](https://docs.oracle.com/javacomponents/jmc-5-5/jmc-user-guide/intro.htm#JMCCI109).
:::danger
If providing the output file to [ConsenSys Quorum support](https://consensys.net/quorum/support/), be aware that while JFR files don't contain secrets such as private keys, some details about the user configuration can be inferred from the JFR output.
:::
---
## Configure logging
# Use logging
Besu uses [Log4j 2](https://logging.apache.org/log4j/2.x/) for logging and provides two methods to configure logging behavior:
- [Basic](#basic-logging) - Changes the log level.
- [Advanced](#advanced-logging) - Configures the output and format of the logs.
[Besu Developer Quickstart](https://github.com/Consensys/besu-dev-quickstart) provides an example implementation using Grafana Alloy, Loki, and Grafana for log management.
## Basic logging
Use the [`--logging`](../../reference/options.md#logging) command line option to specify logging verbosity. The [`--logging`](../../reference/options.md#logging) option changes the volume of events displayed in the log. Valid log levels are `OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`, `ALL`. The default level is `INFO`.
For most use cases, the basic method provides enough configurability.
:::tip
Use the [`admin_changeLogLevel`](../../reference/api/admin.md#admin_changeloglevel) API method to change the log level while Besu is running.
:::
## Advanced logging
You can provide your own logging configuration using the standard Log4j 2 configuration mechanisms. For example, the following Log4j 2 configuration is the same as the [default configuration] except for the exclusion of logging of stack traces for exceptions:
```xml title="debug.xml"
INFO
```
To use your custom configuration, set the environment variable `LOG4J_CONFIGURATION_FILE` to the location of your configuration file.
If you have more specific requirements, you can create your own [Log4j 2 configuration](https://logging.apache.org/log4j/2.x/manual/configuration.html).
For Bash-based executions, you can set the variable for only the scope of the program execution by setting it before starting Besu.
To set the debug logging and start Besu connected to the Sepolia testnet:
```bash
LOG4J_CONFIGURATION_FILE=./debug.xml besu --network=sepolia
```
### Log invalid transactions
You can log information about invalid transactions that have been removed from the transaction pool.
Use the log marker `INVALID_TX_REMOVED` and the following fields to format the log line as required:
- `txhash` - The hash of the transaction.
- `txlog` - The human-readable log of the transaction.
- `reason` - The reason the transaction is invalid.
- `txrlp` - The RLP encoding of the transaction.
For example, the following Log4j 2 configuration enables logging of invalid transactions:
```xml title="debug.xml"
INFO
```
### Log rotation
The [Besu Developer Quickstart](https://github.com/Consensys/besu-dev-quickstart) logging configuration defines a [log rotation to restrict the size of the log files].
[default configuration]: https://github.com/besu-eth/besu/blob/750580dcca349d22d024cc14a8171b2fa74b505a/besu/src/main/resources/log4j2.xml
[log rotation to restrict the size of the log files]: https://github.com/Consensys/besu-dev-quickstart/blob/master/files/common/config/besu/log-config.xml
---
## Use metrics
# Use metrics to monitor node performance
To enable the [Prometheus](https://prometheus.io/) monitoring and alerting service to access Besu metrics, use the [`--metrics-enabled`](../../reference/options.md#metrics-enabled) option. Use [Grafana](https://grafana.com/) to visualize the collected data. See the sample [Besu Full Grafana dashboard](https://grafana.com/grafana/dashboards/16455-besu-full/).
The Besu example networks have [monitoring with Prometheus and Grafana configured].
Use Prometheus to monitor the number of blocks your Besu node is behind the chain head, and to alert you that your node is not keeping up with the chain head.
[This recording](https://www.youtube.com/watch?v=7BuutRe0I28&feature=youtu.be) shows examples of monitoring Besu.
## Install Prometheus
To use Prometheus with Besu, install the [Prometheus main component](https://prometheus.io/download/). On MacOS, install with [Homebrew](https://formulae.brew.sh/formula/prometheus):
```bash
brew install prometheus
```
:::tip
You can also install:
- Exporters that send system metrics to Prometheus to monitor non-Besu-specific items such as disk and CPU usage.
- Other Prometheus components, such as the Alert Manager. Additional configuration is not required for these components because Prometheus handles and analyzes data directly from the feed.
:::
## Set up and run Prometheus with Besu
To configure Prometheus and run with Besu:
1. Configure Prometheus to poll Besu.
For example, add the following YAML fragment to the `scrape_configs` block of the `prometheus.yml` file:
```yml
- job_name: besu
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- localhost:9545
```
```yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
- job_name: besu
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- localhost:9545
```
Prometheus requires 3 MB of space per node per hour for metrics, with a `scrape_interval` of 15 seconds.
2. Start Besu with the [`--metrics-enabled`](../../reference/options.md#metrics-enabled) option.
To start a single node for testing with metrics enabled, run the following command:
```bash
besu --network=dev --rpc-http-cors-origins="all" --rpc-http-enabled --metrics-enabled
```
```bash
besu --network=dev --rpc-http-cors-origins="all" --rpc-http-enabled --metrics-enabled
```
To specify the host and port on which Prometheus accesses Besu, use the
[`--metrics-host`](../../reference/options.md#metrics-host) and
[`--metrics-port`](../../reference/options.md#metrics-port) options.
The default host and port are `127.0.0.1` (`localhost`) and `9545`.
:::danger
To avoid DNS rebinding attacks, if running Prometheus on a different host than your Besu node
(any host other than `localhost`), add the hostname that Prometheus uses to
[`--host-allowlist`](../../reference/options.md#host-allowlist).
For example, if Prometheus is configured to get metrics from `http://besu.local:8008/metrics`,
then `besu.local` must be in `--host-allowlist`.
:::
3. In another terminal, run Prometheus specifying the `prometheus.yml` file:
```bash
prometheus --config.file=prometheus.yml
```
4. View the [Prometheus graphical interface](#view-prometheus-graphical-interface).
:::tip
Use a log ingestion tool, such as Logstash, to parse the logs and alert you to configured anomalies.
:::
## Run Prometheus with Besu in push mode
The [`--metrics-enabled`](../../reference/options.md#metrics-enabled) option enables Prometheus
polling of Besu, but sometimes metrics are hard to poll (for example, when running inside Docker
containers with varying IP addresses).
To enable Besu to push metrics to a [Prometheus push gateway](https://github.com/prometheus/pushgateway),
use the [`--metrics-push-enabled`](../../reference/options.md#metrics-push-enabled) option.
To configure Prometheus and run with Besu pushing to a push gateway:
1. Configure Prometheus to read from a push gateway.
For example, add the following YAML fragment to the `scrape_configs` block of the `prometheus.yml` file:
```yml
- job_name: push-gateway
metrics_path: /metrics
scheme: http
static_configs:
- targets:
- localhost:9091
```
1. Start the push gateway.
You can deploy the push gateway using the Docker image:
```bash
docker pull prom/pushgateway
docker run -d -p 9091:9091 prom/pushgateway
```
1. Start Besu specifying the `--metrics-push-enabled` option and port of the push gateway:
```bash
besu --network=dev --rpc-http-cors-origins="all" --rpc-http-enabled --metrics-push-enabled --metrics-push-port=9091 --metrics-push-host=127.0.0.1
```
```bash
besu --network=dev --rpc-http-cors-origins="all" --rpc-http-enabled --metrics-push-enabled --metrics-push-port=9091 --metrics-push-host=127.0.0.1
```
1. In another terminal, run Prometheus specifying the `prometheus.yml` file:
```bash
prometheus --config.file=prometheus.yml
```
1. View the [Prometheus graphical interface](#view-prometheus-graphical-interface).
## View Prometheus graphical interface
1. Open a Web browser to [`http://localhost:9090`](http://localhost:9090) to view the Prometheus graphical interface.
1. Choose **Graph** from the menu bar and click the **Console** tab below.
1. From the **Insert metric at cursor** drop-down, select a [metric](#view-the-metrics-list) such as `besu_blockchain_difficulty_total` or `ethereum_blockchain_height` and click **Execute**. The values display.
1. Click the **Graph** tab to view the data as a time-based graph. The query string displays below the graph. For example, `{ethereum_blockchain_height{instance="localhost:9545",job="prometheus"}`.
## View the metrics list
Run the following command to view the full list of available metrics:
```bash
curl http://localhost:9545/metrics
```
Update the host and port if you are not using the default values.
Each metric, such as `besu_blockchain_chain_head_gas_limit`, starts with a metric category prefix.
Metrics specific to Besu use the `besu_` prefix, followed by another metric category.
You can enable metric categories using the
[`--metrics-category`](../../reference/options.md#metrics-category) command line option.
[monitoring with Prometheus and Grafana configured]: ../../../private-networks/tutorials/quickstart.md#5-monitor-nodes-with-prometheus-grafana-and-loki
---
## Profile Besu with Pyroscope
[Grafana Pyroscope](https://grafana.com/docs/pyroscope/latest/) continuously profiles a running node and shows which code paths consume CPU, memory, and lock time. Use Pyroscope when [metrics](metrics.md) tell you a node is under load but not which part of Besu is responsible.
The Besu Docker image bundles the [Pyroscope Java agent](https://grafana.com/docs/pyroscope/latest/configure-client/language-sdks/java/) and a default agent configuration file. The agent is inactive until you attach it.
:::note
The Docker image bundles the agent from Besu 25.6.0 onwards. The binary distribution doesn't include it, so use [Java Flight Recorder](java-flight-recorder.md) to profile a node installed from the binary distribution.
:::
## Prerequisites
- A [Pyroscope server](https://grafana.com/docs/pyroscope/latest/get-started/) your Besu container can reach.
- A Grafana instance with a [Pyroscope data source](https://grafana.com/docs/grafana/latest/datasources/grafana-pyroscope/) to view the profiles.
## Enable the agent
Attach the bundled agent using [`BESU_OPTS`](../configure-java/pass-jvm-options.md), and set `PYROSCOPE_SERVER_ADDRESS` to the address of your Pyroscope server:
```bash
docker run -p 8545:8545 -p 30303:30303 \
-e BESU_OPTS=-javaagent:/opt/besu/pyroscope/pyroscope.jar \
-e PYROSCOPE_SERVER_ADDRESS=http://:4040 \
-e PYROSCOPE_APPLICATION_NAME= \
hyperledger/besu:latest --network=sepolia
```
```yaml
services:
besu:
image: hyperledger/besu:latest
command: --network=sepolia
environment:
BESU_OPTS: -javaagent:/opt/besu/pyroscope/pyroscope.jar
PYROSCOPE_SERVER_ADDRESS: http://pyroscope:4040
PYROSCOPE_APPLICATION_NAME:
ports:
- 8545:8545
- 30303:30303
```
`PYROSCOPE_APPLICATION_NAME` is the name the node appears under in Grafana. Set a distinct value for each node so you can tell profiles apart.
:::tip
If you run Pyroscope in the same Docker network under the hostname `pyroscope`, on the default port `4040`, you can omit `PYROSCOPE_SERVER_ADDRESS`. That address is already the default in the bundled configuration.
:::
## View profiles in Grafana
Select the Pyroscope data source in Grafana, then select your node under **Service** and a profile type such as `process_cpu:cpu`. The flame graph shows the call stacks that consumed the most CPU over the selected time range, and the table lists the same data by symbol.

The root frame sits at the top of the flame graph, and each row below it shows the functions that frame called. A bar's width is the proportion of samples in which that function was on the stack, so wide bars deep in the graph are the hotspots worth investigating.
## Change the agent configuration
The image sets `PYROSCOPE_CONFIGURATION_FILE` to `/etc/besu/pyroscope.properties`, which contains the following defaults:
| Property | Environment variable | Default |
| ------------------------------ | ------------------------------ | ----------------------- |
| `pyroscope.server.address` | `PYROSCOPE_SERVER_ADDRESS` | `http://pyroscope:4040` |
| `pyroscope.application.name` | `PYROSCOPE_APPLICATION_NAME` | `besu` |
| `pyroscope.format` | `PYROSCOPE_FORMAT` | `jfr` |
| `pyroscope.profiling.event` | `PYROSCOPE_PROFILING_EVENT` | `itimer` |
| `pyroscope.profiling.interval` | `PYROSCOPE_PROFILING_INTERVAL` | `10ms` |
| `pyroscope.profiling.alloc` | `PYROSCOPE_PROFILING_ALLOC` | `512k` |
| `pyroscope.profiling.lock` | `PYROSCOPE_PROFILING_LOCK` | `10ms` |
| `pyroscope.upload.interval` | `PYROSCOPE_UPLOAD_INTERVAL` | `15s` |
| `pyroscope.log.level` | `PYROSCOPE_LOG_LEVEL` | `debug` |
Override any property with the matching environment variable, which is the property name in uppercase with underscores instead of dots. For example, `pyroscope.upload.interval` becomes `PYROSCOPE_UPLOAD_INTERVAL`.
The bundled configuration sets the agent log level to `debug`. Set `PYROSCOPE_LOG_LEVEL=info` to reduce how much the agent logs.
To replace the configuration wholesale, mount your own properties file over `/etc/besu/pyroscope.properties`, or point `PYROSCOPE_CONFIGURATION_FILE` at a different path. Don't use quotes in the properties file.
For the full set of agent options, including authentication for hosted Pyroscope, see the [Pyroscope Java SDK documentation](https://grafana.com/docs/pyroscope/latest/configure-client/language-sdks/java/).
---
## Understand metrics
When running Besu on Ethereum Mainnet using [snap sync](../../concepts/node-sync.md#snap-synchronization), you might notice graphical patterns that stand out in different metrics charts. These patterns are related to the [CPU usage](#cpu-usage) and [block time](#block-time) of the Besu sync process.
## CPU usage
The following screenshot from [monitoring Besu with Prometheus and Grafana] shows patterns related to CPU usage.

The CPU pattern is a "staircase" pattern, where each step represents one of the Besu running stages.
### 1. Blocks import and world state download
Step 1 highlights blocks import and world state download, two tasks executed in parallel in Besu. Besu manages these two tasks with two different pipelines.
This step is CPU-bound.[^1] The two pipeline stages run on multiple threads.
As displayed in the following screenshot (for a VM with 8 CPUs) the CPU load average is about 7.5 and sometimes exceeds 10 (a 100% load for the 8 CPUs is 8). This means there's more work to be done than what the CPUs can handle.

### 2. World state healing
Step 2, world state healing, starts just after the world state download in step 1 is complete. The peak in system CPU is related to the high rate of input and output (IO) required during this step. IO usage is around 61% during healing, and it's only 39% during the remaining sync.

### 3. Blocks import
After steps 1 and 2, world state is downloaded and healed, and block import continues.
The visible drop in CPU shows that Besu finished the world state nodes download.
The block import step is long because Besu can't parallelize block import -- it must validate each parent block before importing a child.
:::note
The Besu team is currently working on other algorithm and implementations to make this block import faster.
:::
### 4. Blocks full import
In step 4, Besu executes all transactions of each block. This is when Besu updates the world state after the healing step.
The quantity of imported blocks in this step depends on the speed of the sync. This number indicates the cumulated blocks quantity behind head since the last healing step.
This step consumes less CPU than the previous steps because the sequential part -- executing transactions on the EVM -- must be single-threaded, reducing the concurrent work at the CPU level.
### 5. Blocks production and propagation
Once Besu is completely synced, it propagates blocks and executes the transactions inside each block. Step 5, block production and propagation, shows a reduction in CPU consumption due to the idle time while waiting for the new block and the sequential nature of executing transactions on the EVM.
## Block time
Block time measures the duration of getting new blocks in Besu. Block time is closely related to [CPU usage](#cpu-usage).
The following screenshot shows patterns related to block time as available in the [Besu Grafana full dashboard](https://grafana.com/grafana/dashboards/16455-besu-full/).

The block time pattern is also a "staircase" pattern.
### 1. Block import time
Step 1, block import time, is the duration of importing a block.
Import includes:
- Data retrieval over the network.
- Headers, body, and receipt validation.
- Persisting the block in the database.
Block import takes between a few and tens of milliseconds.
### 2. Block full import time
Step 2, block full import time, is the duration of importing a block (step 1) and executing all its transactions.
Block full import takes between 1 and 2 seconds per block, depending on the number and complexity of the transactions.
### 3. Block network time
Step 3, block network time, is the duration of propagating a block over the network and executing all its transactions.
Block network takes between 13 and 16 seconds.
[monitoring Besu with Prometheus and Grafana]: ../../../private-networks/tutorials/quickstart.md#5-monitor-nodes-with-prometheus-grafana-and-loki
[^1]: A CPU-bound task means that the time required to execute the task is determined only by the CPU speed.
---
## Prune pre-merge history
Node operators using [Snap sync](../concepts/node-sync.md#snap-synchronization) can significantly reduce
disk usage by removing [pre-merge](https://ethereum.org/en/roadmap/merge/) Proof of Work (PoW)
block data from the local database.
Besu can prune all pre-merge block bodies and associated transaction receipts, leaving only headers and
the genesis block.
:::warning
Besu does not currently provide a way to import pre-merge block data after pruning.
If you need to restore the full pre-merge history, you can revert to the former Snap sync behaviour and download
all blocks from peers by setting
[`--snapsync-synchronizer-pre-checkpoint-headers-only-enabled=false`](../reference/options.md#snapsync-synchronizer-pre-checkpoint-headers-only-enabled).
:::
Besu provides multiple options to prune the historical blockchain data:
- [Offline pruning](#offline-pruning) to prune data on a stopped Besu instance.
- [Online pruning](#online-pruning) to prune data on a running Besu instance.
- [Sync Besu](#sync-without-pre-merge-blocks) using Snap sync, which by default prunes the historical
blockchain data.
## Offline pruning
The fastest option for pruning pre-merge blocks is to perform an offline prune. It won't prune as much data as a full resync.
1. Ensure your Besu instance has stopped, and run the following command:
```bash
besu --data-path=/path/to/your/database storage prune-pre-merge-blocks
```
The command [`prune-pre-merge-blocks`](../reference/subcommands.md#prune-pre-merge-blocks)
prunes the database using the default options.
On completion, you'll receive the `Pruning pre-merge blocks and transaction receipts completed` log message.
It should only take a few minutes to complete but has been known to take up to two hours on occasion.
1. Add the following RocksDB garbage collection options and restart Besu to help free up space:
- `--Xplugin-rocksdb-blockchain-blob-garbage-collection-enabled`
- `--Xplugin-rocksdb-blob-garbage-collection-age-cutoff=0.5`: The fraction of file age that makes a blob file eligible for garbage collection; `0.5` means only the oldest 50% of files are eligible.
- `--Xplugin-rocksdb-blob-garbage-collection-force-threshold=0.1`: The fraction of garbage within an eligible blob file required to trigger compaction; `0.1` triggers garbage collection when at least 10% of an eligible file's content is garbage.
:::info
In testing, we saw the space increased by up to 200GB before the space was finally reclaimed.
We suggest waiting 24-48 hours for all the space to be reclaimed.
:::
1. (Optional) Remove the RocksDB options and restart Besu. This will disable garbage collection which isn't necessary after pruning has reclaimed all the space.
## Online pruning
:::caution Deprecated
Online pruning using `--history-expiry-prune` is deprecated in Besu version 26.1.0 and will be removed in a future release.
Use [offline pruning](#offline-pruning) or [sync without pre-merge blocks](#sync-without-pre-merge-blocks) instead.
:::
Online pruning allows you to prune the pre-merge blocks on a running Besu instance. It has the least
downtime but may impact normal operations for lower spec users. Add the [`--history-expiry-prune`](../reference/options.md#history-expiry-prune) option and restart your Besu node.
:::note
The early access option `--Xpre-merge-pruning-quantity` can be used to specify how many blocks to prune
for each new block added to the chain. For example, `--Xpre-merge-pruning-quantity=10`.
During testing on a 4 CPU machine, we only noticed an impact to Besu when this was tuned to `1000`
:::
The Besu logs will print the progress in the logs, and you'll see the `Done pruning pre-merge blocks.` message
when complete.
## Sync without pre-merge blocks
This option has the most downtime but reclaims the most disk space.
Delete your database and by default, syncing a Besu node using [`SNAP` sync (`--sync-mode=SNAP`)](../reference/options.md#sync-mode)
will prune pre-merge blocks and only retain their headers.
If you're a solo staker, consider using [RocketPool's rescue node](https://rescuenode.com/docs/about)
to minimize downtime.
---
## Create and send transactions
You can send signed transactions using the [`eth_sendRawTransaction`](../reference/api/eth/submit.md#eth_sendrawtransaction)
JSON-RPC API method.
Signed transactions can be simple value transfers, contract creation, or contract invocation. Set the
maximum transaction fee for transactions using the [`--rpc-tx-feecap`](../reference/options.md#rpc-tx-feecap) CLI option.
[Use client libraries](develop/client-libraries.md) to create and send a signed raw transaction to
transfer Ether and create a smart contract.
To accept signed transactions from remote connections, set the [API listening host](use-besu-api/index.md#service-hosts)
to `0.0.0.0`. Setting the listening host to `0.0.0.0` exposes the API service connection on your node to
any remote connection. In a production environment, ensure you are using a firewall to avoid exposing
your node to the internet.
:::danger Private keys
Don't use the accounts from the examples on Mainnet or any public network except for testing. The private keys are displayed which means the accounts are not secure.
All accounts and private keys in the examples are from the `dev.json` genesis file in the [`/besu/config/src/main/resources`](https://github.com/besu-eth/besu/tree/master/config/src/main/resources) directory.
In production environments avoid exposing your private keys by creating signed transactions offline, or use [Web3Signer](https://docs.web3signer.consensys.net/) to isolate your private keys and sign transactions with [`eth_sendTransaction`](https://docs.web3signer.consensys.net/reference/api/json-rpc#eth_sendtransaction).
:::
## `eth_call` vs. `eth_sendRawTransaction`
You can interact with contracts using [`eth_call`](../reference/api/eth/execute.md#eth_call) or [`eth_sendRawTransaction`](../reference/api/eth/submit.md#eth_sendrawtransaction). The table below compares the characteristics of both calls.
| `eth_call` | `eth_sendRawTransaction` |
| --- | --- |
| Read-only | Write |
| Invokes contract function locally | Broadcasts to the network |
| Does not change state of blockchain | Updates the blockchain (for example, transfers ether between accounts) |
| Does not consume gas | Requires gas |
| Synchronous | Asynchronous |
| Returns the value of a contract function available immediately | Returns transaction hash only. A block might not include all possible transactions (for example, if the gas price is too low). |
## Override state values
Use methods that accept the [state override object](../reference/api/eth/execute.md#eth_call) to override an account with temporary state values before
executing a call. State overrides allow you to make temporary state changes without affecting the actual blockchain state, and provide the following benefits:
- Minimize the amount of contract code that must be deployed onchain. Code that returns internal
state or performs predefined validations can be kept offchain and supplied to the node on demand.
- Extend and invoke custom methods on deployed contracts for analysis and debugging without
reconstructing the entire state in a sandbox, allowing selective state or code overrides
to observe execution changes.
The following methods support the [state override object](../reference/api/eth/execute.md#eth_call):
- [`eth_call`](../reference/api/eth/execute.md#eth_call)
- [`eth_estimateGas`](../reference/api/eth/execute.md#eth_estimategas)
- [`eth_simulateV1`](../reference/api/eth/execute.md#eth_simulatev1)
- [`debug_traceCall`](../reference/api/debug/trace.md#debug_tracecall) (via the `stateOverrides` options wrapper)
## Use wallets for key management
Besu doesn't support key management inside the client. Use:
- [Web3Signer](https://docs.web3signer.consensys.net/) with Besu to provide access to your key store and sign transactions.
- Third-party tools (for example, [MetaMask](https://metamask.io/) and [web3j](https://web3j.io/)) for creating accounts.
---
## Use EVM tool
# Use the EVM tool
The Besu EVM tool is a CLI program that executes arbitrary EVM programs and Ethereum State Tests
outside the context of an operating node.
Use the EVM tool for benchmarking and fuzz testing.
## Get the EVM tool
The EVM tool is part of the standard [Besu binary distribution](../../get-started/install/binary-distribution.md).
### Build from source
To build from source, run the following from the root of the Besu repository:
```bash
./gradlew :ethereum:evmTool:installDist
```
An extractable archive files is created in `ethereum/evmtool/build/distributions` and an executable
installation in `ethereum/evmtool/build/install/evmtool`.
Execute the EVM tool:
```bash
ethereum/evmtool/build/install/evmtool/bin/evmtool
```
### Execute with Docker
To run the Besu EVM tool in a container:
```bash
docker run -rm hyperledger/besu-evmtool:develop
```
- Because no data is stored in local directories we recommended using the `-rm` docker option.
The `-rm` option deletes the container at the end of execution.
- If you use an option that requires input from standard in, use the `-i` docker option.
The `-i` option pipes standard input to the EVM tool.
- If you need to reference files we recommend using a docker file binding, such as
`-v ${PWD}:/opt/data`, which maps the current directory to the `/opt/data` directory in the container.
:::note
The `latest` tag is the latest released version of Besu.
The `develop` tag is the current main branch code that will go into a future release version of Besu.
:::
## EVM tool options
The first mode of the EVM tool runs arbitrary EVM bytecode.
Use [command line options](../../reference/evm-tool.md#options) to specify the code and other
contextual information.
For example:
```bash
evmtool --code=5B600080808060045AFA50600056
```
The EVM tool also has [subcommands](../../reference/evm-tool.md#subcommands) used for testing code bases.
These subcommands are not meant for typical user interactions.
---
## Troubleshoot peering
Many factors can affect the ability of your node to find and maintain peers. Your network router, machine environment, and node configuration are all important. If you have peering issues, start by [configuring your ports](../connect/configure-ports.md) and [managing peers](../connect/manage-peers.md).
## Peering FAQ
### "Why can’t I find enough peers to sync?"
One or more of the following may be the cause:
- Your hardware doesn't have enough CPU, disk IOPS, or bandwidth to handle all the peers.
- Your ports aren't open in your firewall and/or router.
- Your node is sending large numbers of DNS requests. See [issue #4375](https://github.com/besu-eth/besu/issues/4375).
- Your node is experiencing the normal behavior of peers connecting and disconnecting. This is especially normal soon after you start your node.
You can try the following to find more peers:
- Set [`p2p-host`](../../reference/options.md#p2p-host) to your external IP address to allow inbound connections.
- Restart Besu. This can take a while to build up again.
- Set `-Xdns-enabled` to `true` (only for private networks).
- Delete the node key (which is autogenerated in your data directory). Deleting the node key might help find more peers for two reasons:
1. Your node (identified by the address associated with this key) has been put onto other peers' bad peer lists for some reason.
2. Peer discovery is influenced by the value of the node key. This is related to the node "distance" in the [discovery algorithm](https://github.com/ethereum/devp2p/wiki/Discovery-Overview#kademlia).
You can read the [Prysm EL and CL peering documentation](https://www.offchainlabs.com/prysm/docs/manage-connections/p2p-host-ip/) for more information.
### "What network or router/modem settings should I check?"
Check the following settings:
- Your machine and router's specified DNS should support TCP. You can check your DNS online for TCP support. Google and Cloudflare, 8.8.8.8 and 1.1.1.1, support TCP over port 853. Other DNS might as well.
- The appropriate ports should be open on your router, or your router should have UPNP enabled. See the next FAQ for more information on router settings.
- If you use [Docker](https://docs.docker.com/network/network-tutorial-host/) or virtualization, the container should be able to create outbound connections on the host machine.
### "Which URLs should I check?"
Check that the [enode URLs](../../concepts/node-keys.md#enode-url) specified for [bootnodes](../../../private-networks/how-to/configure/bootnodes.md) or [static nodes](../connect/static-nodes.md) match the enode URLs displayed when starting the remote nodes.
### "How do I open/forward my ports?"
If you’re behind NAT, you probably need to set up port forwarding in your router. You might also need to configure your firewall. Forward and open `30303` (if using the default p2p port) for both UDP and TCP. If your router supports UPNP, you can set [`--nat-method`](../../reference/options.md#nat-method) to [`UPNPP2PONLY`](../connect/specify-nat.md#upnp).
### "How do I test that my ports are open?"
You can use this [open port checker](https://www.yougetsignal.com/tools/open-ports/).
### "What's the ideal number of peers for Besu?"
The default maximum is 25. Increasing the number of peers increases the bandwidth, CPU, and disk access Besu uses to respond to peers. Hardware with low specifications might result in low peer numbers. You'll experience diminishing returns with a larger number of peers (>100).
### "What's the benefit of increasing the number of peers?"
Increasing the number of max peers won't speed up Besu syncing, because the bottleneck during sync is disk IO and CPU.
Note that Besu's peers are only used for the initial sync and transaction gossip, neither of which affects attestation performance. The beacon node connectivity controls how quickly you receive blocks and how attestations are published. Increasing Besu's peer count increases the load on your node, which may hurt attestations.
## Metrics
Capture [metrics](../monitor/index.md) to gain insights into peering behavior over time.
To [enable Prometheus to access Besu](../monitor/metrics.md), open the metrics port or metrics push port to Prometheus or the Prometheus push gateway on TCP.
Specify the ports for Prometheus and Prometheus push gateway using the [`--metrics-port`](../../reference/options.md#metrics-port) and [`--metrics-push-port`](../../reference/options.md#metrics-push-port) options. The defaults are `9545` and `9001`.
---
## Troubleshoot performance
Your hardware, machine environment, and node configuration can affect your node's ability to serve
requests and perform [validator duties](../../concepts/proof-of-stake/index.md), including
[attestation performance](../../concepts/proof-of-stake/attestations.md).
If you notice high resource usage when [monitoring your node](../monitor/index.md), you can
try the following suggestions:
* Disable swapping.
Besu is an I/O intensive application, especially during sync, enabling swapping hurts Besu's performance.
You can disable swap at the OS level.
[This article](https://www.tecmint.com/disable-swap-partition/) provides information on how to
disable swap (and caveats).
* Use a high performance SSD disk with NVMe, since Besu's performance bottleneck is often slow disk I/O.
* Configure memory and RAM:
* If you have RAM constraints, use [OpenJ9](../../get-started/system-requirements.md) if you're
running on `x86_64` Linux architecture to reduce memory usage.
* Review and change your [Java heap size](../configure-java/manage-memory.md) if necessary.
5GB is an appropriate limit.
Higher values may improve sync time, but can be reduced after completing sync.
* Ensure Besu is using [jemalloc](../../get-started/install/binary-distribution.md).
* If you have 32GB RAM or more, set the `Xplugin-rocksdb-high-spec-enabled` configuration option
to `true`.
Don't use this on RAM machines with 16GB RAM or less if you're running a consensus client on the
same hardware.
* If you're running on ARM64, make sure the glibc version is greater than 2.29.
If not, Besu uses a Java implementation instead of the native one for some precompiled contracts,
which results in lower performance.
* On Ubuntu, run `ldd --version`.
See [the methods for other environments](https://dev.to/0xbf/how-to-get-glibc-version-c-lang-26he).
* Pay attention to what processes are running on the same machine/VM as Besu.
Java applications, with default settings, are designed to run alone on the machine.
You can run your consensus client on the same machine, but this adds overhead on Besu, and vice
versa (on CPU cache misses, CPU scheduler latency, IO, etc.).
You should continue to monitor your node after following these suggestions.
---
## Trace transactions
To get detailed information about transaction processing, use the [`TRACE` API](../../reference/api/trace.md). Enable the `TRACE` API using the [`--rpc-http-api`](../../reference/options.md#rpc-http-api) or [`--rpc-ws-api`](../../reference/options.md#rpc-ws-api) command line options.
The `TRACE` API has two sets of trace calls, [ad-hoc tracing APIs](#ad-hoc-tracing-apis) and [transaction-trace filtering APIs](#transaction-trace-filtering-apis).
## Ad-hoc tracing APIs
These APIs allow you to use the [`trace`](../../reference/api/trace.md#trace),
[`vmTrace`](../../reference/api/trace.md#vmtrace), or
[`stateDiff`](../../reference/api/trace.md#statediff) diagnostic options when tracing calls or transactions.
When using [Bonsai Tries](../../concepts/data-storage-formats.md#bonsai-tries) with the ad-hoc
tracing APIs, the requested block or transaction must be within the number of
[blocks retained](../../reference/options.md#bonsai-historical-block-limit) (by default, 512
from the head of the chain).
The ad-hoc tracing APIs are:
- [`trace_call`](../../reference/api/trace.md#trace_call)
- [`trace_callMany`](../../reference/api/trace.md#trace_callmany)
- [`trace_rawTransaction`](../../reference/api/trace.md#trace_rawtransaction)
- [`trace_replayBlockTransactions`](../../reference/api/trace.md#trace_replayblocktransactions)
## Transaction-trace filtering APIs
These APIs allow you to filter and search by specific information such as the block, address, or transaction. These APIs only use the [`trace`](../../reference/api/trace.md#trace) type.
To use the transaction-trace filtering APIs, your node must be an
[archive node](../../concepts/node-sync.md#archive-nodes), or the requested block
or transaction must be within the number of
[blocks retained](../../reference/options.md#bonsai-historical-block-limit) when using
[Bonsai Tries](../../concepts/data-storage-formats.md#bonsai-tries) (by default, 512 from the head
of the chain).
The transaction-trace filtering APIs are:
- [`trace_block`](../../reference/api/trace.md#trace_block)
- [`trace_filter`](../../reference/api/trace.md#trace_filter)
- [`trace_get`](../../reference/api/trace.md#trace_get)
- [`trace_transaction`](../../reference/api/trace.md#trace_transaction)
## Dumping traces to file
For large blocks or when you prefer file output over a JSON response, use the debug API methods:
- [`debug_standardTraceBlockToFile`](../../reference/api/debug/trace.md#debug_standardtraceblocktofile)
- [`debug_standardTraceBadBlockToFile`](../../reference/api/debug/trace.md#debug_standardtracebadblocktofile)
Enable or disable trace fields (txHash, stack, memory, storage, and opcodes) via the optional options parameter on both methods. For example, set `disableStack`, `disableMemory`, and/or `disableStorage` to reduce output size or focus on specific data.
:::note
Trace files are written under the node data directory in the `traces` subdirectory; the data directory is set by the [`--data-path`](../../reference/options.md#data-path) option.
:::
---
## Upgrade Besu
# Upgrade your Besu node
This page provides instructions for upgrading your Besu node on:
- [Linux](#upgrade-on-linux)
- [Docker](#upgrade-on-docker)
- [Kubernetes](#upgrade-on-kubernetes)
- [Ansible](#upgrade-on-ansible)
When upgrading your node, we recommend:
- Checking the [Besu release notes](https://github.com/besu-eth/besu/releases) for breaking changes.
- Preserving your node's data and configuration.
- Storing your configuration under version control.
## Upgrade on Linux
1. Run the following script to automatically download the latest Linux release, extract it, and clean up:
```bash
RELEASE_URL="https://api.github.com/repos/besu-eth/besu/releases/latest"
TAG=$(curl -s $RELEASE_URL | jq -r .tag_name)
BINARIES_URL="https://github.com/besu-eth/besu/releases/download/$TAG/besu-$TAG.tar.gz"
echo Downloading URL: $BINARIES_URL
cd $HOME
wget -O besu.tar.gz $BINARIES_URL
tar -xzvf besu.tar.gz -C $HOME
rm besu.tar.gz
sudo mv $HOME/besu-${TAG} besu
```
2. Stop your Besu node:
```bash
sudo systemctl stop execution
```
3. Remove old binaries, install new binaries, and restart Besu:
```bash
sudo rm -rf /usr/local/bin/besu
sudo mv $HOME/besu /usr/local/bin/besu
sudo systemctl start execution
```
:::tip note
Thank you to
[CoinCashew](https://www.coincashew.com/coins/overview-eth/guide-or-how-to-setup-a-validator-on-eth2-mainnet/part-ii-maintenance/updating-execution-client#besu)
for this upgrade script.
You can also see CoinCashew for instructions on upgrading Besu by building from source.
:::
## Upgrade on Docker
1. Update your Docker image:
```bash
docker pull hyperledger/besu:latest
```
2. Stop the current container:
```bash
docker stop besu-node
```
3. Start a new container with the updated image:
```bash
docker run -d \
--name besu-node \
-v besu-data:/opt/besu/data \
-v besu-config:/etc/besu \
hyperledger/besu:latest
```
Here is an example `docker-compose.yml` file:
```yaml
version: '3.8'
services:
besu:
image: hyperledger/besu:latest
volumes:
- besu-data:/opt/besu/data
- besu-config:/etc/besu
ports:
- "8545:8545"
- "30303:30303"
volumes:
besu-data:
besu-config:
```
## Upgrade on Kubernetes
1. Update your deployment manifest with a new image version:
```yaml
spec:
containers:
- name: besu
image: hyperledger/besu:new-version
```
2. Apply the update:
```bash
kubectl apply -f besu-deployment.yaml
```
Here is an example PVC configuration:
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: besu-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Ti
```
## Upgrade on Ansible
You can use the [Ansible role on Galaxy](https://galaxy.ansible.com/ui/standalone/roles/consensys/hyperledger_besu/)
directly or customize it to suit your needs.
Upgrade your Besu node by running the play with the new version.
For more information, select **Documentation** on the [Ansible Galaxy Besu page](https://galaxy.ansible.com/ui/standalone/roles/consensys/hyperledger_besu/).
The playbook:
1. Stops Besu.
2. Downloads the updated version.
3. Applies any new configuration.
4. Starts Besu.
## Verify post-upgrade
### RPC methods
If you have [JSON-RPC HTTP enabled](../reference/options.md#rpc-http-enabled),
you can use the following commands to verify that you've successfully upgraded your Besu node.
Call [`eth_syncing`](../reference/api/eth/client.md#eth_syncing) to check the node synchronization status:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' http://127.0.0.1:8545 -H "Content-Type: application/json"
```
Call [`web3_clientVersion`](../reference/api/web3.md#web3_clientversion) to check the current client version:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}' http://127.0.0.1:8545 -H "Content-Type: application/json"
```
Call [`net_peerCount`](../reference/api/net.md#net_peercount) to verify peer connections:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}' http://127.0.0.1:8545 -H "Content-Type: application/json"
```
### Logs
You can also check Besu's logs to verify the version and whether Besu is in sync.
For example, the startup logs look like the following:
```bash
{"@timestamp":"2025-01-17T07:23:03,791","level":"INFO","thread":"main","class":"Besu","message":"Starting Besu","throwable":""}
{"@timestamp":"2025-01-17T07:23:04,558","level":"INFO","thread":"main","class":"Besu","message":"Connecting to 0 static nodes.","throwable":""}
{"@timestamp":"2025-01-17T07:23:04,643","level":"INFO","thread":"main","class":"Besu","message":"
####################################################################################################
# #
# Besu version 25.1.0 #
#
... #
```
### Metrics
If you have [metrics enabled](../reference/options.md#metrics-enabled), you can verify the version by checking the
`process_release` metric in [Prometheus](monitor/metrics.md), or on the command line:
```bash
curl -s localhost:9545/metrics | grep process_release
```
For example, the response looks like the following:
```bash
process_release{version="besu/v25.10/linux-x86_64/openjdk-java-21"} 1.0
```
## Find peers on restarting
Nodes store known peers in the peer table.
The peer table is not persisted to disk.
When a node restarts, the node connects to the specified bootnodes and discovers other nodes through the peer discovery process.
The node continues collecting data from where it left off before the restart (assuming there was no data corruption in a failure scenario).
Before the node restarted, connected peers saved the node details in their peer tables.
These peers can reconnect to the restarted node.
The restarted node uses these peers and the bootnodes, to discover more peers.
To ensure that the restarted node successfully rejoins the network, ensure you specify at least one operational bootnode.
## Troubleshoot
#### Sync not progressing
Verify that the node is properly connected to the bootnodes.
Check the node logs to ensure that the connections are being established correctly.
#### Low peer count
Ensure that your network connection is stable and that the required ports for peer discovery and communication are open and correctly forwarded.
#### API unavailable
Check the configuration of your RPC endpoint to ensure it is set up correctly and is accessible.
Verify that the API service is running and the correct ports are being used.
#### Data corruption
If you encounter data corruption, restore the node data from a known good backup.
Ensure regular backups are in place to avoid data loss.
:::note
As a last resort, you can delete the database to resync the node.
This can solve corruption issues, but it might suffer significant downtime depending on the size of the network.
:::
---
## Access logs using JSON-RPC
# Access logs using the Besu API
Subscribe to events, such as logs, using either [RPC Pub/Sub over WebSockets](rpc-pubsub.md) or filters over HTTP.
Access logs using the following Besu API methods:
- [`eth_getFilterChanges`](../../reference/api/eth/filter.md#eth_getfilterchanges)
- [`eth_getFilterLogs`](../../reference/api/eth/filter.md#eth_getfilterlogs)
- [`eth_getLogs`](../../reference/api/eth/filter.md#eth_getlogs)
Use [`eth_newFilter`](../../reference/api/eth/filter.md#eth_newfilter) to create the filter before using [`eth_getFilterChanges`](../../reference/api/eth/filter.md#eth_getfilterchanges) and [`eth_getFilterLogs`](../../reference/api/eth/filter.md#eth_getfilterlogs)).
:::note
The following examples use the sample contract included in [events and logs](../../concepts/events-and-logs.md).
:::
## Create a filter
Create a filter using [`eth_newFilter`](../../reference/api/eth/filter.md#eth_newfilter).
If the [example contract](../../concepts/events-and-logs.md) was deployed to 0x42699a7612a82f1d9c36148af9c77354759b210b, the following request for `eth_newFilter` creates a filter to log when `valueIndexed` is set to 5:
```json
{
"jsonrpc": "2.0",
"method": "eth_newFilter",
"params": [
{
"fromBlock": "earliest",
"toBlock": "latest",
"address": "0x42699a7612a82f1d9c36148af9c77354759b210b",
"topics": [
["0xd3610b1c54575b7f4f0dc03d210b8ac55624ae007679b7a928a4f25a709331a8"],
["0x0000000000000000000000000000000000000000000000000000000000000005"]
]
}
],
"id": 1
}
```
[`eth_newFilter`](../../reference/api/eth/filter.md#eth_newfilter) returns a filter ID hash (for example, `0x1ddf0c00989044e9b41cc0ae40272df3`).
### Poll a filter for changes
To poll the filter for changes since the last poll, use [`eth_getFilterChanges`](../../reference/api/eth/filter.md#eth_getfilterchanges) with the filter ID hash returned by [`eth_newFilter`](../../reference/api/eth/filter.md#eth_newfilter).
If the contract had been executed twice since the last poll, with `valueIndexed` set to 1 and 5, [`eth_getFilterChanges`](../../reference/api/eth/filter.md#eth_getfilterchanges) returns only the log where the [topic](../../concepts/events-and-logs.md#event-parameters) for `valueIndexed` is 5:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x21c",
"blockHash": "0xc7e6c9d5b9f522b2c9d2991546be0a8737e587beb6628c056f3c327a44b45132",
"blockTimestamp": "0x55ba4740",
"transactionHash": "0xfd1a40f9fbf89c97b4545ec9db774c85e51dd8a3545f969418a22f9cb79417c5",
"transactionIndex": "0x0",
"address": "0x42699a7612a82f1d9c36148af9c77354759b210b",
"data": "0x0000000000000000000000000000000000000000000000000000000000000005",
"topics": [
"0xd3610b1c54575b7f4f0dc03d210b8ac55624ae007679b7a928a4f25a709331a8",
"0x0000000000000000000000000000000000000000000000000000000000000005"
]
}
]
}
```
### Get all logs for a filter
To get all logs for a filter, use [`eth_getFilterLogs`](../../reference/api/eth/filter.md#eth_getfilterlogs).
If the contract had been executed twice with `valueIndexed` set to 5 since the filter was created using `eth_newFilter`, `eth_getFilterLogs` returns:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x1a7",
"blockHash": "0x4edda22a242ddc7bc51e2b6b11e63cd67be1af7389470cdea9c869768ff75d42",
"blockTimestamp": "0x55ba4662",
"transactionHash": "0x9535bf8830a72ca7d0020df0b547adc4d0ecc4321b7d5b5d6beb1eccee5c0afa",
"transactionIndex": "0x0",
"address": "0x42699a7612a82f1d9c36148af9c77354759b210b",
"data": "0x0000000000000000000000000000000000000000000000000000000000000005",
"topics": [
"0xd3610b1c54575b7f4f0dc03d210b8ac55624ae007679b7a928a4f25a709331a8",
"0x0000000000000000000000000000000000000000000000000000000000000005"
]
},
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x21c",
"blockHash": "0xc7e6c9d5b9f522b2c9d2991546be0a8737e587beb6628c056f3c327a44b45132",
"blockTimestamp": "0x55ba4740",
"transactionHash": "0xfd1a40f9fbf89c97b4545ec9db774c85e51dd8a3545f969418a22f9cb79417c5",
"transactionIndex": "0x0",
"address": "0x42699a7612a82f1d9c36148af9c77354759b210b",
"data": "0x0000000000000000000000000000000000000000000000000000000000000005",
"topics": [
"0xd3610b1c54575b7f4f0dc03d210b8ac55624ae007679b7a928a4f25a709331a8",
"0x0000000000000000000000000000000000000000000000000000000000000005"
]
}
]
}
```
:::tip
You can use [`eth_getLogs`](#get-logs-using-a-filter-options-object) with a filter options object to get all logs matching the filter options instead of using [`eth_newFilter`](../../reference/api/eth/filter.md#eth_newfilter) followed by [`eth_getFilterLogs`](../../reference/api/eth/filter.md#eth_getfilterlogs).
:::
## Uninstall a filter
When a filter is no longer required, use [`eth_uninstallFilter`](../../reference/api/eth/filter.md#eth_uninstallfilter) to remove the filter.
## Get logs using a filter options object
To get all logs for a filter options object, use [`eth_getLogs`](../../reference/api/eth/filter.md#eth_getlogs).
The following request for `eth_getLogs` returns all the logs where the example contract has been deployed to `0x42699a7612a82f1d9c36148af9c77354759b210b` and executed with `valueIndexed` set to 5.
```json
{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [
{
"fromBlock": "earliest",
"toBlock": "latest",
"address": "0x42699a7612a82f1d9c36148af9c77354759b210b",
"topics": [
["0xd3610b1c54575b7f4f0dc03d210b8ac55624ae007679b7a928a4f25a709331a8"],
["0x0000000000000000000000000000000000000000000000000000000000000005"]
]
}
],
"id": 1
}
```
The above example returns the same result as calling [eth_newFilter](#create-a-filter) followed by [eth_getFilterLogs](#get-all-logs-for-a-filter).
---
## Authenticate over JSON-RPC requests
# Authenticate and authorize JSON-RPC
Authentication identifies a user, and authorization verifies user access to requested JSON-RPC methods. Besu verifies users using
[JSON Web Tokens (JWT)](https://jwt.io/introduction/).
Besu supports two mutually exclusive authentication methods:
- [Username and password](#username-and-password-authentication)
- [JWT public key](#jwt-public-key-authentication).
Besu creates JWT internally with [username and password authentication](#username-and-password-authentication), and externally with [JWT public key authentication](#jwt-public-key-authentication).
:::info
Using JSON-RPC authentication and authorization with [MetaMask](https://metamask.io/) is not supported.
:::
:::caution
To prevent interception of authentication credentials and authenticated tokens, make authenticated requests over HTTPS. We recommend running production deployments behind a network layer that provides SSL termination. Besu does not provide a HTTPS connection natively.
:::
## Username and password authentication
Enable authentication from the command line. Supply the credentials file and send a request to the `/login` endpoint using the username and password. The `/login` endpoint creates a JWT for making permitted JSON-RPC requests.
Using [public key authentication](#jwt-public-key-authentication) disables the `/login` endpoint.
### 1. Create the credentials file
The `toml` credentials file defines user details and the JSON-RPC methods they can access.
```toml title="auth.toml"
[Users.username1]
password = "$2a$10$l3GA7K8g6rJ/Yv.YFSygCuI9byngpEzxgWS9qEg5emYDZomQW7fGC"
permissions=["net:*","eth:blockNumber"]
[Users.username2]
password = "$2b$10$6sHt1J0MVUGIoNKvJiK33uaZzUwNmMmJlaVLkIwinkPiS1UBnAnF2"
permissions=["net:version","admin:*"]
```
Each user requiring JSON-RPC access the configuration file lists the:
- Username. `Users.` is mandatory and followed by the username. That is, replace `` in `[Users.]` with the username.
- Hash of the user password. Use the [`password hash`](../../reference/subcommands.md#password) subcommand to generate the hash.
- [JSON-RPC permissions](#json-rpc-permissions).
```bash
besu password hash --password=MyPassword
```
```text
$2a$10$L3Xb5G/AJOsEK5SuOn9uzOhpCCfuVWTajc5hwWerY6N5xBM/xlrMK
```
### 2. Enable authentication
Enable authentication for the JSON-RPC API using the
[`--rpc-http-authentication-enabled`](../../reference/options.md#rpc-http-authentication-enabled)
or [`--rpc-ws-authentication-enabled`](../../reference/options.md#rpc-ws-authentication-enabled) option.
Specify the [credentials file](#1-create-the-credentials-file) using the
[`--rpc-http-authentication-credentials-file`](../../reference/options.md#rpc-http-authentication-credentials-file)
or [`--rpc-ws-authentication-credentials-file`](../../reference/options.md#rpc-ws-authentication-credentials-file) option.
:::note
With authentication enabled, you can specify methods that don't require authentication using
[`--rpc-http-api-methods-no-auth`](../../reference/options.md#rpc-http-api-methods-no-auth) or
[`--rpc-ws-api-methods-no-auth`](../../reference/options.md#rpc-ws-api-methods-no-auth).
:::
### 3. Generate an authentication token
To generate an authentication token, make a request to the `/login` endpoint with your username and password. Specify the HTTP port or the WS port to generate a token to authenticate over HTTP or WS respectively. HTTP and WS requires a different token.
```bash
curl -X POST --data '{"username":"username1","password":"MyPassword"}' /login
```
```bash
curl -X POST --data '{"username":"username1","password":"MyPassword"}' http://localhost:8545/login
```
```bash
curl -X POST --data '{"username":"username1","password":"MyPassword"}' /login
```
```bash
curl -X POST --data '{"username":"username1","password":"MyPassword"}' http://localhost:8546/login
```
```json
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJwZXJtaXNzaW9ucyI6WyIqOioiXSwidXNlcm5hbWUiOiJ1c2VyMiIsImlhdCI6MTU1MDQ2MDYwNCwiZXhwIjoxNTUwNDYwOTA0fQ.l2Ycqzl_AyvReXBeUSayOlOMS_E8-DCuz3q0Db0DKD7mqyl6q-giWoEtfdWzUEvZbRRi2_ecKO3N6JkXq7zMKQAJbVAEzobfbaaXWcQEpHOjtnK4_Yz-UPyKiXtu7HGdcdl5Tfx3dKoksbqkBl3U3vFWxzmFnuu3dAISfVJYUNA"
}
```
Authentication tokens expire five minutes after generation. If you require access after the token expires, you need to generate a new token.
## JWT public key authentication
Enable authentication from the command line and supply the external JWT provider's public key.
:::caution
JWT public authentication disables the Besu `/login` endpoint, meaning [username and password authentication](#username-and-password-authentication) will not work.
:::
### 1. Generate a private and public key pair
The private and accompanying public key files must be in `.pem` format.
The [key algorithm](https://datatracker.ietf.org/doc/html/rfc7518#section-3.1) can be:
- RSA with private key length of at least 2048 bits using algorithm `RS256`, `RS384`, or `RS512`.
- ECDSA private key, using `ES256` (`secp256r1` or `secp256k1`), `ES384`, or `ES512`.
The default value for Besu is `RS256`.
When you use a different key algorithm, you must specify the
[`--rcp-http-authentication-jwt-algorithm`](../../reference/options.md#rpc-http-authentication-jwt-algorithm)
option and/or the
[`--rcp-ws-authentication-jwt-algorithm`](../../reference/options.md#rpc-ws-authentication-jwt-algorithm)
option depending on your needs.
1. Generate the private key:
```bash
openssl genrsa -out privateRSAKey.pem 2048
```
2. Generate the public key:
```bash
openssl rsa -pubout -in privateRSAKey.pem -pubout -out publicRSAKey.pem
```
1. Generate the private key:
```bash
openssl ecparam -name secp256r1 -genkey -out privateECDSAKey.pem
```
2. Generate the public key:
```bash
openssl ec -in privateECDSAKey.pem -pubout -out publicECDSAKey.pem
```
:::danger Private key security
The private key must be kept secret. Never share private keys publicly or on a Web site, even if advertised as secure.
Always keep your private keys safe -- ideally using [hardware](https://connect2id.com/products/nimbus-jose-jwt/examples/pkcs11) or [vault](https://www.vaultproject.io/docs/secrets/identity/identity-token) -- and define a strong security policy and
[best practices](https://auth0.com/docs/secure/tokens/token-best-practices).
Compromised keys can provide attackers access to your node's RPC-API.
:::
### 2. Create the JWT
Create the JWT using a trusted authentication provider[^1] or [library](https://jwt.io/libraries) in your own code.
[^1]: for example [Auth0](https://auth0.com/) or [Keycloak](https://www.keycloak.org/)
See [Java code sample to generate JWT using Vertx](https://github.com/NicolasMassart/java-jwt-sample-generation/) for an example implementation.
:::caution Important
The JWT must use one of the `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, or `ES512` algorithms.
:::
Each payload for the JWT must contain:
- [JSON-RPC permissions](#json-rpc-permissions)
- [`exp` (Expiration Time) claim](https://tools.ietf.org/html/rfc7519#section-4.1.4)
```json
{
"permissions": ["*:*"],
"exp": 1600899999002
}
```

### 3. Enable authentication
Enable authentication for the JSON-RPC API using the
[`--rpc-http-authentication-enabled`](../../reference/options.md#rpc-http-authentication-enabled)
or [`--rpc-ws-authentication-enabled`](../../reference/options.md#rpc-ws-authentication-enabled) option.
Specify the JWT provider's public key file to use with the externally created JWT, using the
[`--rpc-http-authentication-jwt-public-key-file`](../../reference/options.md#rpc-http-authentication-jwt-public-key-file)
or [`--rpc-ws-authentication-jwt-public-key-file`](../../reference/options.md#rpc-ws-authentication-jwt-public-key-file) option.
:::note
With authentication enabled, you can specify methods that don't require authentication using
[`--rpc-http-api-methods-no-auth`](../../reference/options.md#rpc-http-api-methods-no-auth) or
[`--rpc-ws-api-methods-no-auth`](../../reference/options.md#rpc-ws-api-methods-no-auth).
:::
## JSON-RPC permissions
Each user has a list of permissions strings defining the methods they can access. To give access to:
- All API methods, specify `["*:*"]`.
- All API methods in an API group, specify `[":*"]`. For example, `["eth:*"]`.
- Specific API methods, specify `[":"]`. For example, `["admin:peers"]`.
With authentication enabled, to explicitly specify a user cannot access any methods, include the user with an empty permissions list (`[]`). Users with an empty permissions list and users not included in the credentials file cannot access any JSON-RPC methods.
## Use an authentication token to make requests
Specify the authentication token as a `Bearer` token in the JSON-RPC request header.
```bash
curl -X POST -H 'Authorization: Bearer ' -d '{"jsonrpc":"2.0","method":"","params":[],"id":1}' -H "Content-Type: application/json"
```
```bash
curl -X POST -H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJwZXJtaXNzaW9ucyI6WyIqOioiXSwidXNlcm5hbWUiOiJ1c2VyMiIsImlhdCI6MTU1MDQ2MTQxNiwiZXhwIjoxNTUwNDYxNzE2fQ.WQ1mqpqzRLHaoL8gOSEZPvnRs_qf6j__7A3Sg8vf9RKvWdNTww_vRJF1gjcVy-FFh96AchVnQyXVx0aNUz9O0txt8VN3jqABVWbGMfSk2T_CFdSw5aDjuriCsves9BQpP70Vhj-tseaudg-XU5hCokX0tChbAqd9fB2138zYm5M' -d '{"jsonrpc":"2.0","method":"net_listening","params":[],"id":1}' http://localhost:8545/ -H "Content-Type: application/json"
```
---
## Use GraphQL over HTTP
GraphQL can reduce the overhead needed for common queries.
For example, instead of querying each receipt in a block, GraphQL can get the same result with a
single query for the entire block.
The [Besu GraphQL schema] describes the GraphQL implementation for Ethereum.
Enable the GraphQL service using [command line options](index.md#enable-api-access).
:::note
GraphQL is not supported over WebSocket.
:::
Access the GraphQL endpoint at `http://:/graphql`.
Configure `` and `` using [`graphql-http-host`](../../reference/options.md#graphql-http-host)
and [`graphql-http-port`](../../reference/options.md#graphql-http-port).
The default endpoint is `http://127.0.0.1:8547/graphql`.
## GraphQL requests with cURL
[Besu JSON-RPC API methods](../../reference/api/index.md) with an equivalent
[GraphQL](graphql.md) query include a GraphQL request and result in the method example.
For example, the following request returns the block number:
```bash
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{block{number}}"}' http://localhost:8547/graphql
```
```json
{
"data" : {
"block" : {
"number" : "0x281"
}
}
}
```
The following request returns the gas price:
```bash
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{gasPrice}"}' http://localhost:8547/graphql
```
```json
{
"data" : {
"gasPrice" : "0x0"
}
}
```
The following [`syncing`](../../reference/api/eth/client.md#eth_syncing) request returns data about the
synchronization status:
```bash
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{syncing{startingBlock currentBlock highestBlock}}"}' http://localhost:8547/graphql
```
```json
{
"data" : {
"syncing" : {
"startingBlock" : 665,
"currentBlock" : 3190,
"highestBlock" : 26395
}
}
}
```
:::info note
In some cases, for example, when your node is fully synced, the syncing request returns a `null` response:
```json
{
"data" : {
"syncing" : null
}
}
```
:::
## GraphQL requests with GraphiQL app
The third-party tool, [GraphiQL](https://github.com/skevy/graphiql-app), provides a tabbed interface
for editing and testing GraphQL queries and mutations.
GraphiQL also provides access to the [Besu GraphQL schema] from within the app.

## Pending
`transactionCount` and `transactions` supports the Pending query.
:::info
Besu does not execute pending transactions so results from `account`, `call`, and `estimateGas` for
Pending do not reflect pending transactions.
:::
```bash
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{pending {transactionCount}}"}' http://localhost:8547/graphql
```
```json
{
"data": {
"pending": {
"transactionCount": 2
}
}
}
```
```bash
curl -X POST -H "Content-Type: application/json" --data '{ "query": "{pending {transactions{hash}}}"}' http://localhost:8547/graphql
```
```json
{
"data": {
"pending": {
"transactions": [
{
"hash": "0xbb3ab8e2113a4afdde9753782cb0680408c0d5b982572dda117a4c72fafbf3fa"
},
{
"hash": "0xf6bd6b1bccf765024bd482a71c6855428e2903895982090ab5dbb0feda717af6"
}
]
}
}
}
```
[Besu GraphQL schema]: https://github.com/besu-eth/besu/blob/750580dcca349d22d024cc14a8171b2fa74b505a/ethereum/api/src/main/resources/schema.graphqls
---
## Access the Besu API
Access the [Besu API](../../reference/api/index.md) using:
- [JSON-RPC over HTTP, WebSocket, or IPC](json-rpc.md)
- [RPC Pub/Sub over WebSockets and IPC](rpc-pubsub.md)
- [GraphQL over HTTP](graphql.md).
:::note
HTTP and WebSocket responses are compact JSON by default. You can use [`--json-pretty-print-enabled`](../../reference/options.md#json-pretty-print-enabled) to pretty-print the output.
:::
The following sections provide information about JSON-RPC, RPC Pub/Sub, and GraphQL.
## Enable API access
To enable API access, use the [`--rpc-http-enabled`](../../reference/options.md#rpc-http-enabled), [`--rpc-ws-enabled`](../../reference/options.md#rpc-ws-enabled), [`--graphql-http-enabled`](../../reference/options.md#graphql-http-enabled), or the early access `--Xrpc-ipc-enabled` options.
:::caution
`--Xrpc-ipc-enabled` is an early access option.
:::
## Service hosts
To specify the host the API service listens on, use the [`--rpc-http-host`](../../reference/options.md#rpc-http-host), [`--rpc-ws-host`](../../reference/options.md#rpc-ws-host), and [`--graphql-http-host`](../../reference/options.md#graphql-http-host) options. The default host is `127.0.0.1`.
To allow remote connections, set the host to `0.0.0.0`.
:::caution
Setting the host to `0.0.0.0` exposes the API service connection on your node to any remote connection. In a production environment, ensure you use a firewall to avoid exposing your node to the internet.
:::
## Service ports
To specify the port the API service listens on, use the [`--rpc-http-port`](../../reference/options.md#rpc-http-port), [`--rpc-ws-port`](../../reference/options.md#rpc-ws-port), and [`--graphql-http-port`](../../reference/options.md#graphql-http-port) options.
The default ports are:
- 8545 for JSON-RPC over HTTP.
- 8546 for JSON-RPC over WebSocket.
- 8547 for GraphQL over HTTP.
Ports must be [exposed appropriately](../connect/configure-ports.md).
## Socket path
To specify the socket path for the IPC socket, use the `--Xrpc-ipc-path` option. The default path is `besu.ipc` in the Besu data directory.
:::caution
`--Xrpc-ipc-path` is an early access option.
:::
## Host allowlist
To prevent DNS rebinding attacks, Besu checks incoming HTTP request host headers, WebSocket connections, and GraphQL requests. Besu accepts requests only when hostnames specified using the [`--host-allowlist`](../../reference/options.md#host-allowlist) option matches the request host headers. By default, Besu accepts requests and connections from `localhost` and `127.0.0.1`.
:::info
This isn't a permissioning feature. To restrict access to the API, we recommend using the [Besu authentication mechanism](authenticate.md) with username and password authentication or JWT public key authentication.
:::
If your application publishes RPC ports, specify the hostnames when starting Besu.
```bash
besu --host-allowlist=example.com
```
Specify `*` for `--host-allowlist` to effectively disable host protection.
:::caution
Specifying `*` for `--host-allowlist` is not recommended for production code.
:::
## Not supported by Besu
### Account management
Account management relies on private key management in the client, which is not supported by Besu.
To send signed transactions, use [`eth_sendRawTransaction`](../../reference/api/eth/submit.md#eth_sendrawtransaction). `eth_sendTransaction` is not implemented.
For [account management](../send-transactions.md#use-wallets-for-key-management), use third-party wallets.
### Protocols
Besu does not support the Whisper and Swarm protocols.
---
## Use JSON-RPC over HTTP, WS, and IPC
# Use JSON-RPC over HTTP, WebSocket, and IPC
JSON-RPC APIs allow you to interact with your node. JSON-RPC endpoints are not enabled by default.
:::caution
You should secure access to your node's JSON-RPC endpoints. Users with access to your node via JSON-RPC can make calls directly to your node, causing your node to consume resources.
:::
To enable JSON-RPC over HTTP or WebSocket, use the [`--rpc-http-enabled`](../../reference/options.md#rpc-http-enabled) and [`--rpc-ws-enabled`](../../reference/options.md#rpc-ws-enabled) options.
To enable JSON-RPC over an [IPC socket](index.md#socket-path), use the `--Xrpc-ipc-enabled` option.
:::caution
`--Xrpc-ipc-enabled` is an early access option.
:::
Subscription methods (`eth_subscribe`, `eth_unsubscribe`) are supported over IPC as well as WebSocket, but not over HTTP. See [RPC Pub/Sub over WebSockets and IPC](rpc-pubsub.md).
## Geth console
The geth console is a REPL (Read, Evaluate, & Print Loop) JavaScript console. Use JSON-RPC APIs supported by geth and Besu directly in the console.
To use the geth console with Besu:
1. Start Besu with the [`--rpc-http-enabled`](../../reference/options.md#rpc-http-enabled) or `--Xrpc-ipc-enabled`
option.
2. Specify which APIs to enable using the [`--rpc-http-api`](../../reference/options.md#rpc-http-api) or
`--Xrpc-ipc-api` option.
3. Start the geth console specifying the JSON-RPC endpoint:
```bash
geth attach http://localhost:8545
```
```bash
geth attach /path/to/besu.ipc
```
4. Use the geth console to call [JSON-RPC API methods](../../reference/api/index.md) that geth and Besu share.
```bash
eth.syncing
```
## JSON-RPC authentication
Besu disables [Authentication](authenticate.md) by default.
## HTTP and WebSocket requests
### HTTP
To make RPC requests over HTTP, you can use [`curl`](https://curl.haxx.se/download.html).
```bash
curl -X POST --data '{"jsonrpc":"2.0","id":,"method":"","params":[]}' -H "Content-Type: application/json"
```
```bash
curl -X POST --data '{"jsonrpc":"2.0","id":"1","method":"eth_blockNumber","params":[]}' http://127.0.0.1:8555/ -H "Content-Type: application/json"
```
```json
{
"jsonrpc": "2.0",
"id": "1",
"result": "0x60e"
}
```
You can use `curl` to make multiple RPC requests (batch requests) over HTTP at the same time. Send the requests as an array, and receive an array of responses. The default number of allowed requests in a RPC batch request is `1024`. Use the [`--rpc-http-max-batch-size`](../../reference/options.md#rpc-http-max-batch-size) command line option to update the default value.
```bash
curl -X POST --data '[{"jsonrpc":"2.0","id":"1","method":"eth_blockNumber","params":[]}, {"jsonrpc":"2.0","id":"2","method":"admin_peers","params":[]}]' http://127.0.0.1:8555/ -H "Content-Type: application/json"
```
```json
[
{
"jsonrpc": "2.0",
"id": "1",
"result": "0x60e"
},
{
"jsonrpc": "2.0",
"id": "2",
"result": []
}
]
```
### WebSocket
To make RPC requests over WebSocket, you can use [`wscat`](https://github.com/websockets/wscat), a Node.js based command-line tool.
First connect to the WebSocket server using `wscat` (you only need to connect once per session):
```bash
wscat -c ws://
```
After you establish a connection, the terminal displays a '>' prompt. Send individual requests as a JSON data package at each prompt.
```bash
{"jsonrpc":"2.0","id":,"method":"","params":[]}
```
```bash
{"jsonrpc":"2.0","id":"1","method":"eth_blockNumber","params":[]}
```
```json
{
"jsonrpc": "2.0",
"id": "1",
"result": "0x23"
}
```
You can use `wscat` to make multiple RPC requests over WebSocket at the same time. Send the requests as an array, and receive an array of responses.
```bash
[{"jsonrpc":"2.0","id":"1","method":"eth_blockNumber","params":[]}, {"jsonrpc":"2.0","id":"2","method":"admin_peers","params":[]}]
```
```json
[
{
"jsonrpc": "2.0",
"id": "1",
"result": "0x23"
},
{
"jsonrpc": "2.0",
"id": "2",
"result": []
}
]
```
:::note
`wscat` does not support headers. [Authentication](authenticate.md) requires you to pass an authentication token in the request header. To use authentication with WebSocket, you need an app that supports headers.
:::
## Readiness and liveness endpoints
Besu provides readiness and liveness endpoints to confirm the Besu node status.
Both return a `200 OK` HTTP status when ready or live, and a `503 Service Unavailable` HTTP status if not ready or live.
### Readiness
By default, the readiness check requires a connected peer and the node to be within two blocks of the best known block. If you have [disabled P2P communication](../../reference/options.md#p2p-enabled), you do not need peers. A live node with P2P disabled is always ready.
Use the query parameters `minPeers` and `maxBlocksBehind` to adjust the number of peers required and the number of blocks tolerance.
```bash
http:///readiness
```
```bash
curl -v 'http://localhost:8545/readiness'
```
```bash
curl -v 'http://localhost:8545/readiness?minPeers=0&maxBlocksBehind=10'
```
```json
{
"status": "DOWN"
}
```
The readiness response object contains the following field:
- `status`: _string_ - readiness status of the node, either `UP` or `DOWN`
### Liveness
The liveness check requires the JSON-RPC server to be up. You can use the endpoint to verify that the node can respond to RPC calls. The `status` in the response will always be `UP`.
```bash
http:///liveness
```
```bash
curl -v 'http://localhost:8545/liveness'
```
```json
{
"status": "UP"
}
```
## API methods enabled by default
Besu enables the `ETH`, `NET`, and `WEB3` API methods by default.
To enable the `ADMIN`, `DEBUG`, `EEA`, `IBFT`, `MINER`, `PERM`, `PLUGINS`, `PRIV`, `TRACE`, and `TXPOOL` API methods, use the [`--rpc-http-api`](../../reference/options.md#rpc-http-api), [`--rpc-ws-api`](../../reference/options.md#rpc-ws-api), or `--Xrpc-ipc-api` options.
:::caution
`--Xrpc-ipc-api` is an early access option.
:::
## Block parameter
When you make requests that might have different results depending on the block accessed, the block
parameter specifies the block.
Methods such as [`eth_getTransactionByBlockNumberAndIndex`](../../reference/api/eth/transaction.md#eth_gettransactionbyblocknumberandindex)
have a block parameter.
The block parameter can have one of the following values:
- `blockNumber` : _quantity_ - The block number, specified in hexadecimal.
`0x0` represents the genesis block.
- `blockHash` : _string_ or _object_ - 32-byte block hash or JSON object specifying the block hash.
If using a JSON object, you can specify `requireCanonical` to indicate whether the block must be a
canonical block.
See [this example](https://github.com/besu-eth/besu/blob/a2dedb0b2c7980cdc35db8eb4c094f2eb0dc7deb/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_getBalance_blockHashObjectCanonical.json).
:::note
Only the following methods support the `blockHash` parameter:
- [`eth_call`](../../reference/api/eth/execute.md#eth_call)
- [`eth_getBalance`](../../reference/api/eth/state.md#eth_getbalance)
- [`eth_getCode`](../../reference/api/eth/state.md#eth_getcode)
- [`eth_getProof`](../../reference/api/eth/state.md#eth_getproof)
- [`eth_getStorageAt`](../../reference/api/eth/state.md#eth_getstorageat)
- [`eth_getStorageValues`](../../reference/api/eth/state.md#eth_getstoragevalues)
- [`eth_getTransactionCount`](../../reference/api/eth/state.md#eth_gettransactioncount)
:::
- `earliest` : _tag_ - The earliest (genesis) block.
- `latest` : _tag_ - The most recent block.
- `pending` : _tag_ - The next anticipated block, except in the following cases:
- For some methods (specified in their parameter description), `pending` returns the
same value as `latest`.
- For [`eth_getTransactionCount`](../../reference/api/eth/state.md#eth_gettransactioncount),
`pending` refers to the most recent block plus pending transactions.
- For [`qbft_getValidatorsByBlockNumber`](../../../private-networks/reference/api/qbft.md#qbft_getvalidatorsbyblocknumber),
`pending` returns a list of validators that will be used to produce the next block.
- `finalized` : _tag_ - The most recent crypto-economically secure block.
It cannot be reorganized outside manual intervention driven by community coordination.
- `safe` : _tag_ - The most recent block that is safe from reorganization under honest majority and
certain synchronicity assumptions.
---
## Use RPC Pub/Sub over WS and IPC
# Use RPC Pub/Sub over WebSockets and IPC
Subscribe to events by using either RPC Pub/Sub over WebSockets or IPC, or [filters over HTTP](access-logs.md).
Use RPC Pub/Sub over WebSockets or IPC to wait for events instead of polling for them. For example, dapps subscribe to logs and receive notifications when a specific event occurs.
Methods specific to RPC Pub/Sub are:
- `eth_subscribe` - create a subscription for specific events.
- `eth_unsubscribe` - cancel a subscription for specific events.
:::info
Unlike other [Besu API methods](../../reference/api/index.md), you cannot call the RPC Pub/Sub methods over HTTP. Use the [`--rpc-ws-enabled`](../../reference/options.md#rpc-ws-enabled) option for WebSockets or the `--Xrpc-ipc-enabled` option for IPC (see [JSON-RPC over IPC](json-rpc.md)) to enable subscription methods.
:::
### Use RPC Pub/Sub
[WebSockets](json-rpc.md#http-and-websocket-requests) and [IPC](json-rpc.md) support the RPC Pub/Sub API.
To create subscriptions, use `eth_subscribe`. Once subscribed, the API publishes notifications using `eth_subscription`.
Subscriptions couple with connections. If a connection is closed, all subscriptions created over the connection are removed.
:::note
Besu limits how many subscriptions can be active at once across all WebSocket connections. Once the limit is reached, `eth_subscribe` returns an error until existing subscriptions end. Use the [`--rpc-ws-max-active-subscriptions`](../../reference/options.md#rpc-ws-max-active-subscriptions) option to change the limit, which is `100000` by default.
:::
### Subscription ID
`eth_subscribe` returns a subscription ID for each subscription created. Notifications include the subscription ID.
For example, to create a synchronizing subscription:
```json
{ "id": 1, "method": "eth_subscribe", "params": ["syncing"] }
```
The result includes the subscription ID of `"0x1"`:
```json
{ "jsonrpc": "2.0", "id": 1, "result": "0x1" }
```
The notifications also include the subscription ID of `"0x1"`:
```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x1",
"result": {
"startingBlock": "0x0",
"currentBlock": "0x50",
"highestBlock": "0x343c19"
}
}
}
```
### Notifications when synchronizing
Subscribing to some events (for example, logs) can cause a flood of notifications while the node is synchronizing.
## Subscribe
Use `eth_subscribe` to create subscriptions for the following event types:
- [New headers](#new-headers)
- [Logs](#logs)
- [Pending transactions](#pending-transactions)
- [Dropped transactions](#dropped-transactions)
- [Transaction receipts](#transaction-receipts)
- [Synchronizing](#synchronizing)
### New headers
To notify you about each block added to the blockchain, use the `newHeads` parameter with `eth_subscribe`.
If a chain reorganization occurs, the subscription publishes notifications for blocks in the new chain. This means the subscription can publish notifications for multiple blocks at the same height on the blockchain.
The new headers notification returns [block objects](../../reference/api/eth/block.md#eth_getblockbyhash). The second parameter is optional. If specified, the notifications include whole [transaction objects](../../reference/api/eth/transaction.md#eth_gettransactionbyhash), Otherwise, the notifications include transaction hashes.
To subscribe to new header notifications:
```json
{
"id": 1,
"method": "eth_subscribe",
"params": ["newHeads", { "includeTransactions": true }]
}
```
Example result:
```json
{ "jsonrpc": "2.0", "id": 2, "result": "0x1" }
```
Example notification without the `{"includeTransactions": true}` parameter included:
```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x1",
"result": {
"number": "0x40c22",
"hash": "0x16af2ee1672203c7ac13ff280822008be0f38e1e5bdc675760015ae3192c0e3a",
"parentHash": "0x1fcf5dadfaf2ab4d985eb05d40eaa23605b0db25d736610c4b87173bfe438f91",
"nonce": "0x0000000000000000",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"logsBloom": "0x00008000000000080000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000040000000000000000000000000000000000000000001000000000000000000000040000000000000000000000000000000000000400000000010000000000000000100000000000020000000000000000000000000000000000010000000000000000000000000000000000000000000",
"transactionsRoot": "0x5b2e3c1a49352f1ca9fb5dfe74b7ffbbb6d70e23a12693444e26058d8a8e6296",
"stateRoot": "0xbe8d3bc58bd982421a3ea8b66753404502df0f464ae78a17661d157c406dd38b",
"receiptsRoot": "0x81b175ec1f4d44fbbd6ba08f1bd3950663b307b7cb35751c067b535cc0b58f12",
"miner": "0x0000000000000000000000000000000000000000",
"difficulty": "0x1",
"totalDifficulty": "0x7c16e",
"extraData": "0xd783010600846765746887676f312e372e33856c696e757800000000000000002160f780bb1f61eda045c67cdb1297ba37d8349df8035533cb0cf82a7e45f23f3d72bbec125a9f499b3eb110b7d1918d466cb2ede90b38296cfe2aaf452c513f00",
"size": "0x3a1",
"gasLimit": "0x47e7c4",
"gasUsed": "0x11ac3a",
"timestamp": "0x592afc24",
"uncles": [],
"transactions": [
"0x419c69d21b14e2e8f911def22bb6d0156c876c0e1c61067de836713043364d6c",
"0x70a5b2cb2cee6e0b199232a1757fc2a9d6053a4691a7afef8508fd88aeeec703",
"0x4b3035f1d32339fe1a4f88147dc197a0fe5bbd63d3b9dec2dad96a3b46e4fddd"
]
}
}
}
```
Example notification with the `{"includeTransactions": true}` parameter included:
```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params":{
"subscription":"0x1",
"result": {
....
"transactions":[
{
"blockHash":"0xa30ee4d7c271ae5150aec494131c5f1f34089c7aa8fb58bd8bb916a55275bb90",
"blockNumber":"0x63",
"from":"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas":"0x5208",
"gasPrice":"0x3b9aca00",
"hash":"0x11f66c3e96a92e3c14c1c33ad77381221bf8b58a887b4fed6aee456fc6f39b24",
"input":"0x",
"nonce":"0x1",
"to":"0x627306090abab3a6e1400e9345bc60c78a8bef57",
"transactionIndex":"0x0",
"value":"0x56bc75e2d63100000",
"v":"0xfe8",
"r":"0x4b57d179c74885ef5f9326fd000665ea7fae44095c1e2016a2817fc671beb8cc",
"s":"0x7ec060b115746dda392777df07ae1feacc0b83b3646f0a3de9a5fc3615af9bb8",
}
],
},
}
}
```
### Logs
To notify you about [logs](../../concepts/events-and-logs.md) included in new blocks, use the `logs` parameter with `eth_subscribe`. Specify a filter object to receive notifications only for logs matching your filter.
Logs subscriptions have a filter object parameter with the following fields:
- `address` - (optional) Either an address or an array of addresses. Returns only logs created from these addresses.
- `topics` - (optional) Returns only logs that match the [specified topics](../../concepts/events-and-logs.md#topic-filters).
- `fromBlock` - (optional) The earliest block from which to return logs.
- `toBlock` - (optional) The last block from which to return logs.
If a chain reorganization occurs, the subscription publishes notifications for logs from the old chain with the `removed` property in the [log object](../../reference/api/eth/filter.md#eth_getlogs) set to `true`. This means the subscription can publish notifications for multiple logs for the same transaction.
The logs subscription returns [log objects](../../reference/api/eth/filter.md#eth_getlogs).
```json
{
"id": 1,
"method": "eth_subscribe",
"params": ["logs", {}]
}
```
```json
{
"id": 1,
"method": "eth_subscribe",
"params": [
"logs",
{
"address": "0x8320fe7702b96808f7bbc0d4a888ed1468216cfd",
"topics": [
"0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"
],
"fromBlock": "0x0",
"toBlock": "latest"
}
]
}
```
```json
{ "jsonrpc": "2.0", "id": 1, "result": "0x2" }
```
```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x2",
"result": {
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x2174",
"blockHash": "0x7bc83837534aa13df55ff7db77784b1d1ba666d4c4bdd223cae9fe09c7c37eba",
"transactionHash": "0x942179373e413824c6bc7045e92295aff91b679215446549b4aeb084da46495b",
"transactionIndex": "0x0",
"address": "0x9b8397f1b0fecd3a1a40cdd5e8221fa461898517",
"data": "0x",
"topics": [
"0x199cd93e851e4c78c437891155e2112093f8f15394aa89dab09e38d6ca072787",
"0x0000000000000000000000000000000000000000000000000000000000000005"
]
}
}
}
```
### Pending transactions
To notify you about pending transactions added to the transaction pool for the node, use the `newPendingTransactions` parameter with `eth_subscribe`.
The pending transactions subscription returns the transaction hashes or transaction details of the pending transactions. If the `includeTransactions` parameter is not included, the default is transaction hashes only.
If a chain reorganization occurs, Besu resubmits transactions for inclusion in the new canonical chain. This means the subscription can publish notifications for the same pending transaction more than once.
To subscribe to pending transaction notifications and receive transaction hashes only:
```json
{
"id": 1,
"method": "eth_subscribe",
"params": ["newPendingTransactions", { "includeTransactions": false }]
}
```
Example result:
```json
{ "jsonrpc": "2.0", "id": 1, "result": "0x1" }
```
Example notification:
```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x1",
"result": "0x5705bc8bf875ff03e98adb98489428835892dc6ba6a6b139fee1becbc26db0b8"
}
}
```
To subscribe to pending transaction notifications and receive transaction details:
```json
{
"id": 1,
"method": "eth_subscribe",
"params": ["newPendingTransactions", { "includeTransactions": true }]
}
```
Example result:
```json
{ "jsonrpc": "2.0", "id": 1, "result": "0x2" }
```
Example notification:
```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x2",
"result": {
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0x5208",
"gasPrice": "0x2540be400",
"hash": "0x7a4185f40ee93cb27eb132f301d0a5414c1f871051f166fc8804c376aab3ffec",
"input": "0x",
"nonce": "0x13",
"to": "0x9d8f8572f345e1ae53db1dfa4a7fce49b467bd7f",
"value": "0x8ac7230489e80000",
"v": "0xfe7",
"r": "0xdd9013c67469d2fe79afdc61777c55bdced33c90fa6f9b83d8f9b7e445085123",
"s": "0x45823a1ab22ae9c83876ea435dc5ecc4fe3a83c1bfbc340a5f57df2f5a474fa5"
}
}
}
```
### Dropped transactions
To notify you about transactions dropped from the transaction pool for the node, use the `droppedPendingTransactions` parameter with `eth_subscribe`.
The dropped transactions subscription returns the transaction hashes of the dropped transactions.
Dropped transactions can be re-added to the transaction pool from a variety of sources. For example, receiving a previously dropped transaction from a peer. As a result, it's possible to receive multiple dropped transaction notifications for the same transaction.
To subscribe to dropped transaction notifications:
```json
{ "id": 1, "method": "eth_subscribe", "params": ["droppedPendingTransactions"] }
```
Example result:
```json
{ "jsonrpc": "2.0", "id": 1, "result": "0x1" }
```
Example notification:
```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x1",
"result": "0xf57d6a90a7fb30880cfbdf6b432b487d0e94a3b55b34dc4b45e3b0b237ecab4c"
}
}
```
### Transaction receipts
To notify you about transaction receipts for each new block, use the
`transactionReceipts` parameter with `eth_subscribe`.
The transaction receipts subscription returns an array of
[transaction receipt objects](../../reference/api/eth/transaction.md#eth_gettransactionreceipt).
The receipt format matches the `eth_getTransactionReceipt` response.
If a chain reorganization occurs, the subscription publishes receipts for blocks
added to the new canonical chain.
To subscribe to all transaction receipt notifications:
```json
{
"id": 1,
"method": "eth_subscribe",
"params": ["transactionReceipts"]
}
```
Example result:
```json
{ "jsonrpc": "2.0", "id": 1, "result": "0x3" }
```
Example notification:
```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x3",
"result": [
{
"blockHash": "0x19514ce955c65e4dd2cd41f435a75a46a08535b8fc16bc660f8092b32590b182",
"blockNumber": "0x6f55",
"contractAddress": null,
"cumulativeGasUsed": "0x18c36",
"effectiveGasPrice": "0x9502f907",
"from": "0x22896bfc68814bfd855b1a167255ee497006e730",
"gasUsed": "0x18c36",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0xfd584430cafa2f451b4e2ebcf3986a21fff04350",
"transactionHash": "0x4a481e4649da999d92db0585c36cba94c18a33747e95dc235330e6c737c6f975",
"transactionIndex": "0x0",
"type": "0x0"
}
]
}
}
```
To subscribe to receipt notifications for specific transactions, specify the
optional `transactionHashes` filter.
You can specify up to 200 transaction hashes.
```json
{
"id": 1,
"method": "eth_subscribe",
"params": [
"transactionReceipts",
{
"transactionHashes": [
"0x0000000000000000000000000000000000000000000000000000000000000001",
"0x0000000000000000000000000000000000000000000000000000000000000002"
]
}
]
}
```
When no receipts match the filter, Besu doesn't send a notification for that
block.
When one or more receipts match the filter, the notification `result` contains
the matching receipts.
### Synchronizing
To notify you about synchronization progress, use the `syncing` parameter with `eth_subscribe`.
When behind the chain head, the synchronizing subscription returns an object indicating the synchronization progress. When fully synchronized, returns `false`.
To subscribe to synchronizing notifications:
```json
{ "id": 1, "method": "eth_subscribe", "params": ["syncing"] }
```
Example result:
```json
{ "jsonrpc": "2.0", "id": 1, "result": "0x4" }
```
Example notification while synchronizing:
```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x4",
"result": {
"startingBlock": "0x0",
"currentBlock": "0x3e80",
"highestBlock": "0x67b93c"
}
}
}
```
Example notification when synchronized with chain head:
```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0x4",
"result": false
}
}
```
## Unsubscribe
To cancel a subscription, use the [subscription ID](#subscription-id) with `eth_unsubscribe`. Only the connection that created a subscription can unsubscribe from it.
`eth_unsubscribe` returns `true` if subscription successfully unsubscribed; otherwise, returns an error.
To unsubscribe from a subscription with subscription ID of `0x1`:
```json
{ "id": 1, "method": "eth_unsubscribe", "params": ["0x1"] }
```
Example result:
```json
{ "jsonrpc": "2.0", "id": 1, "result": true }
```
---
## Use the Engine API
[Consensus and execution clients](../concepts/node-clients.md#execution-and-consensus-clients) communicate with each other using the [Engine API](../reference/engine-api.md). These API methods are a separate subsection of the [JSON-RPC API](../how-to/use-besu-api/index.md).
## Configure the Engine API
The Engine API is enabled by default even if no consensus client configuration exists. You can configure the Engine API to:
- Specify the [service ports](#service-ports).
- Specify the [host allowlist](#host-allowlist).
```bash title="Example Engine API configuration"
besu --engine-rpc-port=8551 --engine-host-allowlist=localhost,127.0.0.1 --engine-jwt-secret=jwt.hex
```
### Service ports
To specify the port the Engine API service listens on for HTTP and WebSocket, use the [`--engine-rpc-port`](../reference/options.md#engine-rpc-port) option. The default is `8551`. This option is useful when you have another execution engine running on port 8551, in which case you can specify Besu to use another port, for example, `--engine-rpc-port 8552`.
### Host allowlist
To prevent DNS rebinding attacks, Besu checks incoming HTTP request host headers, WebSocket connections, and GraphQL requests. Besu accepts requests only when hostnames specified using the [`--engine-host-allowlist`](../reference/options.md#engine-host-allowlist) option matches the request host headers. By default, Besu accepts requests and connections from `localhost` and `127.0.0.1`.
:::info
This isn't a permissioning feature. To restrict access to the Engine API, we recommend using [authentication](#authentication).
:::
If your application publishes RPC ports, specify the hostnames when starting Besu.
Specify `*` for `--engine-host-allowlist` to effectively disable host protection.
:::caution
We don't recommend specifying `*` for `--engine-host-allowlist` in production.
:::
## Authentication
By default, [authentication](../how-to/use-besu-api/authenticate.md) for the Engine API is enabled. To disable, set the [`--engine-jwt-disabled`](../reference/options.md#engine-jwt-disabled) option to `true`.
:::caution
Don't disable JWT authentication in production environments.
Disable only for testing purposes.
:::
Set the [JWT secret](use-besu-api/authenticate.md#jwt-public-key-authentication) by using the [`--engine-jwt-secret`](../reference/options.md#engine-jwt-secret) option.
## Send a payload using the Engine API
### 1. Prepare a payload
Prepare to send a payload using [`engine_forkchoiceUpdatedV1`](https://ethereum.github.io/execution-apis/api/methods/engine_forkchoiceUpdatedV1).
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"engine_forkchoiceUpdatedV1","params":[{"headBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", "safeBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a", "finalizedBlockHash": "0x0000000000000000000000000000000000000000000000000000000000000000"},{"timestamp": "0x5","prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000","suggestedFeeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"}],"id":67}' http://127.0.0.1:8550
```
```json
{
"jsonrpc": "2.0",
"id": 67,
"result": {
"payloadStatus": {
"status": "VALID",
"latestValidHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a",
"validationError": null
},
"payloadId": "0x0000000021f32cc1"
}
}
```
### 2. Get the payload
Get the payload using [`engine_getPayloadV1`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadV1)
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"engine_getPayloadV1","params":["0x1"],"id":1}' http://127.0.0.1:8550
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"parentHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"blockNumber": "0x1",
"gasLimit": "0x1c9c380",
"gasUsed": "0x0",
"timestamp": "0x5",
"extraData": "0x",
"baseFeePerGas": "0x7",
"blockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858",
"transactions": []
}
}
```
### 3. Execute the payload
Execute the payload using [`engine_newPayloadV1`](https://ethereum.github.io/execution-apis/api/methods/engine_newPayloadV1)
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"engine_newPayloadV1","params":[
{
"parentHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a",
"feeRecipient": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"stateRoot": "0xca3149fa9e37db08d1cd49c9061db1002ef1cd58db2210f2115c8c989b2bdf45",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"prevRandao": "0x0000000000000000000000000000000000000000000000000000000000000000",
"blockNumber": "0x1",
"gasLimit": "0x1c9c380",
"gasUsed": "0x0",
"timestamp": "0x5",
"extraData": "0x",
"baseFeePerGas": "0x7",
"blockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858",
"transactions": []
}
],"id":67}' http://127.0.0.1:8550
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"status": "VALID",
"latestValidHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858",
"validationError": null
}
}
```
### 4. Update the fork choice
Update the fork choice using [`engine_forkchoiceUpdatedV1`](https://ethereum.github.io/execution-apis/api/methods/engine_forkchoiceUpdatedV1) again.
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"engine_forkchoiceUpdatedV1","params":[{"headBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", "safeBlockHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858", "finalizedBlockHash": "0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a"},null],"id":67}' http://127.0.0.1:8550
```
```json
{
"jsonrpc": "2.0",
"id": 67,
"result": {
"payloadStatus": {
"status": "VALID",
"latestValidHash": "0x3559e851470f6e7bbed1db474980683e8c315bfce99b2a6ef47c057c04de7858",
"validationError": null
},
"payloadId": null
}
}
```
---
## Public networks
# Besu for public networks
Besu serves as an [execution client](concepts/node-clients.md#execution-clients) on public proof-of-stake Ethereum networks such as:
- Ethereum Mainnet
- Hoodi
- Ephemery
- Sepolia
:::note
Besu is also compatible with [Linea](https://docs.linea.build/get-started/how-to/run-a-node/besu), the Ethereum L2.
:::
Get started by [installing Besu](get-started/install/index.md).
## Architecture
The following diagram outlines the high-level architecture of Besu for public networks.

If you have any questions about Besu for public networks, ask on the **besu** channel on
[Discord](https://discord.gg/hyperledger).
---
## ADMIN methods
# `ADMIN` methods
The `ADMIN` API methods provide administrative functionality to manage your node.
:::note
The `ADMIN` API is not enabled by default for JSON-RPC.
Enable it using the [`--rpc-http-api`](../options.md#rpc-http-api) or [`--rpc-ws-api`](../options.md#rpc-ws-api) option.
:::
## `admin_addPeer`
Adds a [static node](../../how-to/connect/static-nodes.md).
:::caution
If connections are timing out, ensure the node ID in the [enode URL](../../concepts/node-keys.md#enode-url) is correct.
:::
### Parameters
- `enode`: _string_ - [Enode URL](../../concepts/node-keys.md#enode-url) of peer to add.
### Returns
- `true` if peer added or `false` if peer is already a [static node](../../how-to/connect/static-nodes.md).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "admin_addPeer",
"params": [
"enode://f59c0ab603377b6ec88b89d5bb41b98fc385030ab1e4b03752db6f7dab364559d92c757c13116ae6408d2d33f0138e7812eb8b696b2a22fe3332c4b5127b22a3@127.0.0.1:30304"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "admin_addPeer",
"params": [
"enode://f59c0ab603377b6ec88b89d5bb41b98fc385030ab1e4b03752db6f7dab364559d92c757c13116ae6408d2d33f0138e7812eb8b696b2a22fe3332c4b5127b22a3@127.0.0.1:30304"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
---
## `admin_changeLogLevel`
Changes the log level without restarting Besu. You can change the log level for all logs, or you can change the log level for specific packages or classes.
You can specify only one log level per RPC call.
### Parameters
- `level`: _string_ - [Log level](../options.md#logging).
- `log_filter`: _array_ - (Optional) Packages or classes for which to change the log level.
### Returns
- `Success` if the log level has changed, otherwise `error`.
### Example
The following example changes the debug level for specified classes to `DEBUG`.
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "admin_changeLogLevel",
"params": [
"DEBUG",
[
"org.hyperledger.besu.ethereum.eth.manager",
"org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.ApiHandler"
]
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "admin_changeLogLevel",
"params": [
"DEBUG",
[
"org.hyperledger.besu.ethereum.eth.manager",
"org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.ApiHandler"
]
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
The following example changes the debug level of all logs to `WARN`.
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "admin_changeLogLevel",
"params": [
"WARN"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "admin_changeLogLevel",
"params": [
"WARN"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## `admin_generateLogBloomCache`
Generates cached log bloom indexes for blocks.
API methods such as [`eth_getLogs`](eth/filter.md#eth_getlogs) and [`eth_getFilterLogs`](eth/filter.md#eth_getfilterlogs) use the cache for improved performance.
:::tip
Manually executing `admin_generateLogBloomCache` is not required unless the [`--auto-log-bloom-caching-enabled`](../options.md#auto-log-bloom-caching-enabled) command line option is set to false.
:::
:::note
Each index file contains 100000 blocks. The last fragment of blocks less than 100000 are not indexed.
:::
### Parameters
- `startBlock`: _string_ - Block to start generating indexes.
- `endBlock`: _string_ - Block to stop generating indexes.
### Returns
- Log bloom index details.
- `startBlock`: _string_ - Starting block for the last requested cache generation.
- `endBlock`: _string_ - Ending block for the last requested cache generation.
- `currentBlock`: _string_ - Most recent block added to the cache.
- `indexing`: _boolean_ - Indicates if indexing is in progress.
- `requestAccepted`: _boolean_ - Indicates acceptance of the request from this call to generate the cache.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "admin_generateLogBloomCache",
"params": [
"0x0",
"0x10000"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "admin_generateLogBloomCache",
"params": [
"0x0",
"0x10000"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"startBlock": "0x0",
"endBlock": "0x10000",
"currentBlock": "0x0",
"indexing": true,
"requestAccepted": true
}
}
```
---
## `admin_logsRemoveCache`
Removes cache files for the specified range of blocks.
### Parameters
- `fromBlock`: _string_ - Hexadecimal integer representing a block number, or one of the
string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../how-to/use-besu-api/json-rpc.md#block-parameter).
- `toBlock`: _string_ - Hexadecimal integer representing a block number, or one of the
string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
You can skip a parameter by using an empty string, `""`. If you specify:
- No parameters, the call removes cache files for all blocks.
- Only `fromBlock`, the call removes cache files for the specified block.
- Only `toBlock`, the call removes cache files from the genesis block to the specified block.
### Returns
- `Cache Removed` status or `error`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "admin_logsRemoveCache",
"params": [
"0x1",
"0x64"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "admin_logsRemoveCache",
"params": [
"0x1",
"0x64"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"Status": "Cache Removed"
}
}
```
---
## `admin_logsRepairCache`
Repairs cached logs by fixing all segments starting with the specified block number.
### Parameters
- `startBlock`: _string_ - Decimal index of the starting block to fix.
The default is the head block.
### Returns
- Status of the repair request; `Started` or `Already running`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "admin_logsRepairCache",
"params": [
"1200"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "admin_logsRepairCache",
"params": [
"1200"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"Status": "Started"
}
}
```
---
## `admin_nodeInfo`
Returns networking information about the node. The information includes general information about the node and specific information from each running Ethereum sub-protocol (for example, `eth`).
### Parameters
- None
### Returns
- Node object.
- `id`: _string_ - [Node public key](../../concepts/node-keys.md#node-public-key).
- `name`: _string_ - Client name.
- `activeFork`: _string_ - Active EVM hard fork name for the current chain head.
- `enode`: _string_ - [Enode URL](../../concepts/node-keys.md#enode-url) of the node.
- `enr`: _string_ - [ENR URL](../../concepts/node-keys.md#enr-url) of the node.
- `ip`: _string_ - IP address.
- `ipv6`: _string_ - IPv6 address.
- `listenAddr`: _string_ - Host and port for the node.
- `listenAddrV6`: _string_ - IPv6 host and port for the node.
- `ports`: _object_ - Peer discovery and listening ports.
- `discovery`: _number_ - UDP discovery port.
- `discoveryV6`: _number_ - IPv6 UDP discovery port.
- `listener`: _number_ - TCP listening port.
- `listenerV6`: _number_ - IPv6 TCP listening port.
- `protocols`: _object_ - List of objects containing information for each Ethereum sub-protocol.
:::note
If the node is running locally, the host of the `enode` and `listenAddr` display as `[::]` in the result. When advertising externally, the external address displayed for the `enode` and `listenAddr` is defined by [`--nat-method`](../../how-to/connect/specify-nat.md).
:::
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "admin_nodeInfo",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "admin_nodeInfo",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "bdf43211dba30bf100a00040b9f839e17161c88c8573028b8533c8adf8ed1e9466e4b87d716d06292426d154d0df7acde83c3f68df151da5413224b22f049054",
"name": "besu/v26.3-develop-f2ec0fe/osx-aarch_64/oracle_openjdk-java-22",
"enode": "enode://87ec35d558352cc55cd1bf6a472557797f91287b78fe5e86760219124563450ad1bb807e4cc61e86c574189a851733227155551a14b9d0e1f62c5e11332a18a3@[::]:30303",
"enr": "enr:-Jq4QOBEJ_aqkcth60IN44olOQ3uNsfqwEahYc6eKRfBg8ZlGbqhHTKqN_Yr67QWUA9v8_l-iaYhpd2uJC_AEQDv3agCg2V0aMrJhPxk7ASDEYwwgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQK99DIR26ML8QCgAEC5-DnhcWHIjIVzAouFM8it-O0elIN0Y3CCdl-DdWRwgnZf",
"ip": "172.28.0.10",
"ipv6": "fd00:dead:beef:0:0:0:0:10",
"listenAddr": "172.28.0.10:30303",
"listenAddrV6": "[fd00:dead:beef:0:0:0:0:10]:30404",
"ports": {
"discovery": 30303,
"discoveryV6": 30404,
"listener": 30303,
"listenerV6": 30404
},
"protocols": {
"eth": {
"config": {
"chainId": 2018,
"homesteadBlock": 0,
"daoForkBlock": 0,
"daoForkSupport": true,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"constantinopleFixBlock": 0,
"ethash": {
"fixeddifficulty": 100
}
},
"difficulty": 78536,
"genesis": "0x43ee12d45470e57c86a0dfe008a5b847af9e372d05e8ba8f01434526eb2bea0f",
"head": "0xc6677651f16d07ae59cab3a5e1f0b814ed2ec27c00a93297b2aa2e29707844d9",
"network": 2018
}
}
}
}
```
---
## `admin_peers`
Returns networking information about connected remote nodes.
### Parameters
- None
### Returns
- List of objects returned for each remote node.
- `version`: _string_ - P2P protocol version.
- `name`: _string_ - Client name.
- `caps`: _array_ of _strings_ - List of Ethereum sub-protocol capabilities.
- `network`: _object_ - Local and remote addresses established at time of bonding with the peer (the remote address might not match the hex value for `port`; it depends on which node initiated the connection.)
- `port`: _string_ - Port on the remote node on which P2P discovery is listening.
- `id`: _string_ - Node public key (excluding the `0x` prefix, the node public key is the ID in the [enode URL](../../concepts/node-keys.md#enode-url) `enode://@:`.)
- `protocols`: _object_ - [Current state of peer](../../how-to/connect/manage-peers.md#monitor-peer-connections) including `difficulty`, `head`, and `latestBlock` (`head` is the hash of the highest known block for the peer; `latestBlock` is the corresponding block number.)
- `enode`: _string_ - Enode URL of the remote node.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "admin_peers",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "admin_peers",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"version": "0x5",
"name": "besu/v20.10.4-dev-0905d1b2/osx-x86_64/adoptopenjdk-java-11",
"caps": ["eth/67", "eth/68", "IBF/1"],
"network": {
"localAddress": "192.168.1.229:50115",
"remoteAddress": "168.61.153.255:40303"
},
"port": "0x765f",
"id": "0xe143eadaf670d49afa3327cae2e655b083f5a89dac037c9af065914a9f8e6bceebcfe7ae2258bd22a9cd18b6a6de07b9790e71de49b78afa456e401bd2fb22fc",
"protocols": {
"eth": {
"difficulty": "0x1ac",
"head": "0x964090ae9277aef43f47f1b8c28411f162243d523118605f0b1231dbfdf3611a",
"latestBlock": 428,
"version": 65
}
},
"enode": "enode://e143eadaf670d49afa3327cae2e655b083f5a89dac037c9af065914a9f8e6bceebcfe7ae2258bd22a9cd18b6a6de07b9790e71de49b78afa456e401bd2fb22fc@127.0.0.1:30303"
}
]
}
```
---
## `admin_removePeer`
Removes a [static node](../../how-to/connect/static-nodes.md).
### Parameters
- `enode`: _string_ - [Enode URL](../../concepts/node-keys.md#enode-url) of peer to remove.
### Returns
- `true` if peer removed or `false` if peer is not a [static node](../../how-to/connect/static-nodes.md).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "admin_removePeer",
"params": [
"enode://f59c0ab603377b6ec88b89d5bb41b98fc385030ab1e4b03752db6f7dab364559d92c757c13116ae6408d2d33f0138e7812eb8b696b2a22fe3332c4b5127b22a3@127.0.0.1:30304"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "admin_removePeer",
"params": [
"enode://f59c0ab603377b6ec88b89d5bb41b98fc385030ab1e4b03752db6f7dab364559d92c757c13116ae6408d2d33f0138e7812eb8b696b2a22fe3332c4b5127b22a3@127.0.0.1:30304"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
---
## Getters
These methods retrieve bad blocks and raw, RLP-encoded blocks, headers, receipts, and transactions.
## `debug_getBadBlocks`
Returns a list of invalid blocks. This is used to detect and analyze consensus flaws.
### Parameters
- None
### Returns
- List of block objects.
- `number`: _quantity, integer_ - Block number. `null` when block is pending.
- `hash`: _data, 32 bytes_ - Hash of the block. `null` when block is pending.
- `mixHash`: _data, 32 bytes_ - For pre-[merge](https://ethereum.org/roadmap/merge/) blocks, the hash used to verify the proof of work. For post-merge blocks, the `prevRandao` value supplied by the consensus layer.
- `parentHash`: _data, 32 bytes_ - Hash of the parent block.
- `nonce`: _data, 8 bytes_ - Hash of the generated proof of work. `null` when block is pending.
- `sha3Uncles`: _data, 32 bytes_ - SHA3 of the uncle's data in the block.
- `logsBloom`: _data, 256 bytes_ - Bloom filter for the block logs. `null` when block is pending.
- `transactionsRoot`: _data, 32 bytes_ - Root of the transaction trie for the block.
- `stateRoot`: _data, 32 bytes_ - Root of the final state trie for the block.
- `receiptsRoot`: _data, 32 bytes_ - Root of the receipts trie for the block.
- `miner`: _data, 20 bytes_ - Address to pay mining rewards to.
- `difficulty`: _quantity, integer_ - Difficulty for this block.
- `totalDifficulty`: _quantity, integer_ - Total difficulty of the chain until this block. Only present for pre-[merge](https://ethereum.org/roadmap/merge/) blocks. This value will always be `0` for an uncle block.
- `extraData`: _data_ - Extra data field for this block. The first 32 bytes is vanity data you can set using the [`--miner-extra-data`](../../options.md#miner-extra-data) command line option. Stores extra data when used with [IBFT](../../../../private-networks/how-to/configure/consensus/ibft.md#genesis-file).
- `size`: _quantity, integer_ - Size of block in bytes.
- `gasLimit`: _quantity_ - Maximum gas allowed in this block.
- `gasUsed`: _quantity_ - Total gas used by all transactions in this block.
- `timestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) for block assembly.
- `transactions`: _array_ - Array of transaction objects, or 32 byte transaction hashes depending on the specified boolean parameter.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
- `uncles`: _array_ - Array of uncle hashes.
- `baseFeePerGas`: _quantity_ - The block's [base fee per gas](../../../concepts/transactions/types.md#eip1559-transactions). Only present for blocks created after [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559).
- `withdrawalsRoot`: _data, 32 bytes_ - Root of the withdrawals trie for the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `withdrawals`: _array_ - Array of validator withdrawal objects included in the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `index`: _quantity_ - Index of the withdrawal.
- `validatorIndex`: _quantity_ - Index of the validator that initiated the withdrawal.
- `address`: _data, 20 bytes_ - Address the withdrawal was sent to.
- `amount`: _quantity_ - Amount withdrawn, in Gwei.
- `blobGasUsed`: _quantity_ - Total blob gas used by the transactions in this block. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `excessBlobGas`: _quantity_ - Running total of excess blob gas used to calculate the blob base fee for subsequent blocks. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `parentBeaconBlockRoot`: _data, 32 bytes_ - Root of the parent beacon block, which exposes beacon chain state to the EVM. Only present for blocks created after [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) (Cancun).
- `requestsHash`: _data, 32 bytes_ - Hash of the general purpose execution layer requests (for example, deposits, withdrawals, and consolidations) included in the block. Only present for blocks created after [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) (Prague).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_getBadBlocks",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_getBadBlocks",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"block": {
"number": "0xd",
"hash": "0x85c2edc1ca74b4863cab46ff6ed4df514a698aa7c29a9bce58742a33af07d7e6",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x544a2f7a4c8defc0d8da44aa0c0db7c36b56db2605c01ed266e919e936579d31",
"nonce": "0x0000000000000000",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"transactionsRoot": "0x02c387e001cbe2a8296bfa2e18afbc3480d0e49588b05556148b0bf7c17dec41",
"stateRoot": "0x861ab7e868e3c23f84b7c4ed86b52a6a4f063633bc45ef29212c33459df84ea5",
"receiptsRoot": "0xccd2d33763dc0ac3fe02d4ecbbcd7d2bdc6f57db635ba31007184679303721d7",
"miner": "0x0000000000000000000000000000000000000000",
"difficulty": "0x1",
"totalDifficulty": "0x1",
"extraData": "0x00000000000000000000000000000000000000000000000000000000000000008c6a091f07e4ba3930f2f5fabbfc5b1c70986319096760ba200a6abc0d30e33c2d501702d1b58d7f75807bdbf981044557628611319121170b96466ec06bb3fd01",
"size": "0x3a0",
"gasLimit": "0xffffffffffff",
"gasUsed": "0x1a488",
"timestamp": "0x5f5b6824",
"uncles": [],
"transactions": [
{
"blockHash": "0x85c2edc1ca74b4863cab46ff6ed4df514a698aa7c29a9bce58742a33af07d7e6",
"blockNumber": "0xd",
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0x1a49e",
"gasPrice": "0x3e8",
"hash": "0xdd8cf045113754c306ba9ac8ac8786235e33bc5c087678084ef260a2a583f127",
"input": "0x608060405234801561001057600080fd5b5060c78061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d146037578063b05784b8146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea26469706673582212208dea039245bf78c381278382d7056eef5083f7d243d8958817ef447e0a403bd064736f6c63430006060033",
"nonce": "0x0",
"to": null,
"transactionIndex": "0x0",
"value": "0x0",
"v": "0xf9d",
"r": "0xa7a15050302ca4b7d3842d35cdd3cbf25b2c48c0c37f96d78beb6a6a6bc4f1c7",
"s": "0x130d29294b2b6a2b7e89f501eb27772f7abf37bfa28a1ce300daade975589fca"
}
]
},
"hash": "0x85c2edc1ca74b4863cab46ff6ed4df514a698aa7c29a9bce58742a33af07d7e6",
"rlp": "0xf9039df9025ca0544a2f7a4c8defc0d8da44aa0c0db7c36b56db2605c01ed266e919e936579d31a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0861ab7e868e3c23f84b7c4ed86b52a6a4f063633bc45ef29212c33459df84ea5a002c387e001cbe2a8296bfa2e18afbc3480d0e49588b05556148b0bf7c17dec41a0ccd2d33763dc0ac3fe02d4ecbbcd7d2bdc6f57db635ba31007184679303721d7b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010d86ffffffffffff8301a488845f5b6824b86100000000000000000000000000000000000000000000000000000000000000008c6a091f07e4ba3930f2f5fabbfc5b1c70986319096760ba200a6abc0d30e33c2d501702d1b58d7f75807bdbf981044557628611319121170b96466ec06bb3fd01a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f9013af90137808203e88301a49e8080b8e6608060405234801561001057600080fd5b5060c78061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d146037578063b05784b8146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea26469706673582212208dea039245bf78c381278382d7056eef5083f7d243d8958817ef447e0a403bd064736f6c63430006060033820f9da0a7a15050302ca4b7d3842d35cdd3cbf25b2c48c0c37f96d78beb6a6a6bc4f1c7a0130d29294b2b6a2b7e89f501eb27772f7abf37bfa28a1ce300daade975589fcac0"
},
{
"block": {
"number": "0x8",
"hash": "0x601a3ae9b6eceb2476d249e1cffe058ba3ff2c9c1b28b1ec7a0259fdd1d90121",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0x98ae440cd7b904d842daa6c263608969a3c8ce6a9acd6bd1f99b394f5f28a207",
"nonce": "0x0000000000000000",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"transactionsRoot": "0x8ee998cc699a1f9310a1079458780b3ebee8756f96a0905f5224b89d0eb17486",
"stateRoot": "0x140a9783291704223eb759e3a0db5471a520d349fc17ac2f77ff8582472e3bac",
"receiptsRoot": "0x2b5c77f6e7764d2468178fab7253346b9b8bb6a34b63946f6bdc2f5ad398bfc3",
"miner": "0x0000000000000000000000000000000000000000",
"difficulty": "0x2",
"totalDifficulty": "0x2",
"extraData": "0x00000000000000000000000000000000000000000000000000000000000000004d04551bdd9ae08af1fd661e49d4ab662c98c532c7ec0e4656a27e4de7d330af578ab1e4f5e49e085ff1d78673c7388ed9ccf017fbe89e53066bfa4018142c0701",
"size": "0x3a0",
"gasLimit": "0xffffffffffff",
"gasUsed": "0x1a4c9",
"timestamp": "0x5f5b6b80",
"uncles": [],
"transactions": [
{
"blockHash": "0x601a3ae9b6eceb2476d249e1cffe058ba3ff2c9c1b28b1ec7a0259fdd1d90121",
"blockNumber": "0x8",
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0x1a4c9",
"gasPrice": "0x3e8",
"hash": "0x675e336a4281b29c619dfd4ccfbd2f930f3728b20caf9e0067284aa3224e6758",
"input": "0x608060405234801561001057600080fd5b5060c78061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d146037578063b05784b8146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea26469706673582212208dea039245bf78c381278382d7056eef5083f7d243d8958817ef447e0a403bd064736f6c63430006060033",
"nonce": "0x0",
"to": null,
"transactionIndex": "0x0",
"value": "0x0",
"v": "0xf9d",
"r": "0x2e30624c0305e64812e1d9e325ba6e50410314634b008edcb50f45be71fa0d4",
"s": "0x50e205faed23c219ba15610de2451d458cbd4221207b2168344cfc972a7973c0"
}
]
},
"hash": "0x601a3ae9b6eceb2476d249e1cffe058ba3ff2c9c1b28b1ec7a0259fdd1d90121",
"rlp": "0xf9039df9025ca098ae440cd7b904d842daa6c263608969a3c8ce6a9acd6bd1f99b394f5f28a207a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0140a9783291704223eb759e3a0db5471a520d349fc17ac2f77ff8582472e3baca08ee998cc699a1f9310a1079458780b3ebee8756f96a0905f5224b89d0eb17486a02b5c77f6e7764d2468178fab7253346b9b8bb6a34b63946f6bdc2f5ad398bfc3b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020886ffffffffffff8301a4c9845f5b6b80b86100000000000000000000000000000000000000000000000000000000000000004d04551bdd9ae08af1fd661e49d4ab662c98c532c7ec0e4656a27e4de7d330af578ab1e4f5e49e085ff1d78673c7388ed9ccf017fbe89e53066bfa4018142c0701a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f9013af90137808203e88301a4c98080b8e6608060405234801561001057600080fd5b5060c78061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80636057361d146037578063b05784b8146062575b600080fd5b606060048036036020811015604b57600080fd5b8101908080359060200190929190505050607e565b005b60686088565b6040518082815260200191505060405180910390f35b8060008190555050565b6000805490509056fea26469706673582212208dea039245bf78c381278382d7056eef5083f7d243d8958817ef447e0a403bd064736f6c63430006060033820f9da002e30624c0305e64812e1d9e325ba6e50410314634b008edcb50f45be71fa0d4a050e205faed23c219ba15610de2451d458cbd4221207b2168344cfc972a7973c0c0"
}
]
}
```
---
## `debug_getRawBlock`
Returns the [RLP encoding](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/) of the specified block.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of the
string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- RLP-encoded block object.
- `number`: _quantity, integer_ - Block number. `null` when block is pending.
- `hash`: _data, 32 bytes_ - Hash of the block. `null` when block is pending.
- `mixHash`: _data, 32 bytes_ - For pre-[merge](https://ethereum.org/roadmap/merge/) blocks, the hash used to verify the proof of work. For post-merge blocks, the `prevRandao` value supplied by the consensus layer.
- `parentHash`: _data, 32 bytes_ - Hash of the parent block.
- `nonce`: _data, 8 bytes_ - Hash of the generated proof of work. `null` when block is pending.
- `sha3Uncles`: _data, 32 bytes_ - SHA3 of the uncle's data in the block.
- `logsBloom`: _data, 256 bytes_ - Bloom filter for the block logs. `null` when block is pending.
- `transactionsRoot`: _data, 32 bytes_ - Root of the transaction trie for the block.
- `stateRoot`: _data, 32 bytes_ - Root of the final state trie for the block.
- `receiptsRoot`: _data, 32 bytes_ - Root of the receipts trie for the block.
- `miner`: _data, 20 bytes_ - Address to pay mining rewards to.
- `difficulty`: _quantity, integer_ - Difficulty for this block.
- `totalDifficulty`: _quantity, integer_ - Total difficulty of the chain until this block. Only present for pre-[merge](https://ethereum.org/roadmap/merge/) blocks. This value will always be `0` for an uncle block.
- `extraData`: _data_ - Extra data field for this block. The first 32 bytes is vanity data you can set using the [`--miner-extra-data`](../../options.md#miner-extra-data) command line option. Stores extra data when used with [IBFT](../../../../private-networks/how-to/configure/consensus/ibft.md#genesis-file).
- `size`: _quantity, integer_ - Size of block in bytes.
- `gasLimit`: _quantity_ - Maximum gas allowed in this block.
- `gasUsed`: _quantity_ - Total gas used by all transactions in this block.
- `timestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) for block assembly.
- `transactions`: _array_ - Array of transaction objects, or 32 byte transaction hashes depending on the specified boolean parameter.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
- `uncles`: _array_ - Array of uncle hashes.
- `baseFeePerGas`: _quantity_ - The block's [base fee per gas](../../../concepts/transactions/types.md#eip1559-transactions). Only present for blocks created after [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559).
- `withdrawalsRoot`: _data, 32 bytes_ - Root of the withdrawals trie for the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `withdrawals`: _array_ - Array of validator withdrawal objects included in the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `index`: _quantity_ - Index of the withdrawal.
- `validatorIndex`: _quantity_ - Index of the validator that initiated the withdrawal.
- `address`: _data, 20 bytes_ - Address the withdrawal was sent to.
- `amount`: _quantity_ - Amount withdrawn, in Gwei.
- `blobGasUsed`: _quantity_ - Total blob gas used by the transactions in this block. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `excessBlobGas`: _quantity_ - Running total of excess blob gas used to calculate the blob base fee for subsequent blocks. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `parentBeaconBlockRoot`: _data, 32 bytes_ - Root of the parent beacon block, which exposes beacon chain state to the EVM. Only present for blocks created after [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) (Cancun).
- `requestsHash`: _data, 32 bytes_ - Hash of the general purpose execution layer requests (for example, deposits, withdrawals, and consolidations) included in the block. Only present for blocks created after [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) (Prague).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_getRawBlock",
"params": [
"0x32026E"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_getRawBlock",
"params": [
"0x32026E"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0xf96096f90236a09f73691f6dabca4f0a99b05d0a701995506aa311dcaa9ce9833d6f4ca474c162a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794c6e2459991bfe27cca6d86722f35da23a1e4cb97a078103ea8c47231886481d72ec1afae6eeb06c3773ce24a91323d5c9eed69d4cca0008992da2531db404f07b0871dd620a94ba346963e1b1c6dc7b00748e8593a1ea0b6c3890d9604434fc52f722848c84d1770add20cd75bbc28cdedff42940dbb56b90100200800000400000002000e0000000401000000440100000000c0400600000002000801000000040480020840048000000000400000000000000020004220000011002000000000000204000800000010010002000002000000000040a000000000000400020000010885000000000808000000008800001004002010020300005000000010002110410402000000000000000890000008000000000000000000020040000002000000000000810400000040006000004000004080020000000000000022001000000000000840400000000220250000000000080402000420000418000000000000000400040000004080040010200000000000108020020000808332026e8401c9c380833e3c3c846436f93899d883010b05846765746888676f312e32302e32856c696e7578a0112d8f15793e7df7f8dcdb21c891cff78c0d1839cb5b6dcd06116cdbb99536ae88000000000000000008a0cdb97712af6685bb9650d21d609525913293c48adda7c45990926daada335c9bf95c56f8ac82d51f8502540be4008303c9e294a68d4c1e3de1b721ad1356bbf827d6bc8cef304f80b844b1bb4d351300dbc7e12342566318001b83aefc9f20080000f3ef25472407fe9c9c69a1470000000242692bb4cd506c409651ab80eb3acfa54551d3dbc9af4493605d79871ba01e474fb147b16b9538d7a59a57738e406158d9cc306a9062b1b7a9f544c35abfa061aabb714c760f2243a16a024811679d402c8822e8b25dfd0038d84298fb5205b87502f87283aa36a754849502f900849502f9108302222794102554afa6b5dbccc86176faef2b2d854201756e8084e2bc7b43c001a04f2398f24bc950db1f5439de3cf6431ea277236595ae8dc5815c0cc671c9f97ca029898786a59c56f086fc0f7a16859f366cf46084add999fe137cbf43693712e8b87c02f87983aa36a7830293748459682f00850165a0bc008255f094fafb56bb5b37c3b0b0ee9d7c31f018aac91dfb778806f05b59d3b2000080c080a0b069dd8967533a773e592c26b1b36df0793d0b9f6eceba34da246f602c2fae58a002009dab32ab63a25b705d9a00e311f7cd5d85e73f9b2c03ffd0e5135c0bb2c6b89502f89283aa36a7018459682f008459682f0983011fec945b9fedd37f0b92e7e282b19cebcf06f57b77c60480a46a62784200000000000000000000000019a1fcc6fcc5832cd2db7704d75efbc800f5a742c001a0c65eb0e48090a8f8830de47f430b9ad11071a62a5db9555619a990d7e9b81738a05a6e826610a5b2ee529a22942ebcd3abd2a8a10228098c8158380e8fcceb962fb9028002f9027c83aa36a7178459682f008459682f0983017ac9942ab7c0ab9ab47fcf370d13058bfee28f2ec0940c880169964394fc8860b9020496e17852000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000003aa4d7eb55ec2539f5305eb27ea42f6f90f168270000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000000000000000000000000000000000000000028c5c0000000000000000000000003aa4d7eb55ec2539f5305eb27ea42f6f90f168270000000000000000000000003aa4d7eb55ec2539f5305eb27ea42f6f90f168270000000000000000000000003aa4d7eb55ec2539f5305eb27ea42f6f90f16827000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000650cb3772886000000000000000000000000000000000000000000000000000000000000222e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c080a004f8666c8e5d0f3c7110994f624d24aa47a1327814289698c3e2777284a5cfdca04ff05f1b8c5beb58972d40e5a7b894d5e28ad2f15a3429c7d2bee6b6a9633730b9019f02f9019b83aa36a70b8459682f008459682f098303644f944284890d4acd0bcb017ece481b96fd4cb457cac88715c0f4db6e0ea0b90124ee1490b20000000000000000000000000000000000000000000000000000000000028c5c0000000000000000000000007847f2e0262512206333ffb200f6d9df2da319d40000000000000000000000001e8c104d068f22d351859cdbfe41a697a98e6ea20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000222e00000000000000000000000000000000000000000000000000015c0f4db6e0ea00000000000000000000000007847f2e0262512206333ffb200f6d9df2da319d400000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000c080a0e5270f6291acc162885656bedf64fbcb904c41951221dc0cbbbdca03bb33ce43a01f08c7ed3c231403b55f37a157d80e121b653baa810add8c02aea722631450dcb87c02f87983aa36a7830293758459682f00850165a0bc008255f0948d247f4fbbe81429d3d164a5c9ae0063210edbdc8806f05b59d3b2000080c080a0bb83dd6181c9a7ae3069af3bdf1820b5e556eaf99e385b8d7b3571321fb2966ba02ac193773704524adcd02824796df83407a42cdd81e786b591eba43c4ffc6c40b9028002f9027c83aa36a7048459682f008459682f0983017ac9942ab7c0ab9ab47fcf370d13058bfee28f2ec0940c880169964394fc8860b9020496e178520000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000062d23ed77d0e5d0205edabe4ce3a27adc49ac6790000000000000000000000000000000000000000000000000000000000aa36a70000000000000000000000000000000000000000000000000000000000028c5c00000000000000000000000062d23ed77d0e5d0205edabe4ce3a27adc49ac67900000000000000000000000062d23ed77d0e5d0205edabe4ce3a27adc49ac67900000000000000000000000062d23ed77d0e5d0205edabe4ce3a27adc49ac679000000000000000000000000000000000000000000000000016345785d8a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000650cb3772886000000000000000000000000000000000000000000000000000000000000222e000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c001a0fc882968005f717a74a2c2fb345f691091cab084f4bd3934358741807bd5a66ea03f81c68d05d06bf851a6ef5ea6874557a221cbadde24f3fa51f777699b5d2804b8d802f8d583aa36a7822c0b8459682f008459682f098303534f943367dfa11e3148a07c2da773e1f65b155b0abe5680b864ad58bdd100000000000000000000000053844f9577c2334e541aec7df7174ece5df1fcf0000000000000000000000000e9e12c660e77a732940bab3c2cf385c843b834b800000000000000000000000000000000000000000006015d637c177581800000c001a0a292e7723d3c950aa8a557bd91dece34ec527d9efe2cc413d582dcd9fc6bf6eba03386ce6f58e862f329946bf32897f7df5d1c8f818fecfafc1223052fb251d97eb8b602f8b383aa36a7138459682f008459682f09832dc6c094ba175fdab00e7fcf603f43be8f68db7f4de9f3a980b844095ea7b300000000000000000000000084a0cc1ab353da6b7817947f7b116b8ea982c3d20000000000000000000000000000000000000000000000068f365aea1e440000c001a0968ed0274829918071d9cef28e1adbf1fd15ec76e5a4f809971e887b4c9f34b6a001ce26485bc7e3ea71fb99866bd43002b264b2ed80e10850203c2f07b78856bdb87c02f87983aa36a7830293768459682f00850165a0bc008255f0946d3b93db4e4078cf6541a68532d00705d9a4da618806f05b59d3b2000080c080a083c831630788e7ee57c87128d18582e29aa51f1f233e91d916c06d0750578156a0549b5a00477f3fb4d8fbf95ba3a636c3a14ff011c1bbf3a717e00d61735cbf34b87c02f87983aa36a7830293778459682f00850165a0bc008255f0940d3a7d69859a0dd6971d39703b15379e05ae2ec48806f05b59d3b2000080c001a0082660b5db2d3a8a58c0b863673ab27f7cfe4c049dcc52c76a00ab45b0358db5a05a7519a2d399cb534480383ac21262fbde2dd85241495d7832dee8bb02c49c87b87c02f87983aa36a7830293788459682f00850165a0bc008255f0941be13f64a2463fc7a76b4092c53328cc965a77fb8806f05b59d3b2000080c001a0e6ee9b85c3b729518524fdaeb25d47f89f6fc6c4d2c4df707187bef74d73f958a0756bbf4ab119805b77466957b5895c1d5bf422c5f65d8a06f7efd37dcb2c87afb87c02f87983aa36a7830293798459682f00850165a0bc008255f094a90b28fd6f8e46ac668fcb688414184a163e2cd28806f05b59d3b2000080c080a0d394dd43c58591e5dda8a7f3a2f4eae1bfd65655b9e9eec5facc6dcb39aa77baa002eeabf3fe9c0a56eae476d2f6452ea72e63a9c9b1180290b792883258f939f5b8f802f8f583aa36a7830283818459682f008459682f1082962494d0f723c6b2226df56fe41e63b9eaa66eb540bcb880b884abac047b000000000000000000000000000000000000000000000000000000000103e9f0f3471dc445d8f209ef546e0d20eaccc12ed0a5b4100007f57d9bc8638dacaf6480000000000000000000000000000000000000000000000000000000001d209b1ea11d77d1ab457eb3e2954cb2b98e77b5b07e2a4f48507af0adc61329ddc210c001a0efa10ab60f3bd1e7c4a8d52a275a568fbe2f5edc9e1eaf386299577ff9ddbd6ba06e62cf2f66b58f655ddd3eae47ce40408445b086f6ea858edb7bd847ee206207f86f82e6e582014482f618949ebf6b12e7e33b8672788e7b2b3330356f6f2c41880de0b6b3a7640000808401546d72a008d6be7aa21be0a43e08e960620f4c40c44010a743ead9919ef9423863c08b12a06a63a7caae4504ee5528e50387ca09974f7124035328a62d1085da2fee6618f9f86f82e1c382014482f618949c68eb31c4d00b94c3e3d4c2887946f8b076b24c880de0b6b3a7640000808401546d72a0c22d48d72c70ccf0a44d0950daf16741838f9333ee0bc5e05ff02b058da1e010a06a20c9f74cbc14c0d5bf3b3c38d3c33a5ace9194cddc2c533afb16459eaa7647f86f82e4cb82014482f61894d531e7aa3c0bee832aaff22642c7a3128d48a81a880de0b6b3a7640000808401546d72a01dbaeffc8e11964c06a722bae73e35bb5de55b8f959592868f2ff5fc13b69bd3a002acadc04665570a2032cdb616de15bdca79127f21302d62db5baf96ae4734e6f86e830176e381d882520894ad346e81c5b26fe563ab1ba2aa4ff811655882ca872386f26fc10000808401546d72a0b6de11598824e338100d5ebe70c0b0f4d6893fbb36f11ad55cf74b2f43afc5dda05101e65e7e84ea9edba6e5bf1a1e07028ae3fa5213240e812e57cf6b29080726b9235302f9234f83aa36a7830137d564748315f52194ac9251ee97ed8bef31706354310c6b020c35d87b80b922e48ed7b3be000000000000000000000000000000000000000000000000000000000001edc00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001fe000000000000000000000000000000000000000000000000000000000000020c00000000000000000000000000000000000000000000000000000000000001f60000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002200000000000000000000000009d69394bd71906a235f9113cc04321f573958d3e00000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001edc00000000000000000000000000000000000000000000000000000000000320266d6b1b655f66cf8f99d35432492f8fbedfa97a2a48f0efaae65de6738e2594aa5000000000000000000000000000077770000000000000000000000000000000191c15235c348207e935e72b9151056a9661d73631d1e2c3f89ffddf8e74efe8a42ab8767076a555a049372055c846097c99e69c26ab0a24553d21c15de29ea900000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000030ef2c000000000000000000000000000000000000000000000000000000006436f8d800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d65822107fcfd520000000000000000000000000000000000000000000000000000000000000000ec15abee257256da1a964434000f59ddd45b1ce67d5df44f1c82fd5bfe95c3b31dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493470000000000000000000000000000777700000000000000000000000000000001d4b5b35d93f51c8143f6a4cc3d7b320d37ce03989cd88c28601f4ea94cd6554249cff83e4dd8e99a8ef9004b2ac7518996f4784af1f9e52debb6223a697e9652530feda219f333e01f8cd0b31ee83b9c250ee51fde9718ef5fa305cbcd01901200200100002020000400000280000006004000c0020000000000000000000100000000029000000000000000090000000000008000200040000012004020000800000000240002400008000800000020000000001040000000000040824000000000000002040000400000002000080000000000000804000000001001000c84000208000000000180020000014000000000210100510008000082c0000000001200002000000024000008400000000220001800400000008010000052000200000200028000000000800000040200000110000010000010000001020000210004100002000000000900280000010008001000000018004000000020000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001edc0000000000000000000000000000000000000000000000000000000000034bfbc00000000000000000000000000000000000000000000000000000000002ddb24000000000000000000000000000000000000000000000000000000006436f8d800000000000000000000000000000000000000000000000000000000000002e042ab8767076a555a049372055c846097c99e69c26ab0a24553d21c15de29ea900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000016202bf20ff78727f38ef16e03bfb3d4895f35cc626f97ede7cc99f48aeff8661fe32015ea8d62ec7a79e01cd398e85867bafdcf55cb6a7121b6fef097f5f5656a5d11ddf336b6879926ea2ae425e91c748a553c9a496cbe2ab556a91689f75ee2b01ad3c43aa774b50a9d8411a9f65be42d6cde781db1a1949a1e886f868917997b2a7122720155935f15da0807d0054f1a4c3db2a92ec4124bf590ce7a16594f3f1812f260acb049d01ad534a937840a80c0f56fd9a54ca5a8628ed896d14a5f8b2570f5813e35c990656f6300a1a1849429135ada6337646248f6ea03a7f70ac426c1d805216d154ea5a8e5ff953bc04b71b049b4b5bd549b6b0cfa7f8b21dba72a3805c7093d8589f2d4c55b6211441041e8bd7916daed5093fcebd377c31e810a6499e6e26840e3afadc9b339c6abc86b7f89fc3559f4242d373a71389db20219195f6e13069701f6d539dcf63a049726cdd8cadc412d1c43cf3fc0095ae5e2157dc668bdb924d7d7afc2b4632ab8a0e4ef71941a0a6a65645f6cd8570302f90b98bbdd01be238dc07780ee9b93e22ab87f26170d7fc5531347fb9fadcb65dc2ca20442a70be9e785292d533fa9496308a7b1588b50b45c17ea765de525259f036edd3984782399b46793acd5abb9f49e38b309c2363aead57264ac1a44e6432b81127a0bfdc29f01bd04e7db2b2545ed8426d2fe9b3e561793ec8fc875f2a71f31c13d11b94f892bb9f96bd2931b66ffa5e22b104c549e7c0d5010e4e70e271d48c0bd6e4be68c920ea77af85d12eb155d9b25703eabbd0ede1909565a55f11fcba848e01c60438611958101321898e95c8fdc936d31389bdba8073b382e5b1e2cd25993ad31586d7525f165fb25a1cf8c22623f983c025d21f0e52ecfec5f0232a753addaad88340ca39f00e9722f35dd25fbe8fdd8846bfc0288215d0638004009396bfcd5e6eb0c587797ae8297decbca48b02407219b910ce163552ed230438292cec430007886beabe7cdf5c6f9c3740a3dd6c52ba88e6d652ce43f90044193c4a42335291795c2cc160dc68b6225edb425a88d27cae159f77df3a2241fbe809c8f1122d245bf439df0761bec97358b96d6653bc83702b559bde5a2d12f771a2a11bc9dc32580bc3ccf9dfacd0a5379587ac5160b45d333a85cde46810ad2875b406f00438aee245ecc63815528a185e9e2a029147db7fcffcb8875e5259f15c3e467de02e035891b131bc715e54e7e27a7acc437bb9f6f84fa4456aa016b3578a73ed8a4706efb935be8b6abe0697e46d878d9c74e274f2816d2fd88146b316731719e125d227e002af95aa13f468a9bae4ff41a4a6036ee7fc321b3249aed4dfb6e75089ec0656ee4e87e1fffefbd74edf55a20d752a85caccf583c0d9e2ef1040b4d36a8e992ad50ce1c4bd2b300b344ca881725c164886a5f8f18035f6e75e67a3eaa2064fc24ff79897edb624e1a67f34deb414d5efaf4c55d482da108aa2ab7504fd5d7f78d91da5c20230380ec013b910b01a26b8bed8a05a004d52db30b7fb01f16347692e9f19f303f48ea8cbbed2d3a3eb277ddf4e9ed8026af5ce92a618c8942caf28b3249044347e14e5c3c2ed5ec0f9cccf1d11a5b290c00773e12c25feafbcceeb8ae6c25a88c9657c627187af6fe0bfea0b3cc36c908a76f90e965bc4135c8596534f444c91aaaaaa6277985e36248bd53ef0f74f103eeac98ba92c5350e4a0c586c851ad25df982e16b2d408de37c687efc6915a41197df379614aa657ab5100627c47896b51b000cb95505bac77e4e440ecd1fe50252fc98f15ee41cafbf717e144da35f424e141639de04ebe5d333e9df8c06821c689d1ef2abbfd12e8a1edc059a9279db7ff44bac1962b5f7297da5c989528229e98a91a3a2e351f371dfa34d4c3676725baa5fa4696f67f4239b5fe1e3fa351d66aa5a2df992426d94ba049bbb4eea0ab22e3b9a7409f2b6719ede64353f4112e4da3919adc16dcd99c545966256493d2699ae529e365c20515d95c013ba2627576fb75a030ffd25b85ed3fc40dbbedbca54427f8dc2255c16b742b3e2b82e1bb634ae73a402927e6dc424d1908942b9b0f2cc17909ed050defe85d24a1986291facbb4ecf9b7ff66c27f8e771d28ec6866e3d24bc97e7be388013df8ba8f407b9147ed9b3581784003a22eeada55656d2be271afce06ef3fca32ac9b77b4f2420d60e892c95418b2a1b7d3dae2738a073ef105e66c08488e8a91e8ebdb5a10e979611bd29245c13cc4c0f5b33eedc5263edd6c27666e0c3f02161114120230511406f9f82102fd8c37c36d4e383e445df4afc6e7dbaa570cfe05b3f6038ec1b7932b70e7b068a2656173d241e8f20bb6be3a3a3767111aa6f459f84be961c2337f6e03ed3cc6c847a3683894288b471504cbdc43a78f856801a10a87c77322e36e0ca426ec67ad3a2a3b79bc5cb81928a79a67a0fb46bb967cbab73fd36022f92d920204de61717dde6a85b7bcf57584c11ce54ac92998f856bf042a01c5006f155ac97d6757728caceba5530eb745e72277723ad34268b34008a97a27c370e9bc006aeaca4ac36414f35aa41ff400f698623a447c949f7f004f3c3fdb09f2af3c96042e215f0d4bbb23fda72d4f01dd9a55dbdec930919715a23e2cd772a260e2b91324c244d88ce1b83c92dce1aa0e0c255b80ed9325dec0e677563984a1c559ddb4a544eadeb2a38e8ed7736174a30d2bee6e0b65f3766e0b7a4e4d8022dd9f82493a9b1fadd1907147ac29edeb8cf8c7c58fbfa9b82ed3d9f9f05bfc900e52e29a05ca8d445b5245b16928dd61800ebb63933d9c471c2fb38776459641e9debdc606abf6ccfdf8fb41da88ba0745d96fd4557a879fee82e33df32d18b18d7360529f89f3dea680a5cb0c6a7652ee38589e1997f3e64ce4db1d3c04cd628fc0fd6e7ef1944108d48eb742a28467fa4bca693dbc8f923945256da2a83222d172286c82b1949803c54409de4653f258d0cf4266c83d5675ca9b5b3a3fb322b9c493ed7bff0a6165babb19c94d9e2014b13b099f09894fbcf32959b9d4ce71ddf9d24dee8bc40d6be92ee6e1220d84d68ecf1a0424132315c0612802b477b0acabcf346b0ad5ea329ea72f4de7524530bc00ad36baeee835908655faecd350463484d31623127c09c6cec446a9ac9a53cb6841ca2a097ceef88e537e209880ffdcfd5033bc3f5a885c271e41ee332366345fa867780beb3c1d5eaa496ea0908c560e84b404afb45f69169d28348ca20bb4f5693db19304d154f60a91ec4e9255be05739f5dc7e0b420d4bde4b188a8520bf39202f81dd3e2f4adcc6f4b4be16880103e0ab232f509729c91ddf0006d6a099a769b38affb89d7489b3bf261106aec362c77acdbb0a71c3da369067eb0f2ee9866a0bbdc4ee41ae81a88d860f1784565b7b1cdd350e8e12241103ff9d57c86c368775530773bafc058cbcea6309bd6d9c144cf6657cac5084ac5fe63ef038a71b3d79e6b7a32cc70039e182052f5cd5e415128e9ab1f553f13c165ea122d089975c1daf617766e12d9f3abb2501571eefde182b767e4b63568d37a8c553671adcee2ee4c7c6d77493e4599cd70d002a718fe0d7c31b7df3893f8b9993c90d7d55eea1c38292f1eae3a7887cfd182977403d5c029a42809f2c6fb8d04aff1c60106ba36367ecca0699866e5ec922ebaeffc4e624d0cc2c748f9c446da0c293d8ba7a28125145ce0936a2dd47172c4502ccf050145fc0584ad8608ee8f6c34c3e718fa5ca616722c5b3549ddb5e2f6a96e82c3d706bf255afda0272c199da51f9a4a869ce8b164694f6ef7593ce08b4bb0afda822eed4a0a7863f532fc0a22de9de5d3456574021b711c42eb1c9190de35ea592568f8ba5528c0f5fadc38e10b14a89a1e49fba9a76ca2478dcca20f8a3c78bb3e1b9869b7375d0deb87819ce7209ad4d73d84a92d08d23649bb50ecb4a1763050b7860afb055461b3158647b453d7977bddde0fac9415327e7eb2ea373fc8abd6793f576e72a47c92d6f6e19fadfdf2c6912365b74929d9b483c19f5146ac5a8dd943caf50b2e0a95fb19066a63a71862a540b2e41731ea66697094e51d309589ce9d25a37c06c9a12839c4c08a050a3ff9e502514f20d573c610466ac5399e11b0153954428f25d16958ab48614d34f768991f84411c401e6900fb0dfaab4108db0ad42fc9ae0a255e60fa4d92747ddda47d07de9f847e7a2be289798c5d34924aae419abdc41d30fb095c6ccabe5c5d5be73ec6197371ea74e08f0583b21901bd748db5348282cabaf57d883f5c55311f1304d7fcd30a9f0b22f810b1a7f089860e4ca0f23ddce9a23d7167762734b10b995d5bd2cf3b31f8f24b18d0a2f7ce1101d3a32d18988f162e91ac94b0f521f24fa287b0d2b97c408079336b89af9e842cf31886c701018ba98d5b0eb0e6d41b67b499f4c466cb1412db0e5937f7ffa83426c9234c713096444d0fc65d1b45f166e54d2a54bc103de110669fbc34555a6d16714ca37651e976b06a7ee96d80af9ff50162016a998451e2ce5819f3346b1fcdf6fe9ff3ec8420d4860a9980ce28fd8c55660983a3fb02cbedb5c638a49e5cdf0b69b71d78e071f1200608e235e6ed0ee8fea5567be12018bcd026412db0538c28bcd4a9afe799d5c677298646943c4200a039d2fced71d985d188f84dfd3132b6a015c50b8a60d712a97c89e0cd7d3a1740244c1522b117dad1220463f5d4af1004c1a2ad6b5708d7d6b28f8ae1e1e7dd1b2d3798b8c2e27a3559c7202aa268099eb3bbdf7c42d0d20b47e5623dba8e6aa1392ff532113c32bd836f4160abb287aefe648aaff6bb0a23928f580347046b64babf354790704538c6ce83f117ac7e83e1e0f54054466cc82b2144cf135be31f24f1b224e2a956827c303b0d82964e284b968c5ebe97688e49ca793a4aba81a3d36eefd8c12e3ce9409be63c3a308636a7b296b804d8125b4f29068ef44d3f2a3c9eb13e61d6365bb96d6973e88a70757b1d9213511d357d252df58d1e848d534d9517165263e803855e8caf387579f1ff0e7e9c3c8e532a2025d8016b70a45c24a546f0b21acf38d16b27eae6466e22396097090291184a7719beb4a55beb89275c6893e01f2075d3b73e165c39335d34a5aa7b280386e30a6df9ba917e1dc6774e2edaa0c87e8f5fcf89306a6fdbcf8cf52cf25f5df473fe350325d510421546765acd00b34ef53e56b01445deea042282e7d6ce20c8f967204c26bda9f2596fa378dc611091ab6db9e1e8d4e9b5c1cc4c4d6ee2ad82b32d08f8cb5a9dd9b03f7aa754f2738ddf2dc0c3318974ff3810765917c251c74ce3d7132c26b5f2ede12a6f62f2e8ddecd5e0d02f99f2ed8ac15641c586d68e093fbe80cefd6a7dbdac6d43e261160807eb82fc2aea870a22b25148d256a083325a5b97bcf0187f748b6c0a1691867344efdd53809fb9edea57669c33780a4aa9e65149937817d3d845d9fccae1876575d5383d06adeacd0f3371209a30e1a9c98446174b0b98560652d0643f120bdabd5484435871b42ad0ce36aa8330c7edd26e64e89eb84e0c72a2c6e49fb24088ae2bdaf7ef07af9bfe381dd6a9ed430a553de1bad4dcefd5239b389090925a69e44e25800d9fccda11ff4e1e4d3049386397f1145c3595ab5115255bc1c1eabb379a37504eda27b1a103b88ae8f174e1d182e3dfbb0b8317d05d6e08c191661b04537421fd84057a9ff5a6eceb68c5bf1f0e356df6e93d936bb6bdccb42127cba43e7615d522242df13f08e5fa162a641430c1431a7d7181dec65202fb618a690c2bf3361d7dc689d5e4a97a550a9b17c8a5ada8f32db3f774e9ed047c02eb7d1ba7add29fa07ab90f290e77bd91ee9b5208b1fb19a37f29dd1a492fa32156a7d43146a336fe6144d19228f975c54ab304565269124e069e864873c0eef23f2e7b012e84ad0c71d76e1b23b8b9a0a66edcd59f4b203a9773ce26baee206254b49efb10cc48bad814b2e299bd478fd4bd8b1ae2c8bd99070b259a9e204e42fc5f65f9e25cb4e4a1a3b67872314fcaeede2abbbc6978660c3e685f6dccb53160d1f7517bbda54177495c23fcf45cdd66363a70a84f2699e239b5071c9e6cb19069f3e0be9f4390c8028ae9960851e34ea18ff88d36ee826c0a4db4e33e94f0ec6651a728a1a2b0c15b30a1783ad4b1d224d87264779a817d107d40c75b77c25addd7b7d6a8b73b2d551f125daed95786920c4130d2061178604f9604a0e2f1c6cdbf3066fd28bf276ee0aee379bc049bc8eba361f4052bd2a698da312c991015c0fbc43ea1d2e72426279fc5181851a15a2f4883018ab01ff8745625f388f05f5fa9abc5d87a710a1227322626115b60f781f4ddd91e205c1cca582a5e37e005396703375846be4f36fdb76c277dc1a2ff1f183cbafc6db485a562f4d08262a207844a3d12261fa0ac479abca76f417df42b037e611b1b6acfda94d5dacc620c3edf5744db24bcc41ef1722dc0e620f8a35c50585a7cecfc97f05bfec21f919420e62a9c4f28ea9585cc056aee08ed8891d077a9647d9c0b5c3141f8c517f13b05bf0a18b99111d2d6e7b4892e78fab35d882e4e153060f0c44cb946d20ad0897a34d2a24d3800b54acd68fdd797aa362560dcede6d12909948bd6f4726a20142eec9c6b78d224b2c24885490bfb492217c6809e0628164579d2c2c16a90f28aa5393ad44c45d4e1500fccdcc684023d7cac4e2cca889333f048cd9a29de018e958d00553c77c74ab50d974df5f654233fb923e809ef6ceabe6a860386603003cc376e90b8bee74f2477343a5ae923aea4ffe99a91b9d9289ddcc3ca316b026b3d369aca474b7941588fc6e9cb062528b10f13b90dd55afd64f7b0ab79163163ce02aed379af25740ac5e37c5628c0b868b7ccfed0ae521c964846f0287d3006952539b2dffaf891bd01fe98a1685e71536d7f33ae85775d11545eb379e0916be616206968605e5033267f6f79cc651c2ce71a790ae5cef19fea7604e479c0793f82db1f8e85bec40d8c6a2dbc9bf76d02a616aced611ae1a7a3756d87dab2855ca585d0048e1e4222ed9d6fa24e3e13677256fbb9959b965727c192696a11474a7f6a6b6c8efb649b1f601c76576f36996ec7a20eee84208232c20e8502903d4e303e4ad7139c654b7e5d2aa262d75672cbb4f653e62ed8e4d28835f7d6d0efb3f39c40558d9cbf19f250681a5c8a59143fec80d6a69d8a265835d6562ef248fa4ac508bd60c9283f6e731baa786828d0f7a635e1d14a448383c8b0243570df4a42799afe03143c227e3fcf0b1393bdf8bacbd26f1041d5e3112c84755942fac77981fe16f048cd882243a8787b09bdc38847a5a9cc9aaf4d30544181ff014dca8b2892c00a933333df6d8ef79041483f2d8c6416897ae7897ca1da85e8f0a493be4520595cd0dd7d32c87999e703704ba0ac7d8b444dba807746123100e2cf7573843a0a755eebad6045d2970a0ef8c9adddff093e79731d5e506f1c43318fb25144ff5fb63041574e89216ebe0ac75d7dcffc35d095691723493c94dcc11d4480bf3fe7b76ba53cae5b409c002f2d1bb5eab08ac993054ec297543798700fe3e2877a4a0cce53599a66eb4f1fef5cafc774277f0e694ebd7f8748fb5140735282e5e0b9bb35b8aeb098775a33820c9b8decad3ad6ce36f79c347dcc2c60a5442d2eab4368827acae1f0ccd52f0475fab95ac57c3c9d7c2649d355756140d5a1e8c6eab8b67a5c169cb899230c4be1dc702323f2b07ee1fcf5657361e250ccbe93bb403abd857eee4335e454e8485a3b055c908c957dca3f9a288299729216103089910386fb994285602ce12b04be1819a2c80394b2410767d9aabdb591e4c4dcd08d1d5bc1bcb532496ff1fc968ac3ff59bc7266d8ecbb67f34b681331685a99b781c9752dfe83d145bd4f3c8ec634f028e850e246aa81f1d03aef40d000000000000000000000000000000000000000000000000000000000000010cf90109b853f851a0bf32b9037b600aae3ecd3dd1838bc9f18ae1661f615cf3d70bc270b6c31f55fb80808080808080a0a2381991afea644ece5cba0d8d69f838f7b123d2e0057a54509e0c61e8b293028080808080808080b8b2f8b030b8adf8ab8301edbf808303d09094000077770000000000000000000000000000000180b844a0ca2d080000000000000000000000000000000000000000000000000000000000320266d6b1b655f66cf8f99d35432492f8fbedfa97a2a48f0efaae65de6738e2594aa5830518dca079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a05f3b41e975b46e86d5365943cfe25ae960fc2c7c1bb4eb0025eac5eb0bc6639c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ebf901e8b853f851a0529f2d89256fc038782a4d70b40bf127de906cbe211e7acaa3e928e0fd5cf11d80808080808080a0b4f4d0be01c65da5308bab41d52d8a7c93a1693c170c44d1f619b8364d40e3428080808080808080b90190f9018d30b90189f901860183039445b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001000000000000000000000000000000000000000000800000000000000000000000000000000000200000000000000000000000000000000000000001000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000f87cf87a940000777700000000000000000000000000000001f842a058313b60ec6c5bfc381e52f0de3ede0faac3cdffea26f7d6bcc3d09b61018691a00000000000000000000000000000000000000000000000000000000000320266a0d6b1b655f66cf8f99d35432492f8fbedfa97a2a48f0efaae65de6738e2594aa500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000adf8ab8301edbf808303d09094000077770000000000000000000000000000000180b844a0ca2d080000000000000000000000000000000000000000000000000000000000320266d6b1b655f66cf8f99d35432492f8fbedfa97a2a48f0efaae65de6738e2594aa5830518dca079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a05f3b41e975b46e86d5365943cfe25ae960fc2c7c1bb4eb0025eac5eb0bc6639c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000189f901860183039445b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000001000000000000000000000000000000000000000000800000000000000000000000000000000000200000000000000000000000000000000000000001000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000f87cf87a940000777700000000000000000000000000000001f842a058313b60ec6c5bfc381e52f0de3ede0faac3cdffea26f7d6bcc3d09b61018691a00000000000000000000000000000000000000000000000000000000000320266a0d6b1b655f66cf8f99d35432492f8fbedfa97a2a48f0efaae65de6738e2594aa50000000000000000000000000000000000000000000000c080a0ae5e67673b90f2d6802e8dba26aadb2e8b81e059d1611afd1908e743e3c0b75da004886b0ac3a810519aa2395bffdd94fbcfe4a2de989ec95d1aea0fcd09afd931b9235302f9234f83aa36a7830137d664748315f42594ac9251ee97ed8bef31706354310c6b020c35d87b80b922e48ed7b3be000000000000000000000000000000000000000000000000000000000001edc10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000001fe000000000000000000000000000000000000000000000000000000000000020c00000000000000000000000000000000000000000000000000000000000001f60000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000002200000000000000000000000009d69394bd71906a235f9113cc04321f573958d3e00000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001edc10000000000000000000000000000000000000000000000000000000000320267dbfbf2c535ffc52117d4cc616b8d97bd07cdd8585ab67d9095c067e9de6d674400000000000000000000000000007777000000000000000000000000000000010012f20d5ba20a09e185d452c999c129d712b83c75480e2e029fc895986d361a781b2045b8b5226f9c1fd712d8b1a5f1faca84f5fcee87a7d1dd2b57f55617df000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000004f9456000000000000000000000000000000000000000000000000000000006436f8e400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d65822107fcfd520000000000000000000000000000000000000000000000000000000000000000bbe20eedcc0216c615d3a0550a5507bdb2f9912eba7b608300486e871a4e42491dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934700000000000000000000000000007777000000000000000000000000000000014852ab81d236f35c396d4836a6f82239f5672a4b6136ab9ebdd8669a9f9e831b87a26944e5c04f16b79426135ac11b155922c14178bf3d1ecbb1fb12ccc8119a22df5003de2d5956c745f9e825a8f0ca1bb1e265d4d431781b00765e0fe37280000000000004a00000000000800000020400004002001000000000000000010000000002800000000000100009000000000000a000000050000010004020000000000000000412000008002900000000000000000000000000000000820000000000000002000000400000000000080000000000000800000000001000040c0400000000000000010000000001400000000081000001800800008280000000001200002000000000000008440000000000001000000000004000000000000200200040028000000000000000000200000000000000000010000000020200290004100000000000000902080400010000001000000008000000000020000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001edc100000000000000000000000000000000000000000000000000000000005364e600000000000000000000000000000000000000000000000000000000004456ed000000000000000000000000000000000000000000000000000000006436f8e400000000000000000000000000000000000000000000000000000000000002e0781b2045b8b5226f9c1fd712d8b1a5f1faca84f5fcee87a7d1dd2b57f55617df0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000016202bf20ff78727f38ef16e03bfb3d4895f35cc626f97ede7cc99f48aeff8661fe32015ea8d62ec7a79e01cd398e85867bafdcf55cb6a7121b6fef097f5f5656a5d11ddf336b6879926ea2ae425e91c748a553c9a496cbe2ab556a91689f75ee2b01ad3c43aa774b50a9d8411a9f65be42d6cde781db1a1949a1e886f868917997b21ad05b7c1eb0d208d17426c52831c6347a8db75b12bfeb2970c4dc6666e4eba0492d2ec318089b11ee7ec6087ab6a3df335770526cc0c1679b764d847b4ec1e303d400c12e690aa26a3771e5676e7ac95e2dc7a1b33be698f077c598f880d4203defa26ad36b84573e923af347475c7c7671be245e9859ca1db3c047faeee4b1c0e81d8a92915c2b94ff300e18f77f70ffec15631161e0bc3cdc9143c43422c208187652c1ec83c5d282e10587216eaf56689e5fe236f72c13eb9574afabc622a739cefbbe11aaa4e2e3d4c5415818914fe554a07be374f565d9bcebc0134940e8921b87bd4f6b42a6432e6e176be5ec82bb8eb6bdb7e4acc1f1e99725bd3ab2e3fa52e02c2741dfe6eddf5a3846dfd57f6a72e834faa048cb007826a293d9e163d47f9ea635871b25afcc3561dfce77b3a2604b3c8de90aa24916f41aed62d2e0c0d18f9c259bf614f1321c5b7cf7b5bd73cec408dd85f046bf36302e20f3603b7832071796022e893386de4e3b170135a591b1a44117240ba85876dba586b1f31c13d11b94f892bb9f96bd2931b66ffa5e22b104c549e7c0d5010e4e70e271d48c0bd6e4be68c920ea77af85d12eb155d9b25703eabbd0ede1909565a55f12f7e30e74b0329222f6067cad3b4324a80f570506985d729f7780955333f40e615f065023fb607d975d7a2b9f234137e72260d8f6b586baecf42819f8328dfb3304441f2c9e97d1fab9a3625073ac3d2bff6ba2f8d659cbc6f66e8d9afde1ef229ff39bac1ecd65eddc4953e2726a72daefa76f00d58e11c9a9ba3448fbe0d3a03db78d70ed9c574ddc45de5c73efdf3113ee70a4b42cea9884f85c1b995516912800abeb70f3022d5de6d9f49469161a36a6a309099ca43e388908635ed4ae825a14b7cf5213454a1f345497008ed417e5d33ef84c4934368b36f27606072192a1b43396f89647f0541dd25f55b42c5295d3ab2a22355664608b8dfec3c9d76045b27d8c2bdba7f376a44826bbf4044aed0d57068489fd32a2bf52f8613aa150185aafe655d2b86bf8867a6f7728c4133fb95776545b19767a0d7144f60f5ef038eac390d1cac6f9882211d7302137efc82b93b8f9c55db629f47a2c61931c21d01d5ad967c9dc6c1abfd496a74df2ac4714cfb027bc4d8c0153543ca663ded2af64f7396ed3b2ebd1976386814e94b7f7fcc3a19a4dd876288b905c381bc8f008de145083d6404890a863e1af1dd897aeef2516b20df50befb6c708c9728a22cb31d80b0e953aa71230d2462bb0668dd8701e11bc5240d85184f9298e2c5a3257b5dcc3e138df8b7d4162d6253fb5c21a65e952600c8764c613c6f43d22c861d4380cd688c286e9ffad6bb8582421fcab96b075769cf48b3160f056dfac4041b08287533a769bed0f08fdee9a16c5c8f414eb35830793c7b64341fef79dbc529a7b99f85d4e2e88b64954be967c5ee6386f9131b80b454ce70209f78f2101d0ca71da273735bcbcdc5ea5d3d54b607820b9bc852abb1b733cb7bb5018276d30c4c0a7f9ffcd318499a2041043494b82456ca8ac6f07678a8b770329b7c00f31e70e97ce48bc796570be27577e8986ee4c7fa51da44bdecfddfcf18686cbddc02ca206d9132d451ab55cce8069f631412ad2ae02b1a8245d31c0a65854d07370259f632fe253b2412c5a785148248d660d7cb6bef5240749d6ac4a4ac59384b27e7019c6cae15ef7c82e5a952f4da079b6205f9e16f3d3c84e94b490530c5b602d4bf5e9d34f2a785cdb7f7755d6d467a9d88071bbdf8c79195730db7d0b7872cbdcdabab02bd4b8487b726c5ce6492344ae7e900a21893e7b840b46380ba99278ce95322dc23daa97995d1149d425952913428c8ef8659dd2cc2895f12b08e0532a254fd5674fcac1b0992472ef75337d8d77f6fef3720d4b7b17302478c7d2e3b8dec7af4c681aba5e25d8aa3f4382b0082066c3f7a0b4e42c4637df90d9a1e2f3fd1cffa7e0d5577f5da89353521ed02cb1c39eb5746cef10ceb74c3fdba13199b42516ebfe29af40da64ad81b46b7bf04bf25994255c7a51f6839848810025bb52fe7500cf1ef628a07747894e3b73d53e6b2997d0654f1ffd0c070455400fd7e9d670984ac807a0f8131977ed1806fd3c0927c34b7b4dabf011d31e86b1b7932b70e7b068a2656173d241e8f20bb6be3a3a3767111aa6f459f84be961c2337f6e03ed3cc6c847a3683894288b471504cbdc43a78f856801a10a87c77322e36e0ca426ec67ad3a2a3b79bc5cb81928a79a67a0fb46bb967cbab73fd36022f92d920204de61717dde6a85b7bcf57584c11ce54ac92998f856bf042a01c5020d266b1ccea774955484405f58ad161251d879a87c43d5dbaecd976ac5d04dd2586d70031a86b0dcade14028f36a04508494c7a20e98b3b21f7765e7b3ef68f10960709e63eea35a26ff47424e18df8cc271ff3049262c855d6a131695a395f2ba2f1b039012ac8a2abdf6d9f6b0c432f0ae78b9bccb99f89759434477257ce1f44cc61e95b9c9843ec8efb17c640fc4c837ec125fb25323d3f0644615d21721607fee4d68e2dc9bd29f5b13fafe39b0710d0365dccda35e3c937aed1b6949b2a0a7523011eb706357b85e174376ea7cadbd01ed0dd1bc6a8e5a5a11bc6131f0661dd6365b13c6e2de50b98cba1cde58a921d19936c711424eb625b7c35cba01a0f7dfa8d6f86a2a02425ab48e2c28f8f2f61adbb744c221b9c4f35b16c749c227bcee1202e87537c7441f421c855ce87d858a679f09dcf814bfa1f26f7d9ce18f723d2f84d4b25ec60adbb6367e92270836d03c71ed43413767342a4fb8d6801b8755bf65e7947ed4459ad6486fc1cca1f1cc89df3d307f01d8ac68aa1d08d18aa35a46bf245589c599eddc6337e764c36426f7b7f5d2afde0a76fd3aa536d1a165f9f23cfc65866f574f2289aa5be056dd32c72a204ba8328dd9b0b4643790463484d31623127c09c6cec446a9ac9a53cb6841ca2a097ceef88e537e209880ffdcfd5033bc3f5a885c271e41ee332366345fa867780beb3c1d5eaa496ea09160db3fa7477a2fff436ecee95aa2d51ff42ca9d4fcf021b6e501410fd41098a1a8f6021636ece98c27bd74740b7280d3a5e13d9850fcf7f2118c4c91572ba5826fcc4b0837d0b394f6683cba38fa35a5e2bd242041533bd25939cc873d1f5852a2f57cb172eb17c2e3c351240a0b2b334978b90ac18041b09aead26649b1c1c019e41731e77c6b2211d7da94630507bad027561dc625b7e84094378e599a57b09eb32c2a67cf5f2f0bf9250e6da07b165f97dca10517e9f3fe3561d02ec83a722b544bd6e25ef27d9825d13651443c4d984d7e5d0fd70c2a7f983b3ae8c698d27a2a0bf2d35655f477adc99c56f48773922831746f8af58de941a020986ad7c23fb7d31c2f17f305174db26b40447e64c66216dce98e7a8316dd91dee468e602206a4d1d18fa7827f733037fa87dfc9c74c9df0960867087c776382b94db9420a19e5338e17e8a68cb7621f0b56984610bedd3d9b77dc5447cdb129ecc33596079cf206e93904368cae07f0d449e2095f8abd95f26603d2db047647babc8342200be0095aa5489fd18cd00a52f59b70ff04c4b1e572db76d08bad419abbabb00b9e485e3f017807c12b427b5e0e648cf7b16065e313c1c073ce354a5fc6812c02b8d4b6aa1168c575dad9875087fe9f61702309febfb99b895387cc1104c35e123b713019b5e51c320fc2521cdb5cfca20f617773fd46d3872128b87df6f66a21fb3fa16711245ab65eef629c5e6073efaff5b707657f4442f2eb2637fa71000f14fc691a71aacf902c0c1a1a5d7d8d351b8b3cad57acd0a9e47a1abdcaf2b70aed8b7370a6bb2bb4f3d679c4f9793e4b256deefaef1e6dbcdbb648b917e34822d833d2ac1614aebcf360d328d9271f27c52c93de4a9455ce6cd8d2140ebf6b21c9b172cf47556efc5dff9afb913e328a708292bfb65c96d668f4d0b3a9a21b222039156cba9980d6bf11efbd8dd893378e5dc1b323c57d8f702076c22d125d1489bab2553c5521631c35f7b5236007ce8f37012cace78d6eb39718904b5dc31ddcb6f4f175e52bcf6c6008f6f5a572925600194b9af7ae074dbf85119e3afd141b2ff2652a58f043e97f11b77997a9da1c96c18b5254a107f24e997a3ea61c2069b9d04d49bd1bcd2495b19bc71848f28bfb4f0346b682a1b474e040b056e60a32b5e8aa532103101cb45ca41c6a690c8688523b8566d507f29eb44fe2d2490e81f4343ca61c8783b83e40e3ce66532f186e9d09bd2667cf974a763072a910121aa5e86e151d92a868508b680f795bc30b4502769f41e3afef5f321be9ce2f1cff3eb3308d65aa0ed780cc889f605f35eb5e02ba772d08db2579f8561c61fa09a8e23ea1416fb95ca0c7e139ddd16f04b0c872499e44cb5a03868d6c5fa1300c19a96b8586b8f33bd760c6350713696b7d3236acb0eb35bde2e6378e9ef9b117b02290ead7824d42452e332f6ec95a7f871da9ebdf6ad02c959a1a36ba33ff0089a4f5217b7bfa5379a507b1e994fb7b8fef489f1f2cf6fdedf0e530635ef31faaa1a37457c445836376dc5cdefc7770fbbad8c326955655efe4ecde89bd2f1dc62a2551a45206fd7d42605aa1c0fc80476b741bd7df1f0f2db0fc387614240e78427bb3a8cbbaf9bb112da06ea6942335f88c65d42d17816136509ec39b51079b5eb2a8cd15c3d1fbc56dd72c3499c101e2fc9126e8f194c6c8006faef30917c5e535439c6b0d78be52a4d17a3a25d0878649b668db027eecbbafcfac7a612138c77d1511f9cc5e763eaddbad6d9d8770705ef7b4d062b4c6dc72f30d1d272dca8700ae03a4c6d2cc6a0a03f9bfb2615b2b294515ca80827ec9cbaa7746112530f5e70f236a641c05bbc8647dd130f02db3561f9dfaa1d687235bccb0498202af478a6070dfa49df99785a61eb5fe5f18777569c18b08d2042ae8639abbc225b832a2fbcd95ff43a3fee4fb2962983af8304ef995716110a7ad35c538697c109c01c427ca6cefef3a842fcf74b1c49a3f2da88b85fdb1d05e20cd567538942fa2f0ffbb5d2ff73d60d562d9a0a6894bec3d85a709b43e42ab64e2306cb96919e078b899f3155af56390d06ddc662afe8d2c91fc091e2c5cbbfab3fdb3f49423a5a5f7741f2d70c6736adc66e7c2caa89c6bbc678bb4b445a8a63d120867f01f164dc87adc853633ca7bd4b9d585c2a637d1469da612b5210476fc8d66f90029bdbf7fa5eddc8335cd23deb4bb47e1582e64a03dd021292d34435419af80af178cdfab0fb9374fa0fade48108cd3a571b814231784ac37c9f6071fc6ac0bb018595c9d8afbfcd6f31832b2581f7f7ce7c45d22817aab8ac6df0e0995e12dbd1595c3377b707b816c96ceb1893b9e7c747a577bb7540b89eb3ff7cac878a7a121a37b38fcd3248abfd24b50e25948dcaeff8c1c7ab8b745a93adb87cd54fca223dd940ef4d7eca9dd69243c74ea128ed624e52c7a2257f3950d0c7409d665d912495f8a8a2cf2482c1d51cd7793d3d31f32ffc24374d8606daa2a423931d97019ba2fd3ba773645b7fd01cf75e8201dd29f694a72136b585d940bff8867654223c28d0603d85fe4472d93ee30e35f46e27b8f40f9a9ad03992d9ff23305fc062c7d95971baae1ab074df88d41e09ec9752efff012c482e0cf9aea2b78cc26db146a278d584575ed615f5d168e6df7a832322da093f0aea706cee594207427d3005fd910843f3dc54b14f8b187e3b495b7474792743fc2e43f62bbc7fd50a76513f1fa4073b15a42d1e78a708134238f2521c749d086deeef512823b514aa64122b365efd51e11415de40826971c234d571c3e2a0507226c6ccc540e43a9aa32244b29784ac824c20d3d1b72dc7262f61cce4eefbe9a4ea4cb1061e4a71925aa13f31d6ce80bb7c56bf47b91cf107ab17168dd4fb60614757d7c7f4ebe0320692235fb502621ed9b15b9b3fa23aa1bf266a2a2c3f2386b52625e42e0cd85c37319e3266185419bcf6dea997e52ec8fca5887a68530002fcc5b3619e88d4dc9a918cc36bac2416ffa9b9734ac4e67a93a800f36d7aba4ecfed8d65f62cf6ad13d184a8c6406e3ba17b8aee6af0721ed091e1d225d044629a4ef5153c294a3e87e243e03bdcf6eaf7ee56d9d969a1f054d5774a7e2c363b160386b909c89717aa7015385f4ab8b6c97805c12c37d981ca945134cb1306d39a4d136b42c36d8aacd2c37575a11b17fa50ede8072d667f64bb55e3b54aff2c3c61782e442e088db7c1ce62287477132bef00c17e9992dd42f35b5e098eb97724fc4e697d75812635203abe8f96000d9553012be065980fb16d6d1c0c80457585c6eb699b0e8a6e36c1cd518dd1ffc517afcb9114a4ff629d06cd2f0be1495c4ee09243e96529e6c3a228c923ca2a703930ea94f7a5803645324ba9ea1a08e6c3241fe57a80bd24f780566342561189baed15e85ba9257b701d651754ff534e51279961ff379974e34010d80773b169a140e0ee7c5e2c0312c9dee46fb7b309710d448a43805c7eab513e84e346411b7145f77ff4ced7b32eb641528f78d88af0fe88e0840e9c16f2210e18c1da605bb04a4c963441c06fa839f722b0c67345168bc0fbb1c826f20472c7551a1327eae9eddbc24e63814fb81320cbc6f03488d64587f3e5f53c03db02cb15412e622f9ec9944643d4b5530b0cd4d577489d8ee499ecf2b74fb72423412aca8530fe53c3fc584ed8e39f900843ac73e36fb113c343cc197cd689a09e12f29203c1dfe839630f6932f3a29de81ba787f6044e70dff8981b71fe82f8a4d01f45770a53b090026a003b3e639eca0e6a1e5bdd0aad456e89d83012ea1f53e1a5fe848b33528f7195a7b0c36d4315f1b96b62d5603e87a13e12a97ec335e3922d4339d9575cb26d5691da78a738aa5c84aecc22a93033a6912f84360d13e2e23b0185bdc2cd331bd26ababcc91894935db5c7e1800b8a10db884a7614ceea91f38bbf623c5e7e7238eef06cd9fc9e43507c56e8d6212b7d03ef2db0dfceb040c0b206e1b7eee6ae564b15e4c02e9c3e4179d78bc68a9fbc2166cb8458342f218dc631705602b2ef1c6716dbc08f30810c9e2ab3ac7a03e300e9c21cd2a0240025ed5eda13e6daa246241669acfae65302dbca5c579d3b5c3a4c16a976209e22845337f9ca033329f849f3ccebc69ff01b301d99dbe9e79058fade67bf881c70283f41eaca130d1423e733ccd520f26ebbe8d304cbb8fa2f4bf67e2e041e5e90e840d5510d33a9f700219fbead699901ea3b3f8aa3d5ff0c028ceee5b5e711c29e7740bc98f4b78f15f2aa1e01449f1f15e68023861f540d2ae0541273c641914ea0e6abadbb2f11618bb678c8b7abff1f6d4e9f789706cdbd8dcc1acd4bbd506e42e928d134366d3f32d8caa4b86736bb065b1a3f89354835b7ba5ae1e53cc1bd9f5dfa3e0d49c0a0a8d32670c382712e30f8f4cb8fc980785fb6012df752e02c923d3f56f5764a41629646f9fd7641c8365f0917f85a64d0ba36179e2c2b3045d7b3c6ccfdb60cd5c365c43d88e231465c6616f7d2cab0db88cd79268e5ba0cecb98875958ee3827af7842e35d9cc89c3776e5640f2433a6afccf0e6fff9321e31802746639bf2bf77f375dd6799baa184b48815f24d3fca5d534dfe61d1306d15e97d3a320457ddd2239cc52fb31dbf98709cf090ae59afabbda6da75f4e1373a28bcadc2405e0a7f6dbf9a3e26511fc600a496b4623593213283a1fd33f000000000000000000000000000000000000000000000000000000000000010cf90109b853f851a04dd5a916917c46969db2e2093e73972daa52d5582e183eb0bd08362e7aca1dc280808080808080a03605d0d2c4765be29883abb71f1c4b162f9d6786835ccabb068a243ff819909f8080808080808080b8b2f8b030b8adf8ab8301edc0808303d09094000077770000000000000000000000000000000180b844a0ca2d080000000000000000000000000000000000000000000000000000000000320267dbfbf2c535ffc52117d4cc616b8d97bd07cdd8585ab67d9095c067e9de6d6744830518dba079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a05a4ba290d849b719839872aa1e6999ee672fff37d450956de85fe07c96f172d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ebf901e8b853f851a087eef6c6fab228bc280138441d870592a3910f042806b16f257faf5f1542f9a280808080808080a00ac60a3a5bafa4560edb7bd978a6b8980fa818c5edea7c010986328de4d9b4ba8080808080808080b90190f9018d30b90189f901860183039445b9010000000000000400000000000000000000040000000000000000000000000000000000000000000000000000000100000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000080000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000f87cf87a940000777700000000000000000000000000000001f842a058313b60ec6c5bfc381e52f0de3ede0faac3cdffea26f7d6bcc3d09b61018691a00000000000000000000000000000000000000000000000000000000000320267a0dbfbf2c535ffc52117d4cc616b8d97bd07cdd8585ab67d9095c067e9de6d674400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000adf8ab8301edc0808303d09094000077770000000000000000000000000000000180b844a0ca2d080000000000000000000000000000000000000000000000000000000000320267dbfbf2c535ffc52117d4cc616b8d97bd07cdd8585ab67d9095c067e9de6d6744830518dba079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798a05a4ba290d849b719839872aa1e6999ee672fff37d450956de85fe07c96f172d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000189f901860183039445b9010000000000000400000000000000000000040000000000000000000000000000000000000000000000000000000100000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000080000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000f87cf87a940000777700000000000000000000000000000001f842a058313b60ec6c5bfc381e52f0de3ede0faac3cdffea26f7d6bcc3d09b61018691a00000000000000000000000000000000000000000000000000000000000320267a0dbfbf2c535ffc52117d4cc616b8d97bd07cdd8585ab67d9095c067e9de6d67440000000000000000000000000000000000000000000000c080a0d86a71e8e531bae3b2a2e70d98e516ccf31b6583d936ffa31c3772ac265db828a0420f5a8067c7eec5214117647da149eaa4e7c78a10d8ee6fa62001ee1b680f9fb9060002f905fc83aa36a7823d3f647482a9c494bac000000000000000000000000000000000000380b905930001536cb8da3dd105e94414690798c7f100000000057b78da8ccffb3bd38b03c0f12199bb964b426dd6b091efd7dc3ad1a9d321d1713b2ea1189d39280b4791c5c858729090c3b6182ac75951eef74b38191686b35c4669656ca9dc5a0ce7e9399f7efffc03afe7fd6e7485887f6264e97e9856a6978b65c5db3b4ce57cf4812abeba0de10d0d6ee5a2cbc9885a2163a58d1895524adbfd86d795eac74ec74d783b599861bf4b7b3e6daf70b3ae0e5740c88a4dc15b893f76fe074a718bcead52fb2a06d6e5f1cf3ca344ad05dcf5ca10bd9bc2809cd8ecd40a2dd0e03200dadd8f921f0e9953a7e6d8c7dc99e60cf6fe81465175e0cf99b702ac6a13706e64ac349a1119796eb0b6e7d5ae48ad74a5c997d679ef9c637c619587cb98ecf88e620dacdc57701500c74e087533f978831a78bf3857cb6044a8c66e41645cdee74ac7cdac69a8484083eb003827ccfd6b92c77b7097a15f38a419f6f0578f3568465e6fb639f1a8d6e52e9d17a0413100ca8d08b210a2e5adb2bead3dfaada14b2513113802f3996daccac89014dafd1368700300053ad7daeea2a4d4d9e8502aa44337c6ff91165a25de84fe5273b2e5b7f4dda3a0410900125e7778d5c2a59a2ca2ce36bacc9e95812ae1b69a478fc7ecf5ded14b68a80a010d6e03e07137d5de8082773f8a422390cd0a592d81e6e623a42bc69547e6b343e1d9a14e64ac3486116e29a8315486a2324d93d3e33a8344ffdbc2655b76dbf72077e43c13961a6a52f0565f2000881576c7a113e7aa6e9a6ed4679014533f8d1bf80ff44ae5599813e80d2c1f2fd0a03400864952137916724a4504bb118ccaf9236f217a1e43c97e471397a3f86672226dd0e02e00d4dcbfe4dd250a97d0c830b3d93213fd048fed38ea8378018c726be68728e22c687037000e3bb6d2858fba82db877c2e28fa1e2cca4ce57b6bdfdba7513dcd2649da93544083d06f85c8f4d21559e8e7651dcaa0c3aafc4a691fdfb27f2f39ea08ea62feff43cf0d80061500b0b00cb246f3641d83f5c934c477ca641a5c545da8aa0e4662c4c5f26ee70525a04125006cf268fbdcaddb151168bf24d3fa2e09f7445d859ff9e5ba2fe71e7ef8861ba61834a80280ebddf1bc99e8d00ae5d2a0893d64774d4cea1bad7146fc964526b6c4617cd70a68500d00f7e8131b976b9537ab4e2b9c9cf086fcfd82e235cf6c6eabbf8030cc3fd1e395071a840120bfbd7fd4a54397eca0c0f7adc1231dd539950f508f92e237e3aeb91468c38d4083ea0068a89abd38178e2e9f67559758419b6908d48d58967547c9edfe98ba016e050734a809807957936c079272b238748593ee3a73f5c7647d0ece20a5c208769c484474aa2f192b6dcc780a770c9b40b42348219a34a746cb495f3f1efb710a816ac142121461c6f7bf82fb00b0dec5bfbcaa2e32983075c84989e439154bfc7df1d0549680a6c1a4999c18aa010dee074028fcade2995b7daec4562449ccbced0caf7a660f49ac4ea07d485b22348948a0415d001ce8e16f70ca5813141f7f7544586da1364d2f77dd8fbb7cc937c6d46136f93d68f000009a72d59e5a9bdf1de5e60bbb17358bc65e8ff1566fabad6d6eb42ef2781f6d6d40837000bce21c64847942319b4ac1c92b2ee02fe2bfbf43b685908b92a0c3cd25f21641a0417d0084138599419cf73489312bda0d53e1fa748e1f7927380961470ec9fda73b36978c953661c8065aaafe09fb847fb54e35b3c68f771b6953941b2b4e619b486d81761ee187bf828700301cd34529763c60738c12e1ccce6ddff8b8338cda8fda245e5d8d5613d20734408306df96bd65c7b8d5c27299269dd9335ef7cb1f3357145983f365ec2f933686fc6d77d0a01100ca3a3773d3f0a52559ee691776b714fedc8c7b2cd672c7065c295693d0616d37408318007c18e9a9f6e4929e20d8efd4c2428065720ed1938af8e5348c14b373b0a845d1063468d2f96f000000ffff86f9aa5001c001a08f785a1c8e4c549c415dd948da80f86e3aaabc4e7a784604b6362208e0fb6b85a011d366d57b6ad95cda2eb6b618704859b4d433ad7557cad177eff6f6bae578cbc0f90200df8345de7e8203e494e276bc378a527a8792b353cdca5b5e53263dfb9e82168cdf8345de7f8203e594e276bc378a527a8792b353cdca5b5e53263dfb9e82168cdf8345de8082062294388ea662ef2c223ec0b047d41bf3c0f362142ad58212cadf8345de8182062394388ea662ef2c223ec0b047d41bf3c0f362142ad58212cadf8345de828201949425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b8212cadf8345de838201979425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b8212cadf8345de848201999425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b8212cadf8345de8582019a9425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b8212cadf8345de8682019b9425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b8212cadf8345de8782019e9425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b820f08df8345de888201a29425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b820f08df8345de898201a59425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b820f08df8345de8a8201a89425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b820f08df8345de8b8201a99425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b820f08df8345de8c8201aa9425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b820f08df8345de8d8201ac9425c4a76e7d118705e7ea2e9b7d8c59930d8acd3b820f08"
}
```
---
## `debug_getRawHeader`
Returns the [RLP encoding](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/) of the header of specified block.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of the
string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- RLP-encoded block header or `error`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_getRawHeader",
"params": [
"0x32026E"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_getRawHeader",
"params": [
"0x32026E"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0xf90236a09f73691f6dabca4f0a99b05d0a701995506aa311dcaa9ce9833d6f4ca474c162a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794c6e2459991bfe27cca6d86722f35da23a1e4cb97a078103ea8c47231886481d72ec1afae6eeb06c3773ce24a91323d5c9eed69d4cca0008992da2531db404f07b0871dd620a94ba346963e1b1c6dc7b00748e8593a1ea0b6c3890d9604434fc52f722848c84d1770add20cd75bbc28cdedff42940dbb56b90100200800000400000002000e0000000401000000440100000000c0400600000002000801000000040480020840048000000000400000000000000020004220000011002000000000000204000800000010010002000002000000000040a000000000000400020000010885000000000808000000008800001004002010020300005000000010002110410402000000000000000890000008000000000000000000020040000002000000000000810400000040006000004000004080020000000000000022001000000000000840400000000220250000000000080402000420000418000000000000000400040000004080040010200000000000108020020000808332026e8401c9c380833e3c3c846436f93899d883010b05846765746888676f312e32302e32856c696e7578a0112d8f15793e7df7f8dcdb21c891cff78c0d1839cb5b6dcd06116cdbb99536ae88000000000000000008a0cdb97712af6685bb9650d21d609525913293c48adda7c45990926daada335c9b"
}
```
---
## `debug_getRawReceipts`
Returns the [RLP encoding](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/)
of the transaction receipts of the specified block.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of the
string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- Array of RLP-encoded transaction receipts.
- `blockHash`: _data, 32 bytes_ - Hash of block containing this transaction.
- `blockNumber`: _quantity_ - Block number of block containing this transaction.
- `blockTimestamp`: _quantity_ - Hex-encoded unix timestamp (in seconds) of the block that includes this transaction.
- `contractAddress`: _data, 20 bytes_ - Contract address created, if contract creation transaction, otherwise, `null`. A failed contract creation transaction still produces a contract address value.
- `cumulativeGasUsed`: _quantity_ - Total amount of gas used by previous transactions in the block and this transaction.
- `effectiveGasPrice`: _quantity_ - The [actual value per gas deducted](../../../concepts/transactions/types.md#eip1559-transactions) from the sender's account.
- `from`: _data, 20 bytes_ - Address of the sender.
- `gasUsed`: _quantity_ - Amount of gas used by this specific transaction.
- `logs`: _array_ - Array of log objects generated by this transaction.
- `removed`: _tag_ - `true` if log removed because of a chain reorganization. `false` if a valid log.
- `logIndex`: _quantity, integer_ - Log index position in the block. `null` when log is pending.
- `transactionIndex`: _quantity, integer_ - Index position of the starting transaction for the log. `null` when log is pending.
- `transactionHash`: _data, 32 bytes_ - Hash of the starting transaction for the log. `null` when log is pending.
- `blockHash`: _data, 32 bytes_ - Hash of the block that includes the log. `null` when log is pending.
- `blockNumber`: _quantity_ - Number of block that includes the log. `null` when log is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded unix timestamp (in seconds) of the block that includes the log.
- `address`: _data, 20 bytes_ - Address the log originated from.
- `data`: _data_ - Non-indexed arguments of the log.
- `topics`: _array of data, 32 bytes each_ - [Event signature hash](../../../concepts/events-and-logs.md#event-signature-hash) and 0 to 3 [indexed log arguments](../../../concepts/events-and-logs.md#event-parameters).
- `logsBloom`: _data, 256 bytes_ - Bloom filter for light clients to quickly retrieve related logs.
- `status`: _quantity_ - Either `0x0` (failure), `0x1` (success), or `0x2` (invalid).
- `to`: _data, 20 bytes_ - Address of the receiver, if sending ether, otherwise, null.
- `transactionHash`: _data, 32 bytes_ - Hash of the transaction.
- `transactionIndex`: _quantity, integer_ - Index position of transaction in the block.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `revertReason`: _string_ - ABI-encoded string that displays the [reason for reverting the transaction](../../../../private-networks/how-to/send-transactions/revert-reason.md). Only available if revert reason is [enabled](../../options.md#revert-reason-enabled).
- `type`: _quantity_ - Transaction type, `0x00` for legacy transactions, `0x01` for access list types, `0x02` for dynamic fees, and `0x03` for blob transactions.
- `root`: _data, 32 bytes_ - Pre-Byzantium transactions return this field instead of `status`. Post-transaction state root.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_getRawReceipts",
"params": [
"0x32026E"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_getRawReceipts",
"params": [
"0x32026E"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0xf901a60182c70eb9010000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000002000000000000000000000008000000000000000000000000000000000040000000001000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000002000000000100000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000020000000000000000f89df89b947753cfad258efbc52a9a1452e42ffbce9be486cbf863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000828d0386c1122e565f07dd28c7d1340ed5b3315a000000000000000000000000021849e99c31e3113a489d7eb0fd4d8c0edbe47afa00000000000000000000000000000000000000000000000000000000029b92700",
"0xf901a70183018e1cb9010000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000002000000000000000000000008000000000000000000000000000000000040000000001000000000000000000000000000000000000000000000000010000000000000000000000000000000008000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000002000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000020000000000000000f89df89b947753cfad258efbc52a9a1452e42ffbce9be486cbf863a0ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa00000000000000000000000000828d0386c1122e565f07dd28c7d1340ed5b3315a000000000000000000000000069cda9d6cc6ce05982d0b4fdf9480f2991f39b5aa00000000000000000000000000000000000000000000000000000000029b92700"
]
}
```
---
## `debug_getRawTransaction`
Returns the [RLP encoding](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/)
of the specified transaction.
### Parameters
- `transaction`: _string_ - 32-byte transaction hash.
### Returns
- RLP-encoded transaction object.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_getRawTransaction",
"params": [
"0x3a2fd1a5ea9ffee477f449be53a49398533d2c006a5815023920d1c397298df3"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_getRawTransaction",
"params": [
"0x3a2fd1a5ea9ffee477f449be53a49398533d2c006a5815023920d1c397298df3"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0xf8678084342770c182520894658bdf435d810c91414ec09147daa6db624063798203e880820a95a0af5fc351b9e457a31f37c84e5cd99dd3c5de60af3de33c6f4160177a2c786a60a0201da7a21046af55837330a2c52fc1543cd4d9ead00ddf178dd96935b607ff9b"
}
```
---
## DEBUG methods
# `DEBUG` methods
The `DEBUG` API methods allow you to inspect and debug the network.
The `DEBUG` API is a more verbose alternative to the [`TRACE` API](../trace.md), and its main purpose is compatibility with tools such as [Remix](https://remix.ethereum.org/).
Where these APIs overlap, we recommend using the [`TRACE` API](../trace.md) for production use over the `DEBUG` API.
Specifically, we recommend `trace_block` over `debug_traceBlock`, and `trace_transaction` over `debug_traceTransaction`.
:::note
The `DEBUG` API is not enabled by default for JSON-RPC.
Enable it using the [`--rpc-http-api`](../../options.md#rpc-http-api) or [`--rpc-ws-api`](../../options.md#rpc-ws-api) option.
:::
The `DEBUG` methods are grouped into the following pages.
#### Trace
Trace transactions, blocks, and calls.
- `debug_standardTraceBlockToFile`
- `debug_standardTraceBadBlockToFile`
- `debug_traceTransaction`
- `debug_traceBlock`
- `debug_traceBlockByHash`
- `debug_traceBlockByNumber`
- `debug_traceCall`
#### Getters
Retrieve block and transaction information.
- `debug_getBadBlocks`
- `debug_getRawBlock`
- `debug_getRawHeader`
- `debug_getRawReceipts`
- `debug_getRawTransaction`
#### State and node
Inspect account and world state, and manage node operations.
- `debug_accountAt`
- `debug_accountRange`
- `debug_batchSendRawTransaction`
- `debug_metrics`
- `debug_replayBlock`
- `debug_resyncWorldState`
- `debug_setHead`
- `debug_storageRangeAt`
---
## State and node methods
These methods inspect account and world state, and manage node operations such as metrics, resyncing, and replaying blocks.
## `debug_accountAt`
Returns account information at the specified index of the specified block.
### Parameters
- `blockHashOrNumber`: _string_ - Block hash or number at which to retrieve account information.
- `txIndex`: _number_ - Transaction index at which to retrieve account information.
- `address`: _string_ - Contract or account address for which to retrieve information.
### Returns
- Account details object.
- `code`: _data_ - Code for the account. Displays `0x0` if the address is an externally owned account.
- `nonce`: _quantity_ - Number of transactions made by the account before this one.
- `balance`: _quantity_ - Balance of the account in wei.
- `codehash`: _data_ - Code hash for the account.
### Example
This example uses an externally owned account address for the `address` parameter.
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_accountAt",
"params": [
"0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6",
0,
"0xbcde5374fce5edbc8e2a8697c15331677e6ebf0b"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_accountAt",
"params": [
"0xc8df1f061abb4d0c107b2b1a794ade8780b3120e681f723fe55a7be586d95ba6",
0,
"0xbcde5374fce5edbc8e2a8697c15331677e6ebf0b"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"code": "0x0",
"nonce": "0x5",
"balance": "0xad78ebc5ac6200000",
"codehash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
}
}
```
This example uses a contract address for the `address` parameter.
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_accountAt",
"params": [
"0x2b76b3a2fc44c0e21ea183d06c846353279a7acf12abcc6fb9d5e8fb14ae2f8c",
0,
"0x0e0d2c8f7794e82164f11798276a188147fbd415"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_accountAt",
"params": [
"0x2b76b3a2fc44c0e21ea183d06c846353279a7acf12abcc6fb9d5e8fb14ae2f8c",
0,
"0x0e0d2c8f7794e82164f11798276a188147fbd415"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"code": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063b27b880414610030575b600080fd5b61004a60048036038101906100459190610108565b61004c565b005b60606000806000604051935036600085376000803686885af490503d9150816000853e806000811461007d57610093565b60008311156100925761012085019350836040525b5b5060008114156100ec578473ffffffffffffffffffffffffffffffffffffffff167f410d96db3f80b0f89b36888c4d8a94004268f8d42309ac39b7bcba706293e099856040516100e3919061016e565b60405180910390a25b5050505050565b60008135905061010281610227565b92915050565b60006020828403121561011e5761011d610211565b5b600061012c848285016100f3565b91505092915050565b600061014082610190565b61014a818561019b565b935061015a8185602086016101de565b61016381610216565b840191505092915050565b600060208201905081810360008301526101888184610135565b905092915050565b600081519050919050565b600082825260208201905092915050565b60006101b7826101be565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60005b838110156101fc5780820151818401526020810190506101e1565b8381111561020b576000848401525b50505050565b600080fd5b6000601f19601f8301169050919050565b610230816101ac565b811461023b57600080fd5b5056fea2646970667358221220fdfb5c371055342507b8fb9ca7b0c234f79819bd5cb05c0d467fb605de979eb564736f6c63430008060033",
"nonce": "0x1",
"balance": "0x0",
"codehash": "0xf5f334d41776ed2828fc910d488a05c57fe7c2352aab2d16e30539d7726e1562"
}
}
```
---
## `debug_accountRange`
[Retesteth](https://github.com/ethereum/retesteth/wiki/Retesteth-Overview) uses `debug_accountRange` to implement debugging.
Returns the accounts for a specified block.
### Parameters
- `blockHashOrNumber`: _string_ - Block hash or number at which to retrieve account information.
- `txIndex`: _number_ - Transaction index at which to retrieve account information.
- `address`: _string_ - Address hash from which to start.
- `limit`: _integer_ - Maximum number of account entries to return.
### Returns
- Account details object.
- `addressMap`: _map_ of _strings_ to _strings_ - Map of address hashes and account addresses.
- `nextKey`: _string_ - Hash of the next address if any addresses remain in the state, otherwise zero.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_accountRange",
"params": [
"12345",
0,
"0",
5
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_accountRange",
"params": [
"12345",
0,
"0",
5
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"addressMap": {
"0x005e5...86960": "0x0000000000000000000000000000000000000000",
"0x021fe...6ffe3": "0x0000000000000000000000000000000000000000",
"0x028e6...ab776": "0x0000000000000000000000000000000000000000",
"0x02cb5...bc4d8": "0x0000000000000000000000000000000000000000",
"0x03089...23fd5": "0x0000000000000000000000000000000000000000"
},
"nextKey": "0x04242954a5cb9748d3f66bcd4583fd3830287aa585bebd9dd06fa6625976be49"
}
}
```
---
## `debug_batchSendRawTransaction`
Sends a list of [signed transactions](../../../how-to/send-transactions.md). This is used to quickly load a network with a lot of transactions. This does the same thing as calling [`eth_sendRawTransaction`](../eth/submit.md#eth_sendrawtransaction) multiple times.
### Parameters
- `data`: _string_ - Signed transaction data array.
### Returns
- Object returned for each transaction.
- `index`: _string_ - Index of the transaction in the request parameters array.
- `success`: _boolean_ - Indicates whether or not the transaction has been added to the transaction pool.
- `errorMessage`: _string_ - (Optional) Error message.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_batchSendRawTransaction",
"params": [
"0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801ba0ac74ecfa0e9b85785f042c143ead4780931234cc9a032fce99fab1f45e0d90faa02fd17e8eb433d4ca47727653232045d4f81322619c0852d3fe8ddcfcedb66a43",
"0x416",
"0xf868018203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801ca0b24ea1bee8fe36984c36acbf80979a4509f23fc17141851e08d505c0df158aa0a00472a05903d4cd7a811bd4d5c59cc105d93f5943f3393f253e92e65fc36e7ce0",
"0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef5787470de4df820000801ca0f7936b4de04792e3c65095cfbfd1399d231368f5f05f877588c0c8509f6c98c9a01834004dead527c8da1396eede42e1c60e41f38a77c2fd13a6e495479c729b99"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_batchSendRawTransaction",
"params": [
"0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801ba0ac74ecfa0e9b85785f042c143ead4780931234cc9a032fce99fab1f45e0d90faa02fd17e8eb433d4ca47727653232045d4f81322619c0852d3fe8ddcfcedb66a43",
"0x416",
"0xf868018203e882520894627306090abab3a6e1400e9345bc60c78a8bef57872386f26fc10000801ca0b24ea1bee8fe36984c36acbf80979a4509f23fc17141851e08d505c0df158aa0a00472a05903d4cd7a811bd4d5c59cc105d93f5943f3393f253e92e65fc36e7ce0",
"0xf868808203e882520894627306090abab3a6e1400e9345bc60c78a8bef5787470de4df820000801ca0f7936b4de04792e3c65095cfbfd1399d231368f5f05f877588c0c8509f6c98c9a01834004dead527c8da1396eede42e1c60e41f38a77c2fd13a6e495479c729b99"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"index": 0,
"success": true
},
{
"index": 1,
"success": false,
"errorMessage": "Invalid raw transaction hex"
},
{
"index": 2,
"success": true
},
{
"index": 3,
"success": false,
"errorMessage": "TRANSACTION_REPLACEMENT_UNDERPRICED"
}
]
}
```
---
## `debug_metrics`
Returns metrics providing information on the internal operation of Besu.
The available metrics might change over time. The JVM metrics might vary based on the JVM implementation used.
The metric types are:
- Timer
- Counter
- Gauge
### Parameters
- None
### Returns
- Metrics object.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_metrics",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_metrics",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"jvm": {
"memory_bytes_init": {
"heap": 268435456,
"nonheap": 2555904
},
"threads_current": 41,
"memory_bytes_used": {
"heap": 696923976,
"nonheap": 63633456
},
"memory_pool_bytes_used": {
"PS Eden Space": 669119360,
"Code Cache": 19689024,
"Compressed Class Space": 4871144,
"PS Survivor Space": 2716320,
"PS Old Gen": 25088296,
"Metaspace": 39073288
},
...
},
"process": {
"open_fds": 546,
"cpu_seconds_total": 67.148992,
"start_time_seconds": 1543897699.589,
"max_fds": 10240
},
"rpc": {
"request_time": {
"debug_metrics": {
"bucket": {
"+Inf": 2,
"0.01": 1,
"0.075": 2,
"0.75": 2,
"0.005": 1,
"0.025": 2,
"0.1": 2,
"1.0": 2,
"0.05": 2,
"10.0": 2,
"0.25": 2,
"0.5": 2,
"5.0": 2,
"2.5": 2,
"7.5": 2
},
"count": 2,
"sum": 0.015925392
}
}
},
"blockchain": {
"difficulty_total": 3533501,
"announcedBlock_ingest": {
"bucket": {
"+Inf": 0,
"0.01": 0,
"0.075": 0,
"0.75": 0,
"0.005": 0,
"0.025": 0,
"0.1": 0,
"1.0": 0,
"0.05": 0,
"10.0": 0,
"0.25": 0,
"0.5": 0,
"5.0": 0,
"2.5": 0,
"7.5": 0
},
"count": 0,
"sum": 0
},
"height": 1908793
},
"peers": {
"disconnected_total": {
"remote": {
"SUBPROTOCOL_TRIGGERED": 5
},
"local": {
"TCP_SUBSYSTEM_ERROR": 1,
"SUBPROTOCOL_TRIGGERED": 2,
"USELESS_PEER": 3
}
},
"peer_count_current": 2,
"connected_total": 10
}
}
}
```
---
## `debug_replayBlock`
Re-imports the block matching the specified block number, by rolling the head of the local chain back to the block right before the specified block, then importing the specified block.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of the
string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- `Success` or `error`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_replayBlock",
"params": [
"0x1"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_replayBlock",
"params": [
"0x1"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## `debug_resyncWorldState`
Triggers a re-synchronization of the world state while retaining imported blocks. This is useful if there are world state database inconsistencies (for example, Bonsai database issues).
### Parameters
- None
### Returns
- `Success` or `error`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_resyncWorldState",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_resyncWorldState",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## `debug_setHead`
Sets the local chain head to the specified block. Optionally, moves the [bonsai](../../../concepts/data-storage-formats.md#bonsai-tries)
world state to that block when the `shouldMoveWorldstate` parameter is set to `true`.
Moving the world state allows expensive operations like [`debug_traceBlock`](trace.md#debug_traceblock)
to run on historical blocks without replaying all intermediate states. This is helpful to avoid
out of memory errors when executing RPC calls on historical states.
:::warning
Do not use this method when a consensus client is directing Besu, or while the node is
actively importing or proposing blocks as this will likely corrupt the database.
Additionally, if you move the chain head by a large number of blocks (for example, more than 5,000),
the RPC call might time out even though Besu continues the operation in the background.
:::
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of the
string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
- `shouldMoveWorldstate`: _boolean_ - (Optional) If `true`, moves the [bonsai](../../../concepts/data-storage-formats.md#bonsai-tries)
world state to the specified block. The default is `false`.
### Returns
- `Success` or `error`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_setHead",
"params": [
"0x1"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_setHead",
"params": [
"0x1"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## `debug_storageRangeAt`
[Remix](https://remix.ethereum.org/) uses `debug_storageRangeAt` to implement debugging. Use the _Debugger_ tab in Remix instead of calling `debug_storageRangeAt` directly.
Returns the contract storage for the specified range.
### Parameters
- `blockHash`: _string_ - Block hash.
- `txIndex`: _number_ - Transaction index from which to start.
- `address`: _string_ - Contract address.
- `startKey`: _string_ - Start key.
- `limit`: _number_ - Number of storage entries to return.
### Returns
- Range object.
- `storage`: _object_ - Key hash and value. Pre-image key is `null` if it falls outside the cache.
- `nextKey`: _hash_ - Hash of next key if further storage in range. Otherwise, not included.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_storageRangeAt",
"params": [
"0x2b76b3a2fc44c0e21ea183d06c846353279a7acf12abcc6fb9d5e8fb14ae2f8c",
0,
"0x0e0d2c8f7794e82164f11798276a188147fbd415",
"0x0000000000000000000000000000000000000000000000000000000000000000",
1
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_storageRangeAt",
"params": [
"0x2b76b3a2fc44c0e21ea183d06c846353279a7acf12abcc6fb9d5e8fb14ae2f8c",
0,
"0x0e0d2c8f7794e82164f11798276a188147fbd415",
"0x0000000000000000000000000000000000000000000000000000000000000000",
1
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"storage": {
"0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563": {
"key": null,
"value": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
},
"nextKey": "0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6"
}
}
```
---
## Trace methods
These methods trace transactions, blocks, and calls to inspect low-level execution.
## `debug_standardTraceBlockToFile`
Generates files containing the block trace. A separate file is generated for each transaction in the block.
You can also specify a trace file for a specific transaction in a block.
Use [`debug_standardTraceBadBlockToFile`](#debug_standardtracebadblocktofile) to view the trace for an invalid block.
### Parameters
- `blockHash`: _string_ - Block hash.
- `options`: _object_ - (Optional) Request options object (all fields optional).
- `txHash`: _string_ - Transaction hash; if omitted, a trace file is generated for each transaction in the block.
- `disableMemory`: _boolean_ - `true` disables memory capture.
The default is `true`.
- `disableStack`: _boolean_ - `true` disables stack capture.
The default is `false`.
- `disableStorage`: _boolean_ - `true` disables storage capture.
The default is `false`.
- `opcodes`: _array_ of _strings_ - List of opcode names to trace; if omitted or empty, all opcodes are traced.
- `enableReturnData`: _boolean_ - `true` enables return data capture.
The default is `false`.
### Returns
- Location of the generated trace files.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_standardTraceBlockToFile",
"params": [
"0x2dc0b6c43144e314a86777b4bd4f987c0790a6a0b21560671d221ed81a23f2dc",
{
"txHash": "0x4ff04c4aec9517721179c8dd435f47fbbfc2ed26cd4926845ab687420d5580a6",
"disableMemory": false
}
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_standardTraceBlockToFile",
"params": [
"0x2dc0b6c43144e314a86777b4bd4f987c0790a6a0b21560671d221ed81a23f2dc",
{
"txHash": "0x4ff04c4aec9517721179c8dd435f47fbbfc2ed26cd4926845ab687420d5580a6",
"disableMemory": false
}
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"/Users/me/mynode/sepolia/data/traces/block_0x2dc0b6c4-4-0x4ff04c4a-1612820117332"
]
}
```
---
## `debug_standardTraceBadBlockToFile`
Generates files containing the block trace of invalid blocks. A separate file is generated for each transaction in the block.
Use [`debug_standardTraceBlockToFile`](#debug_standardtraceblocktofile) to view the trace for a valid block.
### Parameters
- `blockHash`: _string_ - Block hash.
- `options`: _object_ - (Optional) Request options object (all fields optional).
- `txHash`: _string_ - Transaction hash; if omitted, a trace file is generated for each transaction in the block.
- `disableMemory`: _boolean_ - `true` disables memory capture.
The default is `true`.
- `disableStack`: _boolean_ - `true` disables stack capture.
The default is `false`.
- `disableStorage`: _boolean_ - `true` disables storage capture.
The default is `false`.
- `opcodes`: _array_ of _strings_ - List of opcode names to trace; if omitted or empty, all opcodes are traced.
- `enableReturnData`: _boolean_ - `true` enables return data capture.
The default is `false`.
### Returns
- Location of the generated trace files.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_standardTraceBadBlockToFile",
"params": [
"0x53741e9e94791466d117c5f9e41a2ed1de3f73d39920c621dfc2f294e7779baa"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_standardTraceBadBlockToFile",
"params": [
"0x53741e9e94791466d117c5f9e41a2ed1de3f73d39920c621dfc2f294e7779baa"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"/Users/me/mynode/sepolia/data/traces/block_0x53741e9e-0-0x407ec43d-1600951088172"
]
}
```
---
## `debug_traceTransaction`
[Remix](https://remix.ethereum.org/) uses `debug_traceTransaction` to implement debugging. Use the _Debugger_ tab in Remix instead of calling `debug_traceTransaction` directly.
Reruns the transaction with the same state as when the transaction executed.
### Parameters
- `transactionHash`: _string_ - Transaction hash.
- `options`: _object_ - (Optional) Request options object (all fields optional).
- `disableStorage`: _boolean_ - `true` disables storage capture. The default is `false`.
- `enableMemory`: _boolean_ - `true` enables memory capture. The default is `false`.
If specified, `enableMemory` takes precedence over `disableMemory`.
- `disableMemory`: _boolean_ - `true` disables memory capture. The default is `true`.
- `disableStack` : _boolean_ - `true` disables stack capture. The default is `false`.
- `opcodes`: _array_ of _strings_ - List of opcode names to trace; if omitted or empty, all opcodes are traced.
- `enableReturnData`: _boolean_ - `true` enables return data capture. The default is `false`.
### Returns
- Trace object.
- `gas`: _integer_ - Gas used by the transaction.
- `failed`: _boolean_ - True if transaction failed, otherwise, false.
- `returnValue`: _string_ - Bytes returned from transaction execution (without a `0x` prefix).
- `structLogs`: _array_ - Array of structured log objects.
- `pc`: _integer_ - Current program counter.
- `op`: _string_ - Current opcode.
- `gas`: _integer_ - Gas remaining.
- `gasCost`: _integer_ - Cost in wei of each gas unit.
- `depth`: _integer_ - Execution depth.
- `exceptionalHaltReasons`: _array_ - One or more strings representing an error condition causing the EVM execution to terminate, such as running out of gas or attempting to execute an unknown instruction.
- `stack`: _array of 32 byte arrays_ - EVM execution stack before executing current operation.
- `memory`: _array of 32 byte arrays_ - Memory space of the contract before executing current operation.
- `storage`: _object_ - Storage entries changed by the current transaction.
- `returnData`: _data_ - EVM return data produced by the current opcode, as a hex string.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_traceTransaction",
"params": [
"0x2cc6c94c21685b7e0f8ddabf277a5ccf98db157c62619cde8baea696a74ed18e",
{
"disableStorage": true,
"enableReturnData": true
}
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_traceTransaction",
"params": [
"0x2cc6c94c21685b7e0f8ddabf277a5ccf98db157c62619cde8baea696a74ed18e",
{
"disableStorage": true,
"enableReturnData": true
}
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"gas": 21000,
"failed": false,
"returnValue": "",
"structLogs": [
{
"pc": 100,
"op": "STATICCALL",
"gas": 78000,
"gasCost": 500,
"depth": 1,
"stack": [],
"returnData": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
]
}
}
```
---
## `debug_traceBlock`
Returns full trace of all invoked opcodes of all transactions included in the block.
### Parameters
- `block`: _string_ - RLP of the block.
- `options`: _object_ - (Optional) Request options object (all fields optional).
- `disableStorage`: _boolean_ - `true` disables storage capture. The default is `false`.
- `enableMemory`: _boolean_ - `true` enables memory capture. The default is `false`.
If specified, `enableMemory` takes precedence over `disableMemory`.
- `disableMemory`: _boolean_ - `true` disables memory capture. The default is `true`.
- `disableStack` : _boolean_ - `true` disables stack capture. The default is `false`.
- `opcodes`: _array_ of _strings_ - List of opcode names to trace; if omitted or empty, all opcodes are traced.
- `enableReturnData`: _boolean_ - `true` enables return data capture. The default is `false`.
### Returns
- Trace object.
- `gas`: _integer_ - Gas used by the transaction.
- `failed`: _boolean_ - True if transaction failed, otherwise, false.
- `returnValue`: _string_ - Bytes returned from transaction execution (without a `0x` prefix).
- `structLogs`: _array_ - Array of structured log objects.
- `pc`: _integer_ - Current program counter.
- `op`: _string_ - Current opcode.
- `gas`: _integer_ - Gas remaining.
- `gasCost`: _integer_ - Cost in wei of each gas unit.
- `depth`: _integer_ - Execution depth.
- `exceptionalHaltReasons`: _array_ - One or more strings representing an error condition causing the EVM execution to terminate, such as running out of gas or attempting to execute an unknown instruction.
- `stack`: _array of 32 byte arrays_ - EVM execution stack before executing current operation.
- `memory`: _array of 32 byte arrays_ - Memory space of the contract before executing current operation.
- `storage`: _object_ - Storage entries changed by the current transaction.
- `returnData`: _data_ - EVM return data produced by the current opcode, as a hex string.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_traceBlock",
"params": [
"0xf90277f90208a05a41d0e66b4120775176c09fcf39e7c0520517a13d2b57b18d33d342df038bfca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e6a7a1d47ff21b6321162aea7c6cb457d5476bcaa00e0df2706b0a4fb8bd08c9246d472abbe850af446405d9eba1db41db18b4a169a04513310fcb9f6f616972a3b948dc5d547f280849a87ebb5af0191f98b87be598a0fe2bf2a941abf41d72637e5b91750332a30283efd40c424dc522b77e6f0ed8c4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000860153886c1bbd82b44382520b8252088455c426598b657468706f6f6c2e6f7267a0b48c515a9dde8d346c3337ea520aa995a4738bb595495506125449c1149d6cf488ba4f8ecd18aab215f869f86780862d79883d2000825208945df9b87991262f6ba471f09758cde1c0fc1de734827a69801ca088ff6cf0fefd94db46111149ae4bfc179e9b94721fffd821d38d16464b3f71d0a045e0aff800961cfce805daef7016b9b675c137a6a41a548f7b60a3484c06a33ac0"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_traceBlock",
"params": [
"0xf90277f90208a05a41d0e66b4120775176c09fcf39e7c0520517a13d2b57b18d33d342df038bfca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e6a7a1d47ff21b6321162aea7c6cb457d5476bcaa00e0df2706b0a4fb8bd08c9246d472abbe850af446405d9eba1db41db18b4a169a04513310fcb9f6f616972a3b948dc5d547f280849a87ebb5af0191f98b87be598a0fe2bf2a941abf41d72637e5b91750332a30283efd40c424dc522b77e6f0ed8c4b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000860153886c1bbd82b44382520b8252088455c426598b657468706f6f6c2e6f7267a0b48c515a9dde8d346c3337ea520aa995a4738bb595495506125449c1149d6cf488ba4f8ecd18aab215f869f86780862d79883d2000825208945df9b87991262f6ba471f09758cde1c0fc1de734827a69801ca088ff6cf0fefd94db46111149ae4bfc179e9b94721fffd821d38d16464b3f71d0a045e0aff800961cfce805daef7016b9b675c137a6a41a548f7b60a3484c06a33ac0"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"gas": 21000,
"failed": false,
"returnValue": "",
"structLogs": [
{
"pc": 0,
"op": "STOP",
"gas": 0,
"gasCost": 0,
"depth": 1,
"stack": []
}
]
}
}
```
---
## `debug_traceBlockByHash`
Returns full trace of all invoked opcodes of all transactions included in the block.
### Parameters
- `blockHash`: _string_ - Block hash.
- `options`: _object_ - (Optional) Request options object (all fields optional).
- `disableStorage`: _boolean_ - `true` disables storage capture. The default is `false`.
- `enableMemory`: _boolean_ - `true` enables memory capture. The default is `false`.
If specified, `enableMemory` takes precedence over `disableMemory`.
- `disableMemory`: _boolean_ - `true` disables memory capture. The default is `true`.
- `disableStack` : _boolean_ - `true` disables stack capture. The default is `false`.
- `opcodes`: _array_ of _strings_ - List of opcode names to trace; if omitted or empty, all opcodes are traced.
- `enableReturnData`: _boolean_ - `true` enables return data capture. The default is `false`.
### Returns
- List of trace objects.
- `gas`: _integer_ - Gas used by the transaction.
- `failed`: _boolean_ - True if transaction failed, otherwise, false.
- `returnValue`: _string_ - Bytes returned from transaction execution (without a `0x` prefix).
- `structLogs`: _array_ - Array of structured log objects.
- `pc`: _integer_ - Current program counter.
- `op`: _string_ - Current opcode.
- `gas`: _integer_ - Gas remaining.
- `gasCost`: _integer_ - Cost in wei of each gas unit.
- `depth`: _integer_ - Execution depth.
- `exceptionalHaltReasons`: _array_ - One or more strings representing an error condition causing the EVM execution to terminate, such as running out of gas or attempting to execute an unknown instruction.
- `stack`: _array of 32 byte arrays_ - EVM execution stack before executing current operation.
- `memory`: _array of 32 byte arrays_ - Memory space of the contract before executing current operation.
- `storage`: _object_ - Storage entries changed by the current transaction.
- `returnData`: _data_ - EVM return data produced by the current opcode, as a hex string.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_traceBlockByHash",
"params": [
"0xaceb3b2c9b25b0589230873921eb894b28722011b8df63977145517d754875a5"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_traceBlockByHash",
"params": [
"0xaceb3b2c9b25b0589230873921eb894b28722011b8df63977145517d754875a5"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"gas": 21000,
"failed": false,
"returnValue": "",
"structLogs": [
{
"pc": 0,
"op": "STOP",
"gas": 0,
"gasCost": 0,
"depth": 1,
"stack": []
}
]
}
]
}
```
---
## `debug_traceBlockByNumber`
Returns full trace of all invoked opcodes of all transactions included in the block.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of the
string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
- `options`: _object_ - (Optional) Request options object (all fields optional).
- `disableStorage`: _boolean_ - `true` disables storage capture. The default is `false`.
- `enableMemory`: _boolean_ - `true` enables memory capture. The default is `false`.
If specified, `enableMemory` takes precedence over `disableMemory`.
- `disableMemory`: _boolean_ - `true` disables memory capture. The default is `true`.
- `disableStack` : _boolean_ - `true` disables stack capture. The default is `false`.
- `opcodes`: _array_ of _strings_ - List of opcode names to trace; if omitted or empty, all opcodes are traced.
- `enableReturnData`: _boolean_ - `true` enables return data capture. The default is `false`.
### Returns
- List of trace objects.
- `gas`: _integer_ - Gas used by the transaction.
- `failed`: _boolean_ - True if transaction failed, otherwise, false.
- `returnValue`: _string_ - Bytes returned from transaction execution (without a `0x` prefix).
- `structLogs`: _array_ - Array of structured log objects.
- `pc`: _integer_ - Current program counter.
- `op`: _string_ - Current opcode.
- `gas`: _integer_ - Gas remaining.
- `gasCost`: _integer_ - Cost in wei of each gas unit.
- `depth`: _integer_ - Execution depth.
- `exceptionalHaltReasons`: _array_ - One or more strings representing an error condition causing the EVM execution to terminate, such as running out of gas or attempting to execute an unknown instruction.
- `stack`: _array of 32 byte arrays_ - EVM execution stack before executing current operation.
- `memory`: _array of 32 byte arrays_ - Memory space of the contract before executing current operation.
- `storage`: _object_ - Storage entries changed by the current transaction.
- `returnData`: _data_ - EVM return data produced by the current opcode, as a hex string.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_traceBlockByNumber",
"params": [
"0x7224",
{
"disableStorage": true
}
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_traceBlockByNumber",
"params": [
"0x7224",
{
"disableStorage": true
}
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"gas": 21000,
"failed": false,
"returnValue": "",
"structLogs": [
{
"pc": 0,
"op": "STOP",
"gas": 0,
"gasCost": 0,
"depth": 1,
"stack": []
}
]
}
]
}
```
---
## `debug_traceCall`
Performs an [`eth_call`](../eth/execute.md#eth_call) within the execution environment of a given block, using the final state of its parent block as the base, and provides a detailed trace of the executed opcodes.
Each `options` entry specifies a state that will be temporarily overridden before executing the call.
This allows you to test, analyze, and debug smart contracts more efficiently by allowing
temporary state changes without affecting the actual blockchain state.
### Parameters
- `call`: _object_ - Transaction call object.
- `from`: _data, 20 bytes_ - Address of the sender.
- `to`: _data, 20 bytes_ - Address of the action receiver.
- `gas`: _quantity, integer_ - Gas provided by the sender. `eth_call` consumes zero gas, but other executions might need this parameter. `eth_estimateGas` ignores this value.
- `gasPrice`: _quantity, integer_ - Gas price, in Wei, provided by the sender. The default is `0`. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Can be used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxFeePerGas`.
- `maxFeePerGas`: _quantity, integer_ - Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Can be used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxPriorityFeePerGas`.
- `maxFeePerBlobGas`: _quantity, integer_ - Maximum fee the sender is willing to pay per blob gas. Only used for blob transactions introduced in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844).
- `nonce`: _quantity, integer_ - Number of transactions made by the sender before this one. The default is the sender's nonce.
- `value`: _quantity, integer_ - Value transferred, in Wei.
- `data`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `input` if both parameters are provided.
- `input`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `data` if both parameters are provided.
- `accessList`: _array_ - List of addresses and storage keys that the transaction plans to access. Used only in non-[`FRONTIER`](../../../concepts/transactions/types.md#frontier-transactions) transactions.
- `strict`: _tag_ - Determines if the sender account balance is considered during gas estimation. If `true`, the sender's balance is checked against the transaction's gas parameters. This ensures the estimated gas reflects what the sender can actually afford. If `false`, the balance checks are skipped. The default is `true`.
- `blobVersionedHashes`: _array_ - List of references to blobs introduced in [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844).
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of the
string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
- `options`: _object_ - (Optional) Request options object (all fields optional).
- `disableStorage`: _boolean_ - `true` disables storage capture.
The default is `false`.
- `enableMemory`: _boolean_ - `true` enables memory capture.
The default is `false`.
If specified, `enableMemory` takes precedence over `disableMemory`.
- `disableMemory`: _boolean_ - `true` disables memory capture.
The default is `true`.
- `disableStack` : _boolean_ - `true` disables stack capture.
The default is `false`.
- `opcodes`: _array_ of _strings_ - List of opcode names to trace; if omitted or empty, all opcodes are traced.
- `enableReturnData`: _boolean_ - `true` enables return data capture. The default is `false`.
- `stateOverrides`: _object_ - Address-to-state mapping.
- `balance`: _quantity_ - Temporary account balance for the call execution.
- `nonce`: _quantity_ - Temporary nonce value for the call execution.
- `code`: _binary_ - Bytecode to inject into the account.
- `movePrecompileToAddress`: _data, 20 bytes_ - Address to which the precompile address should be moved.
- `state`: _quantity_ - `key:value` pairs to override all slots in the account storage. You cannot set both the `state` and `stateDiff` options simultaneously.
- `stateDiff`: _quantity_ - `key:value` pairs to override individual slots in the account storage. You cannot set both the `state` and `stateDiff` options simultaneously.
### Returns
- List of trace objects.
- `gas`: _integer_ - Gas used by the transaction.
- `failed`: _boolean_ - True if transaction failed, otherwise, false.
- `returnValue`: _string_ - Bytes returned from transaction execution (without a `0x` prefix).
- `structLogs`: _array_ - Array of structured log objects.
- `pc`: _integer_ - Current program counter.
- `op`: _string_ - Current opcode.
- `gas`: _integer_ - Gas remaining.
- `gasCost`: _integer_ - Cost in wei of each gas unit.
- `depth`: _integer_ - Execution depth.
- `exceptionalHaltReasons`: _array_ - One or more strings representing an error condition causing the EVM execution to terminate, such as running out of gas or attempting to execute an unknown instruction.
- `stack`: _array of 32 byte arrays_ - EVM execution stack before executing current operation.
- `memory`: _array of 32 byte arrays_ - Memory space of the contract before executing current operation.
- `storage`: _object_ - Storage entries changed by the current transaction.
- `returnData`: _data_ - EVM return data produced by the current opcode, as a hex string.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "debug_traceCall",
"params": [
{
"from": "",
"to": "",
"gas": "0xfffff2",
"gasPrice": "0xef",
"value": "0x0",
"data": ""
},
"latest",
{
"disableMemory": true,
"disableStack": true,
"disableStorage": true
}
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "debug_traceCall",
"params": [{"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73","0x0050000000000000000000000000000000000000", "0xfffff2","0xef","0x0","0x0000000000000000000000000030000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000001"},"latest",{"disableMemory":true,"disableStack":true,"disableStorage":true}],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"gas": 21000,
"failed": false,
"returnValue": "",
"structLogs": [
{
"pc": 0,
"op": "STOP",
"gas": 0,
"gasCost": 0,
"depth": 1
}
]
}
]
}
```
---
## Block methods
These methods query blocks and their contents, including block details, transaction counts, receipts, and uncles.
## `eth_getBlockByHash`
Returns information about the block matching the specified block hash.
### Parameters
- `hash`: _string_ - 32-byte hash of a block.
- `verbose`: _boolean_ - If `true`, returns the full transaction objects; if `false`, returns the transaction hashes.
### Returns
- Block object, or `null` when there is no block.
- `number`: _quantity, integer_ - Block number. `null` when block is pending.
- `hash`: _data, 32 bytes_ - Hash of the block. `null` when block is pending.
- `mixHash`: _data, 32 bytes_ - For pre-[merge](https://ethereum.org/roadmap/merge/) blocks, the hash used to verify the proof of work. For post-merge blocks, the `prevRandao` value supplied by the consensus layer.
- `parentHash`: _data, 32 bytes_ - Hash of the parent block.
- `nonce`: _data, 8 bytes_ - Hash of the generated proof of work. `null` when block is pending.
- `sha3Uncles`: _data, 32 bytes_ - SHA3 of the uncle's data in the block.
- `logsBloom`: _data, 256 bytes_ - Bloom filter for the block logs. `null` when block is pending.
- `transactionsRoot`: _data, 32 bytes_ - Root of the transaction trie for the block.
- `stateRoot`: _data, 32 bytes_ - Root of the final state trie for the block.
- `receiptsRoot`: _data, 32 bytes_ - Root of the receipts trie for the block.
- `miner`: _data, 20 bytes_ - Address to pay mining rewards to.
- `difficulty`: _quantity, integer_ - Difficulty for this block.
- `totalDifficulty`: _quantity, integer_ - Total difficulty of the chain until this block. Only present for pre-[merge](https://ethereum.org/roadmap/merge/) blocks. This value will always be `0` for an uncle block.
- `extraData`: _data_ - Extra data field for this block. The first 32 bytes is vanity data you can set using the [`--miner-extra-data`](../../options.md#miner-extra-data) command line option. Stores extra data when used with [IBFT](../../../../private-networks/how-to/configure/consensus/ibft.md#genesis-file).
- `size`: _quantity, integer_ - Size of block in bytes.
- `gasLimit`: _quantity_ - Maximum gas allowed in this block.
- `gasUsed`: _quantity_ - Total gas used by all transactions in this block.
- `timestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) for block assembly.
- `transactions`: _array_ - Array of transaction objects, or 32 byte transaction hashes depending on the specified boolean parameter.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
- `uncles`: _array_ - Array of uncle hashes.
- `baseFeePerGas`: _quantity_ - The block's [base fee per gas](../../../concepts/transactions/types.md#eip1559-transactions). Only present for blocks created after [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559).
- `withdrawalsRoot`: _data, 32 bytes_ - Root of the withdrawals trie for the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `withdrawals`: _array_ - Array of validator withdrawal objects included in the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `index`: _quantity_ - Index of the withdrawal.
- `validatorIndex`: _quantity_ - Index of the validator that initiated the withdrawal.
- `address`: _data, 20 bytes_ - Address the withdrawal was sent to.
- `amount`: _quantity_ - Amount withdrawn, in Gwei.
- `blobGasUsed`: _quantity_ - Total blob gas used by the transactions in this block. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `excessBlobGas`: _quantity_ - Running total of excess blob gas used to calculate the blob base fee for subsequent blocks. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `parentBeaconBlockRoot`: _data, 32 bytes_ - Root of the parent beacon block, which exposes beacon chain state to the EVM. Only present for blocks created after [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) (Cancun).
- `requestsHash`: _data, 32 bytes_ - Hash of the general purpose execution layer requests (for example, deposits, withdrawals, and consolidations) included in the block. Only present for blocks created after [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) (Prague).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getBlockByHash",
"params": [
"0xd5f1812548be429cbdc6376b29611fc49e06f1359758c4ceaaa3b393e2239f9c",
false
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getBlockByHash",
"params": [
"0xd5f1812548be429cbdc6376b29611fc49e06f1359758c4ceaaa3b393e2239f9c",
false
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": {
"number": "0x68b3",
"hash": "0xd5f1812548be429cbdc6376b29611fc49e06f1359758c4ceaaa3b393e2239f9c",
"mixHash": "0x24900fb3da77674a861c428429dce0762707ecb6052325bbd9b3c64e74b5af9d",
"parentHash": "0x1f68ac259155e2f38211ddad0f0a15394d55417b185a93923e2abe71bb7a4d6d",
"nonce": "0x378da40ff335b070",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"logsBloom": "0x00000000000000100000004080000000000500000000000000020000100000000800001000000004000001000000000000000800040010000020100000000400000010000000000000000040000000000000040000000000000000000000000000000400002400000000000000000000000000000004000004000000000000840000000800000080010004000000001000000800000000000000000000000000000000000800000000000040000000020000000000000000000800000400000000000000000000000600000400000000002000000000000000000000004000000000000000100000000000000000000000000000000000040000900010000000",
"transactionsRoot": "0x4d0c8e91e16bdff538c03211c5c73632ed054d00a7e210c0eb25146c20048126",
"stateRoot": "0x91309efa7e42c1f137f31fe9edbe88ae087e6620d0d59031324da3e2f4f93233",
"receiptsRoot": "0x68461ab700003503a305083630a8fb8d14927238f0bc8b6b3d246c0c64f21f4a",
"miner": "0xb42b6c4a95406c78ff892d270ad20b22642e102d",
"difficulty": "0x66e619a",
"totalDifficulty": "0x1e875d746ae",
"extraData": "0xd583010502846765746885676f312e37856c696e7578",
"size": "0x334",
"gasLimit": "0x47e7c4",
"gasUsed": "0x37993",
"timestamp": "0x5835c54d",
"uncles": [],
"transactions": [
"0xa0807e117a8dd124ab949f460f08c36c72b710188f01609595223b325e58e0fc",
"0xeae6d797af50cb62a596ec3939114d63967c374fa57de9bc0f4e2b576ed6639d"
],
"baseFeePerGas": "0x7"
}
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block (hash : \"0xb0efed1fc9326fee967cb2d845d4ebe57c5350a0670c8e86f8052dea6f219f92\") {number transactions{hash} timestamp difficulty totalDifficulty gasUsed gasLimit hash nonce ommerCount logsBloom mixHash ommerHash extraData stateRoot receiptsRoot transactionCount transactionsRoot}}"
}'
```
```text
{
block(hash: "0xb0efed1fc9326fee967cb2d845d4ebe57c5350a0670c8e86f8052dea6f219f92") {
number
transactions {
hash
}
timestamp
difficulty
totalDifficulty
gasUsed
gasLimit
hash
nonce
ommerCount
logsBloom
mixHash
ommerHash
extraData
stateRoot
receiptsRoot
transactionCount
transactionsRoot
}
}
```
```json
{
"data": {
"block": {
"number": 17607,
"transactions": [],
"timestamp": "0x5cdbdfb5",
"difficulty": "0x1",
"totalDifficulty": "0x44c8",
"gasUsed": 0,
"gasLimit": 4700000,
"hash": "0xb0efed1fc9326fee967cb2d845d4ebe57c5350a0670c8e86f8052dea6f219f92",
"nonce": "0x0000000000000000",
"ommerCount": 0,
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"ommerHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"extraData": "0xf882a00000000000000000000000000000000000000000000000000000000000000000d5949811ebc35d7b06b3fa8dc5809a1f9c52751e1deb808400000000f843b841fae6d25da0b91e3e88669d0a765c98479d86d53e9ea1f3fb6b36d7ff22fa622a3da0c49c20e5562c774e90acae8ad487936f6b6019cd8a782db684693cba1e9800",
"stateRoot": "0xa7086c266aed46cd3bc45579178f8acb36d9d147de575a3ecbf8c7e6f1c737fc",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"transactionCount": 0,
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"baseFeePerGas": "0x7"
}
}
}
```
---
## `eth_getBlockByNumber`
Returns information about the block matching the specified block number.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
- `verbose`: _boolean_ - If `true`, returns the full transaction objects; if `false`, returns only the hashes of the transactions.
### Returns
- Block object, or `null` when there is no block.
- `number`: _quantity, integer_ - Block number. `null` when block is pending.
- `hash`: _data, 32 bytes_ - Hash of the block. `null` when block is pending.
- `mixHash`: _data, 32 bytes_ - For pre-[merge](https://ethereum.org/roadmap/merge/) blocks, the hash used to verify the proof of work. For post-merge blocks, the `prevRandao` value supplied by the consensus layer.
- `parentHash`: _data, 32 bytes_ - Hash of the parent block.
- `nonce`: _data, 8 bytes_ - Hash of the generated proof of work. `null` when block is pending.
- `sha3Uncles`: _data, 32 bytes_ - SHA3 of the uncle's data in the block.
- `logsBloom`: _data, 256 bytes_ - Bloom filter for the block logs. `null` when block is pending.
- `transactionsRoot`: _data, 32 bytes_ - Root of the transaction trie for the block.
- `stateRoot`: _data, 32 bytes_ - Root of the final state trie for the block.
- `receiptsRoot`: _data, 32 bytes_ - Root of the receipts trie for the block.
- `miner`: _data, 20 bytes_ - Address to pay mining rewards to.
- `difficulty`: _quantity, integer_ - Difficulty for this block.
- `totalDifficulty`: _quantity, integer_ - Total difficulty of the chain until this block. Only present for pre-[merge](https://ethereum.org/roadmap/merge/) blocks. This value will always be `0` for an uncle block.
- `extraData`: _data_ - Extra data field for this block. The first 32 bytes is vanity data you can set using the [`--miner-extra-data`](../../options.md#miner-extra-data) command line option. Stores extra data when used with [IBFT](../../../../private-networks/how-to/configure/consensus/ibft.md#genesis-file).
- `size`: _quantity, integer_ - Size of block in bytes.
- `gasLimit`: _quantity_ - Maximum gas allowed in this block.
- `gasUsed`: _quantity_ - Total gas used by all transactions in this block.
- `timestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) for block assembly.
- `transactions`: _array_ - Array of transaction objects, or 32 byte transaction hashes depending on the specified boolean parameter.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
- `uncles`: _array_ - Array of uncle hashes.
- `baseFeePerGas`: _quantity_ - The block's [base fee per gas](../../../concepts/transactions/types.md#eip1559-transactions). Only present for blocks created after [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559).
- `withdrawalsRoot`: _data, 32 bytes_ - Root of the withdrawals trie for the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `withdrawals`: _array_ - Array of validator withdrawal objects included in the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `index`: _quantity_ - Index of the withdrawal.
- `validatorIndex`: _quantity_ - Index of the validator that initiated the withdrawal.
- `address`: _data, 20 bytes_ - Address the withdrawal was sent to.
- `amount`: _quantity_ - Amount withdrawn, in Gwei.
- `blobGasUsed`: _quantity_ - Total blob gas used by the transactions in this block. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `excessBlobGas`: _quantity_ - Running total of excess blob gas used to calculate the blob base fee for subsequent blocks. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `parentBeaconBlockRoot`: _data, 32 bytes_ - Root of the parent beacon block, which exposes beacon chain state to the EVM. Only present for blocks created after [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) (Cancun).
- `requestsHash`: _data, 32 bytes_ - Hash of the general purpose execution layer requests (for example, deposits, withdrawals, and consolidations) included in the block. Only present for blocks created after [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) (Prague).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getBlockByNumber",
"params": [
"0x68B3",
true
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getBlockByNumber",
"params": [
"0x68B3",
true
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"number": "0x68b3",
"hash": "0xd5f1812548be429cbdc6376b29611fc49e06f1359758c4ceaaa3b393e2239f9c",
"mixHash": "0x24900fb3da77674a861c428429dce0762707ecb6052325bbd9b3c64e74b5af9d",
"parentHash": "0x1f68ac259155e2f38211ddad0f0a15394d55417b185a93923e2abe71bb7a4d6d",
"nonce": "0x378da40ff335b070",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"logsBloom": "0x00000000000000100000004080000000000500000000000000020000100000000800001000000004000001000000000000000800040010000020100000000400000010000000000000000040000000000000040000000000000000000000000000000400002400000000000000000000000000000004000004000000000000840000000800000080010004000000001000000800000000000000000000000000000000000800000000000040000000020000000000000000000800000400000000000000000000000600000400000000002000000000000000000000004000000000000000100000000000000000000000000000000000040000900010000000",
"transactionsRoot": "0x4d0c8e91e16bdff538c03211c5c73632ed054d00a7e210c0eb25146c20048126",
"stateRoot": "0x91309efa7e42c1f137f31fe9edbe88ae087e6620d0d59031324da3e2f4f93233",
"receiptsRoot": "0x68461ab700003503a305083630a8fb8d14927238f0bc8b6b3d246c0c64f21f4a",
"miner": "0xb42b6c4a95406c78ff892d270ad20b22642e102d",
"difficulty": "0x66e619a",
"totalDifficulty": "0x1e875d746ae",
"extraData": "0xd583010502846765746885676f312e37856c696e7578",
"size": "0x334",
"gasLimit": "0x47e7c4",
"gasUsed": "0x37993",
"timestamp": "0x5835c54d",
"uncles": [],
"transactions": [],
"baseFeePerGas": "0x7"
}
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block (number : 100) {transactions{hash} timestamp difficulty totalDifficulty gasUsed gasLimit hash nonce ommerCount logsBloom mixHash ommerHash extraData stateRoot receiptsRoot transactionCount transactionsRoot ommers{hash} ommerAt(index : 1){hash} miner{address} account(address: \"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73\"){balance} parent{hash} }}"
}'
```
```text
{
block(number: 100) {
transactions {
hash
}
timestamp
difficulty
totalDifficulty
gasUsed
gasLimit
hash
nonce
ommerCount
logsBloom
mixHash
ommerHash
extraData
stateRoot
receiptsRoot
transactionCount
transactionsRoot
ommers {
hash
}
ommerAt(index: 1) {
hash
}
miner {
address
}
account(address: "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73") {
balance
}
parent {
hash
}
}
}
```
```json
{
"data": {
"block": {
"transactions": [],
"timestamp": "0x5cd10933",
"difficulty": "0x1",
"totalDifficulty": "0x65",
"gasUsed": 0,
"gasLimit": 4700000,
"hash": "0x63b3ea2bc37fec8f82680eb823652da6af8acebb4f6c4d0ff659c55be473c8b0",
"nonce": "0x0000000000000000",
"ommerCount": 0,
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"ommerHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"extraData": "0xf882a00000000000000000000000000000000000000000000000000000000000000000d5949811ebc35d7b06b3fa8dc5809a1f9c52751e1deb808400000000f843b8414d877d8d0ced37ea138fab55a978f3740367a24a31731322ecdc3368f11e0d4966c9ce17ae59a76fb94eb436e8a386868f6bd6b0a5678e58daf49f5dd940558b00",
"stateRoot": "0xd650578a04b39f50cc979155f4510ec28c2c0a7c1e5fdbf84609bc7b1c430f48",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"transactionCount": 0,
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"ommers": [],
"ommerAt": null,
"miner": {
"address": "0x9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb"
},
"account": {
"balance": "0xad0f47f269cbf31ac"
},
"parent": {
"hash": "0x7bca25e1fa5e395fd6029eb496a70b6b5495843976bf9e49b993c723ded29d9e"
},
"baseFeePerGas": "0x7"
}
}
}
```
---
## `eth_getBlockReceipts`
Returns all transaction receipts for a given block. Transaction receipts provide a way to track the success or failure of a transaction (`1` if successful and `0` if failed), as well as the amount of
gas used and any event logs that might have been produced by a smart contract during the transaction.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- List of transaction receipt objects, or `null` when there is no block.
- `blockHash`: _data, 32 bytes_ - Hash of block containing this transaction.
- `blockNumber`: _quantity_ - Block number of block containing this transaction.
- `blockTimestamp`: _quantity_ - Hex-encoded unix timestamp (in seconds) of the block that includes this transaction.
- `contractAddress`: _data, 20 bytes_ - Contract address created, if contract creation transaction, otherwise, `null`. A failed contract creation transaction still produces a contract address value.
- `cumulativeGasUsed`: _quantity_ - Total amount of gas used by previous transactions in the block and this transaction.
- `effectiveGasPrice`: _quantity_ - The [actual value per gas deducted](../../../concepts/transactions/types.md#eip1559-transactions) from the sender's account.
- `from`: _data, 20 bytes_ - Address of the sender.
- `gasUsed`: _quantity_ - Amount of gas used by this specific transaction.
- `logs`: _array_ - Array of log objects generated by this transaction.
- `removed`: _tag_ - `true` if log removed because of a chain reorganization. `false` if a valid log.
- `logIndex`: _quantity, integer_ - Log index position in the block. `null` when log is pending.
- `transactionIndex`: _quantity, integer_ - Index position of the starting transaction for the log. `null` when log is pending.
- `transactionHash`: _data, 32 bytes_ - Hash of the starting transaction for the log. `null` when log is pending.
- `blockHash`: _data, 32 bytes_ - Hash of the block that includes the log. `null` when log is pending.
- `blockNumber`: _quantity_ - Number of block that includes the log. `null` when log is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded unix timestamp (in seconds) of the block that includes the log.
- `address`: _data, 20 bytes_ - Address the log originated from.
- `data`: _data_ - Non-indexed arguments of the log.
- `topics`: _array of data, 32 bytes each_ - [Event signature hash](../../../concepts/events-and-logs.md#event-signature-hash) and 0 to 3 [indexed log arguments](../../../concepts/events-and-logs.md#event-parameters).
- `logsBloom`: _data, 256 bytes_ - Bloom filter for light clients to quickly retrieve related logs.
- `status`: _quantity_ - Either `0x0` (failure), `0x1` (success), or `0x2` (invalid).
- `to`: _data, 20 bytes_ - Address of the receiver, if sending ether, otherwise, null.
- `transactionHash`: _data, 32 bytes_ - Hash of the transaction.
- `transactionIndex`: _quantity, integer_ - Index position of transaction in the block.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `revertReason`: _string_ - ABI-encoded string that displays the [reason for reverting the transaction](../../../../private-networks/how-to/send-transactions/revert-reason.md). Only available if revert reason is [enabled](../../options.md#revert-reason-enabled).
- `type`: _quantity_ - Transaction type, `0x00` for legacy transactions, `0x01` for access list types, `0x02` for dynamic fees, and `0x03` for blob transactions.
- `root`: _data, 32 bytes_ - Pre-Byzantium transactions return this field instead of `status`. Post-transaction state root.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getBlockReceipts",
"params": [
"latest"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getBlockReceipts",
"params": [
"0x6f55"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"blockHash": "0x19514ce955c65e4dd2cd41f435a75a46a08535b8fc16bc660f8092b32590b182",
"blockNumber": "0x6f55",
"contractAddress": null,
"cumulativeGasUsed": "0x18c36",
"from": "0x22896bfc68814bfd855b1a167255ee497006e730",
"gasUsed": "0x18c36",
"effectiveGasPrice": "0x9502f907",
"logs": [
{
"address": "0xfd584430cafa2f451b4e2ebcf3986a21fff04350",
"topics": [
"0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d",
"0x4be29e0e4eb91f98f709d98803cba271592782e293b84a625e025cbb40197ba8",
"0x000000000000000000000000835281a2563db4ebf1b626172e085dc406bfc7d2",
"0x00000000000000000000000022896bfc68814bfd855b1a167255ee497006e730"
],
"data": "0x",
"blockNumber": "0x6f55",
"transactionHash": "0x4a481e4649da999d92db0585c36cba94c18a33747e95dc235330e6c737c6f975",
"transactionIndex": "0x0",
"blockHash": "0x19514ce955c65e4dd2cd41f435a75a46a08535b8fc16bc660f8092b32590b182",
"blockTimestamp": "0x561bc2e0",
"logIndex": "0x0",
"removed": false
}
],
"logsBloom": "0x00000004000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000080020000000000000200010000000000000000000001000000800000000000000000000000000000000000000000000000000000100100000000000000000000008000000000000000000000000000000002000000000000000000000",
"status": "0x1",
"to": "0xfd584430cafa2f451b4e2ebcf3986a21fff04350",
"transactionHash": "0x4a481e4649da999d92db0585c36cba94c18a33747e95dc235330e6c737c6f975",
"transactionIndex": "0x0",
"type": "0x0"
},
{
"blockHash": "0x19514ce955c65e4dd2cd41f435a75a46a08535b8fc16bc660f8092b32590b182",
"blockNumber": "0x6f55",
"contractAddress": null,
"cumulativeGasUsed": "0x1de3e",
"from": "0x712e3a792c974b3e3dbe41229ad4290791c75a82",
"gasUsed": "0x5208",
"effectiveGasPrice": "0x9502f907",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0xd42e2b1c14d02f1df5369a9827cb8e6f3f75f338",
"transactionHash": "0xefb83b4e3f1c317e8da0f8e2fbb2fe964f34ee184466032aeecac79f20eacaf6",
"transactionIndex": "0x1",
"type": "0x2"
}
]
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block (hash: \"0x4d746a3381673a5180744a56e78cded4696b77317866c2253566e0fa16967e1d\") {transactions{block{hash logsBloom} hash createdContract{address} cumulativeGasUsed gas gasUsed logs{topics} from{address} to{address} index}}}"
}'
```
```text
{
block (hash: "0x4d746a3381673a5180744a56e78cded4696b77317866c2253566e0fa16967e1d") {
transactions {
block {
hash
logsBloom
}
hash
createdContract {
address
}
cumulativeGasUsed
gas
gasUsed
logs{
topics
}
from{
address
}
to {
address
}
index
}
}
}
```
```json
{
"data" : {
"block" : {
"transactions" : [ {
"block" : {
"hash" : "0x4d746a3381673a5180744a56e78cded4696b77317866c2253566e0fa16967e1d",
"logsBloom" : "0x2e0a8080520608000e38181e0c9081e813a00c184a010d1900c9602240428dc6480004444098428b945010802454104002827420426591a200224016802841900031bd4440828ec9b113081880027c01cc47105c1885d556216200880026160810050028422a4b0c4bc8087372860851000802c8d901158504a482100d488040119c08045e500824402054a0d91cc433188909020a06ac841914a2a082c104a1260460014b8b001b28030202518c040008266038a880026208041d082503589054581223c188004396804801280c00020c492816060a421831c8820ac04460303a9e48128238e0098f319030083808150c4914b8840000206715481500690000"
},
"hash" : "0x7afe779fd0c6d4a1b6f330e679a5cf94095eaa57d2ce0c0ef991dfb2b405374f",
"createdContract" : null,
"cumulativeGasUsed" : "0x5208",
"gas" : "0x61a8",
"gasUsed" : "0x5208",
"logs" : [ ],
"from" : {
"address" : "0x66f962241b8ff853849c85a63a0ce20bae4f68d5"
},
"to" : {
"address" : "0x6be8356826a9fc7b2d911fcc1de6342ae5f5b9a3"
},
"index" : "0x0"
}, {
"block" : {
"hash" : "0x4d746a3381673a5180744a56e78cded4696b77317866c2253566e0fa16967e1d",
"logsBloom" : "0x2e0a8080520608000e38181e0c9081e813a00c184a010d1900c9602240428dc6480004444098428b945010802454104002827420426591a200224016802841900031bd4440828ec9b113081880027c01cc47105c1885d556216200880026160810050028422a4b0c4bc8087372860851000802c8d901158504a482100d488040119c08045e500824402054a0d91cc433188909020a06ac841914a2a082c104a1260460014b8b001b28030202518c040008266038a880026208041d082503589054581223c188004396804801280c00020c492816060a421831c8820ac04460303a9e48128238e0098f319030083808150c4914b8840000206715481500690000"
},
"hash" : "0x412f04ba27c1c096dadb2d8af54ee61034c3d4679fdd025a634e95fa2238713c",
"createdContract" : null,
"cumulativeGasUsed" : "0xbcdb2",
"gas" : "0xbdfe0",
"gasUsed" : "0xb7baa",
"logs" : [ {
"topics" : [ "0xd93fde3ea1bb11dcd7a4e66320a05fc5aa63983b6447eff660084c4b1b1b499b", "0x00000000000000000000000000000000000000000000000000000000000e4d3a" ]
} ],
"from" : {
"address" : "0xe253f7a6533c62755f470b33fa5bcd659a5db3cd"
},
"to" : {
"address" : "0x95ff8d3ce9dcb7455beb7845143bea84fe5c4f6f"
},
"index" : "0x1"
} ]
}
}
}
```
---
## `eth_getBlockTransactionCountByHash`
Returns the number of transactions in the block matching the specified block hash.
### Parameters
- `hash`: _string_ - 32-byte block hash.
### Returns
- Integer representing the number of transactions in the specified block, or `null` if no matching block hash is found.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getBlockTransactionCountByHash",
"params": [
"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getBlockTransactionCountByHash",
"params": [
"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": null
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block(hash:\"0xe455c14f757b0b9b67774baad1be1c180a4c1657df52259dbb685bf375408097\"){transactionCount}}"
}'
```
```text
{
block(hash: "0xe455c14f757b0b9b67774baad1be1c180a4c1657df52259dbb685bf375408097") {
transactionCount
}
}
```
```json
{
"data": {
"block": {
"transactionCount": 1
}
}
}
```
---
## `eth_getBlockTransactionCountByNumber`
Returns the number of transactions in a block matching the specified block number.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- Integer representing the number of transactions in the specified block, or `null` if no matching block number is found.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getBlockTransactionCountByNumber",
"params": [
"0xe8"
],
"id": 51
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getBlockTransactionCountByNumber",
"params": [
"0xe8"
],
"id": 51
}
```
```json
{
"jsonrpc": "2.0",
"id": 51,
"result": "0x8"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block(number:232){transactionCount}}"
}'
```
```text
{
block(number: 232) {
transactionCount
}
}
```
```json
{
"data": {
"block": {
"transactionCount": 1
}
}
}
```
---
## `eth_getUncleByBlockHashAndIndex`
Returns uncle specified by block hash and index.
### Parameters
- `block`: _string_ - 32-byte block hash.
- `uncleIndex`: _string_ - Index of the uncle.
### Returns
- Block object.
- `number`: _quantity, integer_ - Block number. `null` when block is pending.
- `hash`: _data, 32 bytes_ - Hash of the block. `null` when block is pending.
- `mixHash`: _data, 32 bytes_ - For pre-[merge](https://ethereum.org/roadmap/merge/) blocks, the hash used to verify the proof of work. For post-merge blocks, the `prevRandao` value supplied by the consensus layer.
- `parentHash`: _data, 32 bytes_ - Hash of the parent block.
- `nonce`: _data, 8 bytes_ - Hash of the generated proof of work. `null` when block is pending.
- `sha3Uncles`: _data, 32 bytes_ - SHA3 of the uncle's data in the block.
- `logsBloom`: _data, 256 bytes_ - Bloom filter for the block logs. `null` when block is pending.
- `transactionsRoot`: _data, 32 bytes_ - Root of the transaction trie for the block.
- `stateRoot`: _data, 32 bytes_ - Root of the final state trie for the block.
- `receiptsRoot`: _data, 32 bytes_ - Root of the receipts trie for the block.
- `miner`: _data, 20 bytes_ - Address to pay mining rewards to.
- `difficulty`: _quantity, integer_ - Difficulty for this block.
- `totalDifficulty`: _quantity, integer_ - Total difficulty of the chain until this block. Only present for pre-[merge](https://ethereum.org/roadmap/merge/) blocks. This value will always be `0` for an uncle block.
- `extraData`: _data_ - Extra data field for this block. The first 32 bytes is vanity data you can set using the [`--miner-extra-data`](../../options.md#miner-extra-data) command line option. Stores extra data when used with [IBFT](../../../../private-networks/how-to/configure/consensus/ibft.md#genesis-file).
- `size`: _quantity, integer_ - Size of block in bytes.
- `gasLimit`: _quantity_ - Maximum gas allowed in this block.
- `gasUsed`: _quantity_ - Total gas used by all transactions in this block.
- `timestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) for block assembly.
- `transactions`: _array_ - Array of transaction objects, or 32 byte transaction hashes depending on the specified boolean parameter.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
- `uncles`: _array_ - Array of uncle hashes.
- `baseFeePerGas`: _quantity_ - The block's [base fee per gas](../../../concepts/transactions/types.md#eip1559-transactions). Only present for blocks created after [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559).
- `withdrawalsRoot`: _data, 32 bytes_ - Root of the withdrawals trie for the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `withdrawals`: _array_ - Array of validator withdrawal objects included in the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `index`: _quantity_ - Index of the withdrawal.
- `validatorIndex`: _quantity_ - Index of the validator that initiated the withdrawal.
- `address`: _data, 20 bytes_ - Address the withdrawal was sent to.
- `amount`: _quantity_ - Amount withdrawn, in Gwei.
- `blobGasUsed`: _quantity_ - Total blob gas used by the transactions in this block. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `excessBlobGas`: _quantity_ - Running total of excess blob gas used to calculate the blob base fee for subsequent blocks. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `parentBeaconBlockRoot`: _data, 32 bytes_ - Root of the parent beacon block, which exposes beacon chain state to the EVM. Only present for blocks created after [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) (Cancun).
- `requestsHash`: _data, 32 bytes_ - Hash of the general purpose execution layer requests (for example, deposits, withdrawals, and consolidations) included in the block. Only present for blocks created after [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) (Prague).
:::note
Uncles don't contain individual transactions.
:::
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getUncleByBlockHashAndIndex",
"params": [
"0xc48fb64230a82f65a08e7280bd8745e7fea87bc7c206309dee32209fe9a985f7",
"0x0"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getUncleByBlockHashAndIndex",
"params": [
"0xc48fb64230a82f65a08e7280bd8745e7fea87bc7c206309dee32209fe9a985f7",
"0x0"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"difficulty": "0x76b123df93230",
"extraData": "0x50505945206e616e6f706f6f6c2e6f7267",
"gasLimit": "0x7a121d",
"gasUsed": "0x7a0175",
"hash": "0xc20189c0b1a4a23116ab3b177e929137f6e826f17fc4c2e880e7258c620e9817",
"logsBloom": "0x890086c024487ca422be846a201a10e41bc2882902312116c1119609482031e9c000e2a708004a10281024028020c505727a12570c4810121c59024490b040894406a1c23c37a0094810921da3923600c71c03044b40924280038d07ab91964a008084264a01641380798840805a284cce201a8026045451002500113a00de441001320805ca2840037000111640d090442c11116d2112948084240242340400236ce81502063401dcc214b9105194d050884721c1208800b20501a4201400276004142f118e60808284506979a86e050820101c170c185e2310005205a82a2100382422104182090184800c02489e033440218142140045801c024cc1818485",
"miner": "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5",
"mixHash": "0xf557cc827e058862aa3ea1bd6088fb8766f70c0eac4117c56cf85b7911f82a14",
"nonce": "0xd320b48904347cdd",
"number": "0x768964",
"parentHash": "0x98d752708b3677df8f439c4529f999b94663d5494dbfc08909656db3c90f6255",
"receiptsRoot": "0x0f838f0ceb73368e7fc8d713a7761e5be31e3b4beafe1a6875a7f275f82da45b",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x21a",
"stateRoot": "0xa0c7d4fca79810c89c517eff8dadb9c6d6f4bcc27c2edfb301301e1cf7dec642",
"timestamp": "0x5cdcbba6",
"totalDifficulty": "0x229ad33cabd4c40d23d",
"transactionsRoot": "0x866e38e91d01ef0387b8e07ccf35cd910224271ccf2b7477b8c8439e8b70f365",
"uncles": []
}
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block(hash:\"0xc48fb64230a82f65a08e7280bd8745e7fea87bc7c206309dee32209fe9a985f7\"){ ommerAt(index: 0) {difficulty extraData gasLimit gasUsed hash logsBloom mixHash nonce number receiptsRoot stateRoot timestamp totalDifficulty transactionsRoot}}}"
}'
```
```text
{
block(hash: "0xc48fb64230a82f65a08e7280bd8745e7fea87bc7c206309dee32209fe9a985f7") {
ommerAt(index: 0) {
difficulty
extraData
gasLimit
gasUsed
hash
logsBloom
mixHash
nonce
number
receiptsRoot
stateRoot
timestamp
totalDifficulty
transactionsRoot
}
}
}
```
```json
{
"data": {
"block": {
"difficulty": "0x1",
"extraData": "0xf882a00000000000000000000000000000000000000000000000000000000000000000d5949811ebc35d7b06b3fa8dc5809a1f9c52751e1deb808400000000f843b8418e98ef756acdae1e510b1df4b507b7af04eb3802db7fa0f3e73e7d0721b3645e76f4eb3d0dbf0de75620c4405bd5a663247cdd9616482c883053856d857f884a01",
"gasLimit": 4700000,
"gasUsed": 0,
"hash": "0x0efe67972b982eb6be5df84e5238eb07475f86afa8a7de708f6a13ac0ff60d6c",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"nonce": "0x0000000000000000",
"number": 200,
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot": "0xd650578a04b39f50cc979155f4510ec28c2c0a7c1e5fdbf84609bc7b1c430f48",
"timestamp": "0x5cd109fb",
"totalDifficulty": "0xc9",
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}
}
}
```
---
## `eth_getUncleByBlockNumberAndIndex`
Returns uncle specified by block number and index.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
- `uncleIndex`: _string_ - Index of the uncle.
### Returns
- Block object.
- `number`: _quantity, integer_ - Block number. `null` when block is pending.
- `hash`: _data, 32 bytes_ - Hash of the block. `null` when block is pending.
- `mixHash`: _data, 32 bytes_ - For pre-[merge](https://ethereum.org/roadmap/merge/) blocks, the hash used to verify the proof of work. For post-merge blocks, the `prevRandao` value supplied by the consensus layer.
- `parentHash`: _data, 32 bytes_ - Hash of the parent block.
- `nonce`: _data, 8 bytes_ - Hash of the generated proof of work. `null` when block is pending.
- `sha3Uncles`: _data, 32 bytes_ - SHA3 of the uncle's data in the block.
- `logsBloom`: _data, 256 bytes_ - Bloom filter for the block logs. `null` when block is pending.
- `transactionsRoot`: _data, 32 bytes_ - Root of the transaction trie for the block.
- `stateRoot`: _data, 32 bytes_ - Root of the final state trie for the block.
- `receiptsRoot`: _data, 32 bytes_ - Root of the receipts trie for the block.
- `miner`: _data, 20 bytes_ - Address to pay mining rewards to.
- `difficulty`: _quantity, integer_ - Difficulty for this block.
- `totalDifficulty`: _quantity, integer_ - Total difficulty of the chain until this block. Only present for pre-[merge](https://ethereum.org/roadmap/merge/) blocks. This value will always be `0` for an uncle block.
- `extraData`: _data_ - Extra data field for this block. The first 32 bytes is vanity data you can set using the [`--miner-extra-data`](../../options.md#miner-extra-data) command line option. Stores extra data when used with [IBFT](../../../../private-networks/how-to/configure/consensus/ibft.md#genesis-file).
- `size`: _quantity, integer_ - Size of block in bytes.
- `gasLimit`: _quantity_ - Maximum gas allowed in this block.
- `gasUsed`: _quantity_ - Total gas used by all transactions in this block.
- `timestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) for block assembly.
- `transactions`: _array_ - Array of transaction objects, or 32 byte transaction hashes depending on the specified boolean parameter.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
- `uncles`: _array_ - Array of uncle hashes.
- `baseFeePerGas`: _quantity_ - The block's [base fee per gas](../../../concepts/transactions/types.md#eip1559-transactions). Only present for blocks created after [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559).
- `withdrawalsRoot`: _data, 32 bytes_ - Root of the withdrawals trie for the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `withdrawals`: _array_ - Array of validator withdrawal objects included in the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `index`: _quantity_ - Index of the withdrawal.
- `validatorIndex`: _quantity_ - Index of the validator that initiated the withdrawal.
- `address`: _data, 20 bytes_ - Address the withdrawal was sent to.
- `amount`: _quantity_ - Amount withdrawn, in Gwei.
- `blobGasUsed`: _quantity_ - Total blob gas used by the transactions in this block. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `excessBlobGas`: _quantity_ - Running total of excess blob gas used to calculate the blob base fee for subsequent blocks. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `parentBeaconBlockRoot`: _data, 32 bytes_ - Root of the parent beacon block, which exposes beacon chain state to the EVM. Only present for blocks created after [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) (Cancun).
- `requestsHash`: _data, 32 bytes_ - Hash of the general purpose execution layer requests (for example, deposits, withdrawals, and consolidations) included in the block. Only present for blocks created after [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) (Prague).
:::note
Uncles don't contain individual transactions.
:::
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getUncleByBlockNumberAndIndex",
"params": [
"0x7689D2",
"0x0"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getUncleByBlockNumberAndIndex",
"params": [
"0x7689D2",
"0x0"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"difficulty": "0x77daec467bf93",
"extraData": "0x50505945206e616e6f706f6f6c2e6f7267",
"gasLimit": "0x7a121d",
"gasUsed": "0x7a0f7b",
"hash": "0x42d83ae9c0743f4b1f9c61ff7ea8b164c1bab3627decd49233760680be006ecf",
"logsBloom": "0x888200800000340120220008640200500408006100038400100581c000080240080a0014e8002010080004088040004022402a000c18010001400100002a041141a0610a0052900600041018c0002a0003090020404c00206010010513d00020005380124e08050480710000000108401012b0901c1424006000083a10a8c1040100a0440081050210124400040044304070004001100000012600806008061d0320800000b40042160600002480000000800000c0002100200940801c000820800048024904710000400640490026000a44300309000286088010c2300060003011380006400200812009144042204810209020410a84000410520c08802941",
"miner": "0x52bc44d5378309ee2abf1539bf71de1b7d7be3b5",
"mixHash": "0xf977fcdb52868be410b75ef2becc35cc312f13ab0a6ce400ecd9d445f66fa3f2",
"nonce": "0x628b28403bf1e3d3",
"number": "0x7689d0",
"parentHash": "0xb32cfdfbf4adb05d30f02fcc6fe039cc6666402142954051c1a1cb9cc91aa11e",
"receiptsRoot": "0x9c7c8361d1a24ea2841432234c81974a9920d3eba2b2b1c496b5f925a95cb4ac",
"sha3Uncles": "0x7d972aa1b182b7e93f1db043f03fbdbfac6874fe7e67e162141bcc0aefa6336b",
"size": "0x21a",
"stateRoot": "0x74e97b77813146344d75acb5a52a006cc6dfaca678a10fb8a484a8443e919272",
"timestamp": "0x5cdcc0a7",
"totalDifficulty": "0x229b0583b4bd2698ca0",
"transactionsRoot": "0x1d21626afddf05e5866de66ca3fcd98f1caf5357eba0cc6ec675606e116a891b",
"uncles": []
}
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block(number:2587){ ommerAt(index: 0) {difficulty extraData gasLimit gasUsed hash logsBloom mixHash nonce number receiptsRoot stateRoot timestamp totalDifficulty transactionsRoot}}}"
}'
```
```text
{
block(number: 2587) {
ommerAt(index: 0) {
difficulty
extraData
gasLimit
gasUsed
hash
logsBloom
mixHash
nonce
number
receiptsRoot
stateRoot
timestamp
totalDifficulty
transactionsRoot
}
}
}
```
```json
{
"data": {
"block": {
"ommerAt": null
}
}
}
```
---
## `eth_getUncleCountByBlockHash`
Returns the number of uncles in a block from a block matching the given block hash.
### Parameters
- `block`: _string_ - 32-byte block hash.
### Returns
- Integer representing the number of uncles in the specified block.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getUncleCountByBlockHash",
"params": [
"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getUncleCountByBlockHash",
"params": [
"0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": 0x0
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block(hash:\"0x65c08d792e4192b9ece6b6f2390da7da464208b22d88490be8add9373917b426\"){ommerCount}}"
}'
```
```text
{
block(hash: "0x65c08d792e4192b9ece6b6f2390da7da464208b22d88490be8add9373917b426") {
ommerCount
}
}
```
```json
{
"data": {
"block": {
"ommerCount": 2
}
}
}
```
---
## `eth_getUncleCountByBlockNumber`
Returns the number of uncles in a block matching the specified block number.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- Integer representing the number of uncles in the specified block.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getUncleCountByBlockNumber",
"params": [
"0xe8"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getUncleCountByBlockNumber",
"params": [
"0xe8"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x1"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block(number:\"0x59fd\"){ommerCount}}"
}'
```
```text
{
block(number: "0x59fd") {
ommerCount
}
}
```
```json
{
"data": {
"block": {
"ommerCount": 0
}
}
}
```
---
## Client and network methods
These methods query client and network information, such as accounts, chain ID, protocol version, configuration, and sync status.
## `eth_accounts`
Returns a list of account addresses a client owns.
:::note
This method returns an empty object because Besu [doesn't support key management](../../../how-to/send-transactions.md) inside the client.
To provide access to your key store and then sign transactions, use [Web3Signer](https://docs.web3signer.consensys.net/) with Besu.
:::
### Parameters
- None
### Returns
- List of 20-byte account addresses owned by the client.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_accounts",
"params": [],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_accounts",
"params": [],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": []
}
```
---
## `eth_blockNumber`
Returns the index corresponding to the block number of the current chain head.
### Parameters
- None
### Returns
- Hexadecimal integer representing the index corresponding to the block number of the current chain head.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 51
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 51
}
```
```json
{
"jsonrpc": "2.0",
"id": 51,
"result": "0x2377"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block{number}}"
}'
```
```text
{
block {
number
}
}
```
```json
{
"data": {
"block": {
"number": 16221
}
}
}
```
---
## `eth_capabilities`
Returns the node's data-serving capabilities.
### Parameters
- None
### Returns
- Capabilities information.
- `head`: _object_ - Current chain head information.
- `number`: _string_ - Current chain head block number.
- `hash`: _string_ - Current chain head block hash.
- `state`: _object_ - State capability information.
- `disabled`: _boolean_ - Indicates whether the `state` resource is disabled.
- `oldestBlock`: _string_ - (Optional) Oldest available block.
- `tx`: _object_ - Transaction capability information.
- `disabled`: _boolean_ - Indicates whether the `tx` resource is disabled.
- `oldestBlock`: _string_ - (Optional) Oldest available block.
- `logs`: _object_ - Logs capability information.
- `disabled`: _boolean_ - Indicates whether the `logs` resource is disabled.
- `oldestBlock`: _string_ - (Optional) Oldest available block.
- `receipts`: _object_ - Receipts capability information.
- `disabled`: _boolean_ - Indicates whether the `receipts` resource is disabled.
- `oldestBlock`: _string_ - (Optional) Oldest available block.
- `blocks`: _object_ - Blocks capability information.
- `disabled`: _boolean_ - Indicates whether the `blocks` resource is disabled.
- `oldestBlock`: _string_ - (Optional) Oldest available block.
- `stateproofs`: _object_ - State proofs capability information.
- `disabled`: _boolean_ - Indicates whether the `stateproofs` resource is disabled.
- `oldestBlock`: _string_ - (Optional) Oldest available block.
The `oldestBlock` field is included for block-backed resources when pruning has occurred.
If the full chain is available, this can be `0x0`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_capabilities",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_capabilities",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc":"2.0",
"id":1,
"result":{
"head":{
"number":"0x13f8e3a",
"hash":"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3"
},
"state":{
"disabled":false
},
"tx":{
"disabled":false,
"oldestBlock":"0x11b340a"
},
"logs":{
"disabled":false,
"oldestBlock":"0x11b340a"
},
"receipts":{
"disabled":false,
"oldestBlock":"0x11b340a"
},
"blocks":{
"disabled":false,
"oldestBlock":"0x0"
},
"stateproofs":{
"disabled":false
}
}
}
```
---
## `eth_chainId`
Returns the [chain ID](../../../concepts/network-and-chain-id.md).
### Parameters
- None
### Returns
- Chain ID in hexadecimal.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_chainId",
"params": [],
"id": 51
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_chainId",
"params": [],
"id": 51
}
```
```json
{
"jsonrpc": "2.0",
"id": 51,
"result": "0x7e2"
}
```
---
## `eth_config`
Returns the client's fork information for the current, next, and last known forks.
:::info
This method is defined in [EIP-7910](https://eips.ethereum.org/EIPS/eip-7910) and enables node operators to verify client readiness for upcoming forks and debug configuration mismatches.
:::
### Parameters
- None
### Returns
- Configuration information.
- `current`: _object_ - Current fork configuration.
- `activationTime`: _number_ - Fork activation timestamp (Unix epoch seconds).
- `blobSchedule`: _object_ - Blob configuration parameters.
- `baseFeeUpdateFraction`: _number_ - Base fee update fraction.
- `max`: _number_ - Maximum number of blobs per block.
- `target`: _number_ - Target number of blobs per block.
- `chainId`: _string_ - Chain ID in hexadecimal.
- `forkId`: _string_ - Fork hash as defined in [EIP-6122](https://eips.ethereum.org/EIPS/eip-6122).
- `precompiles`: _object_ - Active precompiled contracts with names and addresses.
- `systemContracts`: _object_ - System contract addresses.
- `next`: _object_ - Next fork configuration, or `null` if no future fork is scheduled.
- `last`: _object_ - The furthest configured future fork configuration (the future fork with
the largest `activationTime` among the client's configured forks). If only one future fork is configured, `next` and `last` are the same object. `null` if no future fork is scheduled.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_config",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_config",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"current": {
"activationTime": 1746612311,
"blobSchedule": {
"baseFeeUpdateFraction": 5007716,
"max": 9,
"target": 6
},
"chainId": "0x1",
"forkId": "0xc376cf8b",
"precompiles": {
"BLAKE2F": "0x0000000000000000000000000000000000000009",
"BLS12_G1ADD": "0x000000000000000000000000000000000000000b",
"BLS12_G1MSM": "0x000000000000000000000000000000000000000c",
"BLS12_G2ADD": "0x000000000000000000000000000000000000000d",
"BLS12_G2MSM": "0x000000000000000000000000000000000000000e",
"BLS12_MAP_FP2_TO_G2": "0x0000000000000000000000000000000000000011",
"BLS12_MAP_FP_TO_G1": "0x0000000000000000000000000000000000000010",
"BLS12_PAIRING_CHECK": "0x000000000000000000000000000000000000000f",
"BN254_ADD": "0x0000000000000000000000000000000000000006",
"BN254_MUL": "0x0000000000000000000000000000000000000007",
"BN254_PAIRING": "0x0000000000000000000000000000000000000008",
"ECREC": "0x0000000000000000000000000000000000000001",
"ID": "0x0000000000000000000000000000000000000004",
"KZG_POINT_EVALUATION": "0x000000000000000000000000000000000000000a",
"MODEXP": "0x0000000000000000000000000000000000000005",
"RIPEMD160": "0x0000000000000000000000000000000000000003",
"SHA256": "0x0000000000000000000000000000000000000002"
},
"systemContracts": {
"BEACON_ROOTS_ADDRESS": "0x000f3df6d732807ef1319fb7b8bb8522d0beac02",
"CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS": "0x0000bbddc7ce488642fb579f8b00f3a590007251",
"DEPOSIT_CONTRACT_ADDRESS": "0x00000000219ab540356cbb839cbe05303d7705fa",
"HISTORY_STORAGE_ADDRESS": "0x0000f90827f1c53a10cb7a02335b175320002935",
"WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS": "0x00000961ef480eb55e80d19ad83579a64c007002"
}
},
"next": null,
"last": null
}
}
```
---
## `eth_protocolVersion`
Returns current Ethereum protocol version.
### Parameters
- None
### Returns
- Ethereum protocol version.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_protocolVersion",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_protocolVersion",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x3f"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{protocolVersion}"
}'
```
```text
{
protocolVersion
}
```
```json
{
"data": {
"protocolVersion": 63
}
}
```
---
## `eth_syncing`
Returns an object with data about the synchronization status, or `false` if not synchronizing.
:::note
Once the node reaches the head of the chain, `eth_syncing` returns `false`, indicating that there is no active syncing target.
:::
### Parameters
- None
### Returns
- Synchronization status data object, or `false` if not synchronizing.
- `startingBlock`: _string_ - Index of the highest block on the blockchain when the network synchronization starts.
- `currentBlock`: _string_ - Index of the latest block (also known as the best block) for the current node (this is the same index that [`eth_blockNumber`](#eth_blocknumber) returns.)
- `highestBlock`: _string_ - Index of the highest known block in the peer network (that is, the highest block so far discovered among peer nodes. This is the same value as `currentBlock` if the current node has no peers.)
- `pulledStates`: _string_ - The number of state entries fetched so far, or `null` if this is not known or not relevant (if
[full syncing](../../../concepts/node-sync.md#full-synchronization) or fully synchronized, this field is not returned.)
- `knownStates`: _string_ - The number of states the node knows of so far, or `null` if this is not known or not relevant (if
[full syncing](../../../concepts/node-sync.md#full-synchronization) or fully synchronized, this field is not returned.)
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_syncing",
"params": [],
"id": 51
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_syncing",
"params": [],
"id": 51
}
```
```json
{
"jsonrpc": "2.0",
"id": 51,
"result": {
"startingBlock": "0x0",
"currentBlock": "0x1518",
"highestBlock": "0x9567a3",
"pulledStates": "0x203ca",
"knownStates": "0x200636"
}
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{syncing{startingBlock currentBlock highestBlock pulledStates knownStates}}"
}'
```
```text
{
syncing {
startingBlock
currentBlock
highestBlock
pulledStates
knownStates
}
}
```
```json
{
"data": {
"syncing": {
"startingBlock": 0,
"currentBlock": 5400,
"highestBlock": 9791395,
"pullStates": 132042,
"knownStates": 2098742
}
}
}
```
---
## Execution methods
These methods execute calls, create access lists, estimate gas, and simulate transactions without submitting them to the network.
## `eth_call`
Invokes a contract function locally and does not change the state of the blockchain.
You can interact with contracts using [`eth_sendRawTransaction`](submit.md#eth_sendrawtransaction) or `eth_call`.
By default, the `eth_call` error response includes the [revert reason](../../../../private-networks/how-to/send-transactions/revert-reason.md).
### Parameters
- `call`: _object_ - Transaction call object.
- `from`: _data, 20 bytes_ - Address of the sender.
- `to`: _data, 20 bytes_ - Address of the action receiver.
- `gas`: _integer_ - Gas provided by the sender. `eth_call` consumes zero gas, but other executions might need this parameter. `eth_estimateGas` ignores this value.
- `gasPrice`: _integer_ - Gas price, in Wei, provided by the sender. The default is `0`. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _integer_ - Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Can be used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxFeePerGas`.
- `maxFeePerGas`: _integer_ - Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Can be used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxPriorityFeePerGas`.
- `maxFeePerBlobGas`: _integer_ - Maximum fee the sender is willing to pay per blob gas. Only used for blob transactions introduced in [EIP-4844]( https://eips.ethereum.org/EIPS/eip-4844).
- `nonce`: _integer_ - Number of transactions made by the sender before this one. The default is the sender's nonce.
- `value`: _integer_ - Value transferred, in Wei.
- `data`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `input` if both parameters are provided.
- `input`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `data` if both parameters are provided.
- `accessList`: _array_ - List of addresses and storage keys that the transaction plans to access. Used only in non-[`FRONTIER`](../../../concepts/transactions/types.md#frontier-transactions) transactions.
- `strict`: _boolean_ - Determines if the sender account balance is considered during gas estimation. If `true`, the sender's balance is checked against the transaction's gas parameters. This ensures the estimated gas reflects what the sender can actually afford. If `false`, the balance checks are skipped. The default is `true`.
- `blobVersionedHashes`: _array_ - List of references to blobs introduced in [EIP-4844]( https://eips.ethereum.org/EIPS/eip-4844).
:::note
If you don't want the sender account balance checked, set the gas to zero or specify
`strict:false`. Otherwise the call may fail if the sender account
does not have sufficient funds to cover the gas fees.
:::
- `blockNumber` or `blockHash`: _string_ - Hexadecimal integer representing a block number,
block hash, or one of the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as
described in [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
- `stateOverride`: _object_ - (Optional) The address-to-state mapping.
Each entry specifies a state that will be temporarily overridden before executing the call.
This allows you to test, analyze, and debug smart contracts more efficiently by allowing
temporary state changes without affecting the actual blockchain state.
- `balance`: _quantity_ - Temporary account balance for the call execution.
- `nonce`: _quantity_ - Temporary nonce value for the call execution.
- `code`: _binary_ - Bytecode to inject into the account.
- `movePrecompileToAddress`: _data, 20 bytes_ - Address to which the precompile address should be moved.
- `state`: _quantity_ - `key:value` pairs to override all slots in the account storage. You cannot set both the `state` and `stateDiff` options simultaneously.
- `stateDiff`: _quantity_ - `key:value` pairs to override individual slots in the account storage. You cannot set both the `state` and `stateDiff` options simultaneously.
### Returns
- Return value of the executed contract.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"to": "0x69498dd54bd25aa0c886cf1f8b8ae0856d55ff13",
"value": "0x1"
},
"latest"
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"to": "0x69498dd54bd25aa0c886cf1f8b8ae0856d55ff13",
"value": "0x1"
},
"latest"
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": "0x"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block {number call (data : {from : \"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b\", to: \"0x69498dd54bd25aa0c886cf1f8b8ae0856d55ff13\", data :\"0x12a7b914\"}){data status}}}"
}'
```
```text
{
block {
number
call(data: {from: "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b", to: "0x69498dd54bd25aa0c886cf1f8b8ae0856d55ff13", data: "0x12a7b914"}) {
data
status
}
}
}
```
```json
{
"data": {
"block": {
"number": 17449,
"call": {
"data": "0x",
"status": 1
}
}
}
}
```
The following example creates a simulated contract by not including the `to` parameter from the
transaction call object in the `call` parameter.
Besu simulates the data to create the contract.
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"data": "0x6080604052336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561005057600080fd5b5061021e806100606000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806101b76033913960400191505060405180910390fd5b806001819055505056fe546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572a265627a7a7231582007302f208a10686769509b529e1878bda1859883778d70dedd1844fe790c9bde64736f6c63430005100032",
"gas": "0x439cf",
"gasPrice": "0x0"
},
"latest"
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c8063445df0ac146100465780638da5cb5b14610064578063fdacd576146100ae575b600080fd5b61004e6100dc565b6040518082815260200191505060405180910390f35b61006c6100e2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100da600480360360208110156100c457600080fd5b8101908080359060200190929190505050610107565b005b60015481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806101b76033913960400191505060405180910390fd5b806001819055505056fe546869732066756e6374696f6e206973207265737472696374656420746f2074686520636f6e74726163742773206f776e6572a265627a7a7231582007302f208a10686769509b529e1878bda1859883778d70dedd1844fe790c9bde64736f6c63430005100032"
}
```
The following example checks the USDT contract for the balance of the address `0xfe3b557e8fb62b89f4916b721be55ceb828dbd73`, with
a state override that sets the balance to 20,000 USDT. The result will reflect the overridden balance
for the specified address.
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"to": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"data": "0x70a08231000000000000000000000000fe3b557e8fb62b89f4916b721be55ceb828dbd73"
},
"latest",
{
"0xdAC17F958D2ee523a2206206994597C13D831ec7": {
"stateDiff": {
"0xd0dd44a13782bf89714335c2b2b08ecb7c074e78a161807742c578965dda1b56": "0x0000000000000000000000000000000000000000000000000000000000004E20"
}
}
}
],
"id": 1
}'
```
```json
{
"jsonrpc":"2.0",
"id":1,
"result":"0x0000000000000000000000000000000000000000000000000000000000004e20"
}
```
---
## `eth_createAccessList`
Creates an [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) access list that you can [include in a transaction](../../../concepts/transactions/types.md#access_list-transactions). The method returns a success response (access list and gas used) even if the simulated transaction would revert.
### Parameters
- `transaction`: _object_ - Transaction call object.
- `from`: _data, 20 bytes_ - Address of the sender.
- `to`: _data, 20 bytes_ - Address of the action receiver.
- `gas`: _integer_ - Gas provided by the sender. `eth_call` consumes zero gas, but other executions might need this parameter. `eth_estimateGas` ignores this value.
- `gasPrice`: _integer_ - Gas price, in Wei, provided by the sender. The default is `0`. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _integer_ - Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Can be used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxFeePerGas`.
- `maxFeePerGas`: _integer_ - Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Can be used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxPriorityFeePerGas`.
- `maxFeePerBlobGas`: _integer_ - Maximum fee the sender is willing to pay per blob gas. Only used for blob transactions introduced in [EIP-4844]( https://eips.ethereum.org/EIPS/eip-4844).
- `nonce`: _integer_ - Number of transactions made by the sender before this one. The default is the sender's nonce.
- `value`: _integer_ - Value transferred, in Wei.
- `data`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `input` if both parameters are provided.
- `input`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `data` if both parameters are provided.
- `accessList`: _array_ - List of addresses and storage keys that the transaction plans to access. Used only in non-[`FRONTIER`](../../../concepts/transactions/types.md#frontier-transactions) transactions.
- `strict`: _boolean_ - Determines if the sender account balance is considered during gas estimation. If `true`, the sender's balance is checked against the transaction's gas parameters. This ensures the estimated gas reflects what the sender can actually afford. If `false`, the balance checks are skipped. The default is `true`.
- `blobVersionedHashes`: _array_ - List of references to blobs introduced in [EIP-4844]( https://eips.ethereum.org/EIPS/eip-4844).
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
### Returns
- Access list object.
- `accessList`: _array_ of _objects_ - List of objects.
- `address`: _string_ - Addresses to be accessed by the transaction.
- `storageKeys`: _array_ - Storage keys to be accessed by the transaction.
- `gasUsed`: _string_ - Approximate gas cost for the transaction if the access list is included.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"method": "eth_createAccessList",
"params": [
{
"from": "0xaeA8F8f781326bfE6A7683C2BD48Dd6AA4d3Ba63",
"data": "0x608060806080608155"
},
"pending"
],
"id": 1,
"jsonrpc": "2.0"
}'
```
```json
{
"method": "eth_createAccessList",
"params": [
{
"from": "0xaeA8F8f781326bfE6A7683C2BD48Dd6AA4d3Ba63",
"data": "0x608060806080608155"
},
"pending"
],
"id": 1,
"jsonrpc": "2.0"
}
```
```json
{
"accessList": [
{
"address": "0xa02457e5dfd32bda5fc7e1f1b008aa5979568150",
"storageKeys": [
"0x0000000000000000000000000000000000000000000000000000000000000081",
]
}
]
"gasUsed": "0x125f8"
}
```
:::tip
This method doesn't indicate whether a transaction would succeed or revert; to see simulation outcomes
use [`eth_call`](#eth_call) or [`eth_estimateGas`](#eth_estimategas).
:::
---
## `eth_estimateGas`
Returns an estimate of the gas required for a transaction to complete. The estimation process does not use gas and the transaction is not added to the blockchain. The resulting estimate can be greater than the amount of gas the transaction ends up using, for reasons including EVM mechanics and node performance.
The `eth_estimateGas` call does not send a transaction. You must call [`eth_sendRawTransaction`](submit.md#eth_sendrawtransaction) to execute the transaction.
By default, the `eth_estimateGas` error response includes the [revert reason](../../../../private-networks/how-to/send-transactions/revert-reason.md).
### Parameters
- `call`: _object_ - Transaction call object.
- `from`: _data, 20 bytes_ - Address of the sender.
- `to`: _data, 20 bytes_ - Address of the action receiver.
- `gas`: _integer_ - Gas provided by the sender. `eth_call` consumes zero gas, but other executions might need this parameter. `eth_estimateGas` ignores this value.
- `gasPrice`: _integer_ - Gas price, in Wei, provided by the sender. The default is `0`. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _integer_ - Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Can be used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxFeePerGas`.
- `maxFeePerGas`: _integer_ - Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Can be used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxPriorityFeePerGas`.
- `maxFeePerBlobGas`: _integer_ - Maximum fee the sender is willing to pay per blob gas. Only used for blob transactions introduced in [EIP-4844]( https://eips.ethereum.org/EIPS/eip-4844).
- `nonce`: _integer_ - Number of transactions made by the sender before this one. The default is the sender's nonce.
- `value`: _integer_ - Value transferred, in Wei.
- `data`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `input` if both parameters are provided.
- `input`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `data` if both parameters are provided.
- `accessList`: _array_ - List of addresses and storage keys that the transaction plans to access. Used only in non-[`FRONTIER`](../../../concepts/transactions/types.md#frontier-transactions) transactions.
- `strict`: _boolean_ - Determines if the sender account balance is considered during gas estimation. If `true`, the sender's balance is checked against the transaction's gas parameters. This ensures the estimated gas reflects what the sender can actually afford. If `false`, the balance checks are skipped. The default is `true`.
- `blobVersionedHashes`: _array_ - List of references to blobs introduced in [EIP-4844]( https://eips.ethereum.org/EIPS/eip-4844).
:::note
If you don't want the sender account balance checked, set the gas to zero or specify
`strict:false`. Otherwise the call may fail if the sender account
does not have sufficient funds to cover the gas fees.
:::
- `blockNumber`: _string_ - (Optional) Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter)
The default is `pending`.
- `stateOverride`: _object_ - The address-to-state mapping.
Each entry specifies a state that will be temporarily overridden before executing the call.
This allows you to make temporary state changes without affecting the actual blockchain state.
- `balance`: _quantity_ - Temporary account balance for the call execution.
- `nonce`: _quantity_ - Temporary nonce value for the call execution.
- `code`: _binary_ - Bytecode to inject into the account.
- `movePrecompileToAddress`: _data, 20 bytes_ - Address to which the precompile address should be moved.
- `state`: _quantity_ - `key:value` pairs to override all slots in the account storage. You cannot set both the `state` and `stateDiff` options simultaneously.
- `stateDiff`: _quantity_ - `key:value` pairs to override individual slots in the account storage. You cannot set both the `state` and `stateDiff` options simultaneously.
### Returns
- Amount of gas used.
### Example
The following example returns an estimate of 21000 wei (`0x5208`) for the transaction.
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"params": [
{
"from": "0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73",
"to": "0x44Aa93095D6749A706051658B970b941c72c1D53",
"value": "0x1"
}
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"params": [
{
"from": "0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73",
"to": "0x44Aa93095D6749A706051658B970b941c72c1D53",
"value": "0x1"
}
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": "0x5208"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block{estimateGas (data: {from :\"0x6295ee1b4f6dd65047762f924ecd367c17eabf8f\", to :\"0x8888f1f195afa192cfee860698584c030f4c9db1\"})}}"
}'
```
```text
{
block {
estimateGas(data: {from: "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f", to: "0x8888f1f195afa192cfee860698584c030f4c9db1"})
}
}
```
```json
{
"data": {
"block": {
"estimateGas": 21000
}
}
}
```
The following example request estimates the cost of deploying a simple storage smart contract to the network. The data field contains the hash of the compiled contract you want to deploy. (You can get the compiled contract hash from your IDE, for example, **Remix > Compile tab > details > WEB3DEPLOY**.) The result is 113355 wei.
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"params": [
{
"from": "0x8bad598904ec5d93d07e204a366d084a80c7694e",
"data": "0x608060405234801561001057600080fd5b5060e38061001f6000396000f3fe6080604052600436106043576000357c0100000000000000000000000000000000000000000000000000000000900480633fa4f24514604857806355241077146070575b600080fd5b348015605357600080fd5b50605a60a7565b6040518082815260200191505060405180910390f35b348015607b57600080fd5b5060a560048036036020811015609057600080fd5b810190808035906020019092919050505060ad565b005b60005481565b806000819055505056fea165627a7a7230582020d7ad478b98b85ca751c924ef66bcebbbd8072b93031073ef35270a4c42f0080029"
}
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x1bacb"
}
```
The following example estimates the gas required for the `transfer` call in the USDT contract, with a state
override that sets the balance of the sender address to 20,000 USDT. The result provides the gas required
for the transaction.
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_estimateGas",
"params": [
{
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"to": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"data": "0xa9059cbb000000000000000000000000627306090abaB3A6e1400e9345bC60c78a8BEf570000000000000000000000000000000000000000000000000000000000000064"
},
"latest",
{
"0xdAC17F958D2ee523a2206206994597C13D831ec7": {
"stateDiff": {
"0xd0dd44a13782bf89714335c2b2b08ecb7c074e78a161807742c578965dda1b56": "0x0000000000000000000000000000000000000000000000000000000000004E20"
}
}
}
],
"id": 1
}'
```
```json
{
"jsonrpc":"2.0",
"id":1,
"result":"0xfa07"
}
```
---
## `eth_simulateV1`
Simulates transactions across multiple blocks. Allows you to test transactions with custom state and
block parameters without submitting them to the network.
### Parameters
- `payload`: _object_ - Transaction simulation payload object.
- `blockStateCalls`: _array_ of _objects_ - List of block state call objects.
- `blockOverrides`: _array_ of _objects_ - List of block override objects.
- `baseFeePerGas`: _quantity_ - Base fee per gas for the block.
- `blobBaseFee`: _quantity_ - Base fee per unit of blob gas.
- `feeRecipient`: _data, 20 bytes_ - Address of the fee recipient for the block proposal.
- `gasLimit`: _quantity_ - Maximum gas allowed in this block.
- `number`: _quantity_ - Block number. When overriding block numbers across multiple blocks, block number must be increasing. By default, it's incremented by one for each block.
- `prevRandao`: _data, 32 bytes_ - Previous value of randomness.
- `time`: _quantity_ - Unix epoch time in seconds. Time must increase or remain constant relative to the previous block. By default, it's incremented by one for each block.
- `withdrawals`: _array_ - Array of withdrawals made by validators. This array can have a maximum length of 16.
- `stateOverrides`: _array_ of _objects_ - List of state override objects.
- `balance`: _quantity_ - Temporary account balance for the call execution.
- `nonce`: _quantity_ - Temporary nonce value for the call execution.
- `code`: _binary_ - Bytecode to inject into the account.
- `movePrecompileToAddress`: _data, 20 bytes_ - Address to which the precompile address should be moved.
- `state`: _quantity_ - `key:value` pairs to override all slots in the account storage. You cannot set both the `state` and `stateDiff` options simultaneously.
- `stateDiff`: _quantity_ - `key:value` pairs to override individual slots in the account storage. You cannot set both the `state` and `stateDiff` options simultaneously.
- `calls`: _array_ of _objects_ - List of transaction call objects.
- `from`: _data, 20 bytes_ - Address of the sender.
- `to`: _data, 20 bytes_ - Address of the action receiver.
- `gas`: _quantity, integer_ - Gas provided by the sender. `eth_call` consumes zero gas, but other executions might need this parameter. `eth_estimateGas` ignores this value.
- `gasPrice`: _quantity, integer_ - Gas price, in Wei, provided by the sender. The default is `0`. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Can be used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxFeePerGas`.
- `maxFeePerGas`: _quantity, integer_ - Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Can be used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxPriorityFeePerGas`.
- `maxFeePerBlobGas`: _quantity, integer_ - Maximum fee the sender is willing to pay per blob gas. Only used for blob transactions introduced in [EIP-4844]( https://eips.ethereum.org/EIPS/eip-4844).
- `nonce`: _quantity, integer_ - Number of transactions made by the sender before this one. The default is the sender's nonce.
- `value`: _quantity, integer_ - Value transferred, in Wei.
- `data`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `input` if both parameters are provided.
- `input`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `data` if both parameters are provided.
- `accessList`: _array_ - List of addresses and storage keys that the transaction plans to access. Used only in non-[`FRONTIER`](../../../concepts/transactions/types.md#frontier-transactions) transactions.
- `strict`: _tag_ - Determines if the sender account balance is considered during gas estimation. If `true`, the sender's balance is checked against the transaction's gas parameters. This ensures the estimated gas reflects what the sender can actually afford. If `false`, the balance checks are skipped. The default is `true`.
- `blobVersionedHashes`: _array_ - List of references to blobs introduced in [EIP-4844]( https://eips.ethereum.org/EIPS/eip-4844).
- `traceTransfers`: _boolean_ - (Optional) If `true`, ETH transfers are added as ERC-20 transfer
events to the logs, allowing you to trace value transfers. The default is `false`.
- `validation`: _boolean_ - (Optional) If `true`, `eth_simulateV1` does all the validation that a
normal EVM would do, except contract sender and signature checks. If `false`, `eth_simulateV1` behaves like `eth_call`.
The default is `false`.
- `returnFullTransactionObjects`: _boolean_ - (Optional) If `true`, returns full transaction
objects. If `false`, returns only hashes. The default is `false`.
- `blockNumber` or `blockHash`: _string_ - Hexadecimal integer representing a block number,
block hash, or one of the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as
described in [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
### Returns
- List of simulation result objects.
- All the fields of a block object.
- `number`: _quantity, integer_ - Block number. `null` when block is pending.
- `hash`: _data, 32 bytes_ - Hash of the block. `null` when block is pending.
- `mixHash`: _data, 32 bytes_ - For pre-[merge](https://ethereum.org/roadmap/merge/) blocks, the hash used to verify the proof of work. For post-merge blocks, the `prevRandao` value supplied by the consensus layer.
- `parentHash`: _data, 32 bytes_ - Hash of the parent block.
- `nonce`: _data, 8 bytes_ - Hash of the generated proof of work. `null` when block is pending.
- `sha3Uncles`: _data, 32 bytes_ - SHA3 of the uncle's data in the block.
- `logsBloom`: _data, 256 bytes_ - Bloom filter for the block logs. `null` when block is pending.
- `transactionsRoot`: _data, 32 bytes_ - Root of the transaction trie for the block.
- `stateRoot`: _data, 32 bytes_ - Root of the final state trie for the block.
- `receiptsRoot`: _data, 32 bytes_ - Root of the receipts trie for the block.
- `miner`: _data, 20 bytes_ - Address to pay mining rewards to.
- `difficulty`: _quantity, integer_ - Difficulty for this block.
- `totalDifficulty`: _quantity, integer_ - Total difficulty of the chain until this block. Only present for pre-[merge](https://ethereum.org/roadmap/merge/) blocks. This value will always be `0` for an uncle block.
- `extraData`: _data_ - Extra data field for this block. The first 32 bytes is vanity data you can set using the [`--miner-extra-data`](../../options.md#miner-extra-data) command line option. Stores extra data when used with [IBFT](../../../../private-networks/how-to/configure/consensus/ibft.md#genesis-file).
- `size`: _quantity, integer_ - Size of block in bytes.
- `gasLimit`: _quantity_ - Maximum gas allowed in this block.
- `gasUsed`: _quantity_ - Total gas used by all transactions in this block.
- `timestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) for block assembly.
- `transactions`: _array_ - Array of transaction objects, or 32 byte transaction hashes depending on the specified boolean parameter.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
- `uncles`: _array_ - Array of uncle hashes.
- `baseFeePerGas`: _quantity_ - The block's [base fee per gas](../../../concepts/transactions/types.md#eip1559-transactions). Only present for blocks created after [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559).
- `withdrawalsRoot`: _data, 32 bytes_ - Root of the withdrawals trie for the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `withdrawals`: _array_ - Array of validator withdrawal objects included in the block. Only present for blocks created after [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) (Shanghai).
- `index`: _quantity_ - Index of the withdrawal.
- `validatorIndex`: _quantity_ - Index of the validator that initiated the withdrawal.
- `address`: _data, 20 bytes_ - Address the withdrawal was sent to.
- `amount`: _quantity_ - Amount withdrawn, in Gwei.
- `blobGasUsed`: _quantity_ - Total blob gas used by the transactions in this block. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `excessBlobGas`: _quantity_ - Running total of excess blob gas used to calculate the blob base fee for subsequent blocks. Only present for blocks created after [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) (Cancun).
- `parentBeaconBlockRoot`: _data, 32 bytes_ - Root of the parent beacon block, which exposes beacon chain state to the EVM. Only present for blocks created after [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788) (Cancun).
- `requestsHash`: _data, 32 bytes_ - Hash of the general purpose execution layer requests (for example, deposits, withdrawals, and consolidations) included in the block. Only present for blocks created after [EIP-7685](https://eips.ethereum.org/EIPS/eip-7685) (Prague).
- `calls`: _array_ of _objects_ - List of call result objects.
- `returnData`: _data_ - Data returned for the call.
- `logs`: _array_ - Array of log objects generated during the call.
- `removed`: _tag_ - `true` if log removed because of a chain reorganization. `false` if a valid log.
- `logIndex`: _quantity, integer_ - Log index position in the block. `null` when log is pending.
- `transactionIndex`: _quantity, integer_ - Index position of the starting transaction for the log. `null` when log is pending.
- `transactionHash`: _data, 32 bytes_ - Hash of the starting transaction for the log. `null` when log is pending.
- `blockHash`: _data, 32 bytes_ - Hash of the block that includes the log. `null` when log is pending.
- `blockNumber`: _quantity_ - Number of block that includes the log. `null` when log is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded unix timestamp (in seconds) of the block that includes the log.
- `address`: _data, 20 bytes_ - Address the log originated from.
- `data`: _data_ - Non-indexed arguments of the log.
- `topics`: _array of data, 32 bytes each_ - [Event signature hash](../../../concepts/events-and-logs.md#event-signature-hash) and 0 to 3 [indexed log arguments](../../../concepts/events-and-logs.md#event-parameters).
- `gasUsed`: _quantity_ - Amount of gas used by the call.
- `maxUsedGas`: _quantity_ - Maximum gas used during the call before any refunds.
- `status`: _quantity_ - Status indicating whether the call succeeded (`0x1`). `0x0` indicates that a call has failed.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_simulateV1",
"params": [
{
"blockStateCalls": [
{
"blockOverrides": {
"baseFeePerGas": "0x9"
},
"stateOverrides": {
"0xc000000000000000000000000000000000000000": {
"balance": "0x4a817c800"
}
},
"calls": [
{
"from": "0xc000000000000000000000000000000000000000",
"to": "0xc000000000000000000000000000000000000001",
"maxFeePerGas": "0xf",
"value": "0x1"
},
{
"from": "0xc000000000000000000000000000000000000000",
"to": "0xc000000000000000000000000000000000000002",
"maxFeePerGas": "0xf",
"value": "0x1"
}
]
}
],
"validation": true,
"traceTransfers": true
},
"latest"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_simultateV1",
"params": [
{
"blockStateCalls": [
{
"blockOverrides": {
"baseFeePerGas": "0x9"
},
"stateOverrides": {
"0xc000000000000000000000000000000000000000": {
"balance": "0x4a817c800"
}
},
"calls": [
{
"from": "0xc000000000000000000000000000000000000000",
"to": "0xc000000000000000000000000000000000000001",
"maxFeePerGas": "0xf",
"value": "0x1"
},
{
"from": "0xc000000000000000000000000000000000000000",
"to": "0xc000000000000000000000000000000000000002",
"maxFeePerGas": "0xf",
"value": "0x1"
}
]
}
],
"validation": true,
"traceTransfers": true
},
"latest"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"baseFeePerGas": "0x9",
"blobGasUsed": "0x0",
"calls": [
{
"gasUsed": "0x5208",
"maxUsedGas": "0x7530",
"logs": [
{
"address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"blockHash": "0xc98388385b0dbfc15ad5c6a0f4b19f7abd94efb4618ced05e3eb320ee30b1e7f",
"blockNumber": "0x1496e50",
"data": "0x0000000000000000000000000000000000000000000000000000000000000001",
"logIndex": "0x0",
"removed": false,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000c000000000000000000000000000000000000000",
"0x000000000000000000000000c000000000000000000000000000000000000001"
],
"transactionHash": "0xe7217784e0c3f7b35d39303b1165046e9b7e8af9b9cf80d5d5f96c3163de8f51",
"transactionIndex": "0x0"
}
],
"returnData": "0x",
"status": "0x1"
},
{
"gasUsed": "0x5208",
"maxUsedGas": "0x7530",
"logs": [
{
"address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
"blockHash": "0xc98388385b0dbfc15ad5c6a0f4b19f7abd94efb4618ced05e3eb320ee30b1e7f",
"blockNumber": "0x1496e50",
"data": "0x0000000000000000000000000000000000000000000000000000000000000001",
"logIndex": "0x1",
"removed": false,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000c000000000000000000000000000000000000000",
"0x000000000000000000000000c000000000000000000000000000000000000002"
],
"transactionHash": "0xf0182201606ec03701ba3a07d965fabdb4b7d06b424f226ea7ec3581802fc6fa",
"transactionIndex": "0x1"
}
],
"returnData": "0x",
"status": "0x1"
}
],
"difficulty": "0x0",
"excessBlobGas": "0x4920000",
"extraData": "0x",
"gasLimit": "0x1c9c380",
"gasUsed": "0xa410",
"hash": "0xc98388385b0dbfc15ad5c6a0f4b19f7abd94efb4618ced05e3eb320ee30b1e7f",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x7e2a2fa2a064f693f0a55c5639476d913ff12d05",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x1496e50",
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash": "0xddd47e7383c8ced495e85e053f898d7a333feb0432fa9098306f6f563cde4984",
"receiptsRoot": "0x75308898d571eafb5cd8cde8278bf5b3d13c5f6ec074926de3bb895b519264e1",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x29c",
"stateRoot": "0xd6da11fae4ab94ddba2c4c71206962f7c6eaec6e5fabf00f3f7540c4ed7ad8f1",
"timestamp": "0x67803e64",
"transactions": [
"0xe7217784e0c3f7b35d39303b1165046e9b7e8af9b9cf80d5d5f96c3163de8f51",
"0xf0182201606ec03701ba3a07d965fabdb4b7d06b424f226ea7ec3581802fc6fa"
],
"transactionsRoot": "0x9bdb74f3ce41f5893a02a631e904ae0d21ae8c4e416786d8dbd9cb5c54f1dc0f",
"uncles": [],
"withdrawals": [],
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}
]
}
```
---
## Fee market methods
These methods query gas price and fee market information, including the base fee, blob base fee, fee history, and priority fees.
## `eth_baseFee`
Returns the base fee per gas for the next block in wei.
### Parameters
- None
### Returns
- Hexadecimal integer representing the base fee per gas for the next block in wei, or `null` if the network does not support [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_baseFee",
"params": [],
"id": 51
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_baseFee",
"params": [],
"id": 51
}
```
```json
{
"jsonrpc": "2.0",
"id": 51,
"result": "0x8"
}
```
---
## `eth_blobBaseFee`
Returns the base fee per blob gas in wei.
:::info
[Shard blob transactions](../../../concepts/transactions/types.md#blob-transactions) enable scaling Ethereum by allowing blobs of
data to be stored temporarily by consensus clients.
:::
### Parameters
- None
### Returns
- Hexadecimal integer representing the base fee per blob gas.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_blobBaseFee",
"params": [],
"id": 51
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_blobBaseFee",
"params": [],
"id": 51
}
```
```json
{
"jsonrpc": "2.0",
"id": 51,
"result": "0x3f5694c1f"
}
```
---
## `eth_feeHistory`
Returns base fee per gas and transaction effective priority fee per gas history for the requested block
range, allowing you to track trends over time.
As of [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), this method tracks transaction blob gas fees as well.
### Parameters
- `blockCount`: _integer_ or _string_ - Number of blocks in the requested range. Between 1 and 1024 blocks can be requested in a single query. If blocks in the specified block range are not available, then only the fee history for available blocks is returned. Accepts hexadecimal or integer values.
- `newestBlock`: _string_ - Hexadecimal integer representing the highest number block of
the requested range, or one of the string tags `latest`, `earliest`, `pending`, `finalized`, or
`safe`, as described in [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
- `array` of `integers` - (optional) A monotonically increasing list of percentile values to sample from each block's effective priority fees per gas in ascending order, weighted by gas used.
### Returns
- Fee history results object.
- `oldestBlock`: _quantity, integer_ - Lowest number block of the returned range.
- `baseFeePerGas`: _array_ - Array of block base fees per gas, including an extra block value. The extra value is the next block after the newest block in the returned range. Returns zeroes for blocks created before [EIP-1559](https://github.com/ethereum/EIPs/blob/2d8a95e14e56de27c5465d93747b0006bd8ac47f/EIPS/eip-1559.md).
- `baseFeePerBlobGas`: _array_ - Array of base fees per blob gas. Returns zeroes for blocks created before [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844).
- `gasUsedRatio`: _array_ - Array of block gas used ratios. These are calculated as the ratio of `gasUsed` and `gasLimit`.
- `blobGasUsedRatio`: _array_ - Array of blob gas used ratios. These are calculated as the ratio of `blobGasUsed` and the max blob gas per block.
- `reward`: _array_ - Array of effective priority fee per gas data points from a single block. All zeroes are returned if the block is empty.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_feeHistory",
"params": [
"0x5",
"latest",
[
20,
30
]
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_feeHistory",
"params": [
"0x5",
"latest",
[
20,
30
]
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"oldestBlock": "0x10b52f",
"baseFeePerGas": [
"0x3fa63a3f",
"0x37f999ee",
"0x3e36f20a",
"0x4099f79a",
"0x430d532d",
"0x46fcd4a4"
],
"baseFeePerBlobGas": [
"0x7b7609c19",
"0x6dbe41789",
"0x7223341d4",
"0x6574a002c",
"0x7223341d4",
"0x6574a002c"
],
"gasUsedRatio": [
0.017712333333333333,
0.9458865666666667,
0.6534561,
0.6517375666666667,
0.7347769666666667
],
"blobGasUsedRatio": [
0.0,
0.6666666666666666,
0.0,
1.0,
0.0
],
"reward": [
[
"0x3b9aca00",
"0x59682f00"
],
[
"0x3a13012",
"0x3a13012"
],
[
"0xf4240",
"0xf4240"
],
[
"0xf4240",
"0xf4240"
],
[
"0xf4240",
"0xf4240"
]
]
}
}
```
---
## `eth_gasPrice`
Returns a percentile gas unit price for the most recent blocks, in wei. By default, the last 100 blocks are examined and the 50th percentile gas unit price (that is, the median value) is returned.
If there are no blocks, the value for [`--min-gas-price`](../../options.md#min-gas-price) is returned. The value returned is restricted to values between [`--min-gas-price`](../../options.md#min-gas-price) and [`--api-gas-price-max`](../../options.md#api-gas-price-max). By default, 1000 wei and 500 gwei.
Use the [`--api-gas-price-blocks`](../../options.md#api-gas-price-blocks), [`--api-gas-price-percentile`](../../options.md#api-gas-price-percentile) , and [`--api-gas-price-max`](../../options.md#api-gas-price-max) command line options to configure the `eth_gasPrice` default values.
### Parameters
- None
### Returns
- Percentile gas unit price for the most recent blocks, in wei, as a hexadecimal value.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_gasPrice",
"params": [],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_gasPrice",
"params": [],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": "0x3e8"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{gasPrice}"
}'
```
```text
{
gasPrice
}
```
```json
{
"data": {
"gasPrice": "0x3e8"
}
}
```
---
## `eth_maxPriorityFeePerGas`
Returns an estimate of how much priority fee, in wei, you can pay to get a transaction included in the current block.
### Parameters
- None
### Returns
- Hexadecimal value in wei.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_maxPriorityFeePerGas",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_maxPriorityFeePerGas",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0xf4240"
}
```
---
## Filter and log methods
These methods create, poll, and remove filters, and query event logs.
## `eth_getFilterChanges`
Polls the specified filter and returns an array of changes that have occurred since the last poll.
### Parameters
- `filterId`: _string_ - Filter ID.
### Returns
- If nothing changed since the last poll, an empty list; otherwise:
- For filters created with `eth_newBlockFilter`, returns block hashes.
- For filters created with `eth_newPendingTransactionFilter`, returns transaction hashes.
- For filters created with `eth_newFilter`, returns log objects.
- `removed`: _tag_ - `true` if log removed because of a chain reorganization. `false` if a valid log.
- `logIndex`: _quantity, integer_ - Log index position in the block. `null` when log is pending.
- `transactionIndex`: _quantity, integer_ - Index position of the starting transaction for the log. `null` when log is pending.
- `transactionHash`: _data, 32 bytes_ - Hash of the starting transaction for the log. `null` when log is pending.
- `blockHash`: _data, 32 bytes_ - Hash of the block that includes the log. `null` when log is pending.
- `blockNumber`: _quantity_ - Number of block that includes the log. `null` when log is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded unix timestamp (in seconds) of the block that includes the log.
- `address`: _data, 20 bytes_ - Address the log originated from.
- `data`: _data_ - Non-indexed arguments of the log.
- `topics`: _array of data, 32 bytes each_ - [Event signature hash](../../../concepts/events-and-logs.md#event-signature-hash) and 0 to 3 [indexed log arguments](../../../concepts/events-and-logs.md#event-parameters).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getFilterChanges",
"params": [
"0xf8bf5598d9e04fbe84523d42640b9b0e"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getFilterChanges",
"params": [
"0xf8bf5598d9e04fbe84523d42640b9b0e"
],
"id": 1
}
```
```json title="Example result from a filter created with eth_newBlockFilter"
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0xda2bfe44bf85394f0d6aa702b5af89ae50ae22c0928c18b8903d9269abe17e0b",
"0x88cd3a37306db1306f01f7a0e5b25a9df52719ad2f87b0f88ee0e6753ed4a812",
"0x4d4c731fe129ff32b425e6060d433d3fde278b565bbd1fd624d5a804a34f8786"
]
}
```
```json title="Example result from a filter created with eth_newPendingTransactionFilter"
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0x1e977049b6db09362da09491bee3949d9362080ce3f4fc19721196d508580d46",
"0xa3abc4b9a4e497fd58dc59cdff52e9bb5609136bcd499e760798aa92802769be"
]
}
```
```json title="Example result from a filter created with eth_newFilter"
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x233",
"blockHash": "0xfc139f5e2edee9e9c888d8df9a2d2226133a9bd87c88ccbd9c930d3d4c9f9ef5",
"blockTimestamp": "0x55ba4769",
"transactionHash": "0x66e7a140c8fa27fe98fde923defea7562c3ca2d6bb89798aabec65782c08f63d",
"transactionIndex": "0x0",
"address": "0x42699a7612a82f1d9c36148af9c77354759b210b",
"data": "0x0000000000000000000000000000000000000000000000000000000000000004",
"topics": [
"0x04474795f5b996ff80cb47c148d4c5ccdbe09ef27551820caa9c2f8ed149cce3"
]
},
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0x238",
"blockHash": "0x98b0ec0f9fea0018a644959accbe69cd046a8582e89402e1ab0ada91cad644ed",
"blockTimestamp": "0x55ba4773",
"transactionHash": "0xdb17aa1c2ce609132f599155d384c0bc5334c988a6c368056d7e167e23eee058",
"transactionIndex": "0x0",
"address": "0x42699a7612a82f1d9c36148af9c77354759b210b",
"data": "0x0000000000000000000000000000000000000000000000000000000000000007",
"topics": [
"0x04474795f5b996ff80cb47c148d4c5ccdbe09ef27551820caa9c2f8ed149cce3"
]
}
]
}
```
---
## `eth_getFilterLogs`
Returns an array of [logs](../../../concepts/events-and-logs.md) for the specified filter.
Leave the [`--auto-log-bloom-caching-enabled`](../../options.md#auto-log-bloom-caching-enabled) command line option at the default value of `true` to improve log retrieval performance.
:::note
`eth_getFilterLogs` is only used for filters created with `eth_newFilter`. To specify a filter object and get logs without creating a filter, use `eth_getLogs`.
:::
### Parameters
- `filterId`: _string_ - Filter ID.
### Returns
- List of log objects.
- `removed`: _tag_ - `true` if log removed because of a chain reorganization. `false` if a valid log.
- `logIndex`: _quantity, integer_ - Log index position in the block. `null` when log is pending.
- `transactionIndex`: _quantity, integer_ - Index position of the starting transaction for the log. `null` when log is pending.
- `transactionHash`: _data, 32 bytes_ - Hash of the starting transaction for the log. `null` when log is pending.
- `blockHash`: _data, 32 bytes_ - Hash of the block that includes the log. `null` when log is pending.
- `blockNumber`: _quantity_ - Number of block that includes the log. `null` when log is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded unix timestamp (in seconds) of the block that includes the log.
- `address`: _data, 20 bytes_ - Address the log originated from.
- `data`: _data_ - Non-indexed arguments of the log.
- `topics`: _array of data, 32 bytes each_ - [Event signature hash](../../../concepts/events-and-logs.md#event-signature-hash) and 0 to 3 [indexed log arguments](../../../concepts/events-and-logs.md#event-parameters).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getFilterLogs",
"params": [
"0x5ace5de3985749b6a1b2b0d3f3e1fb69"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getFilterLogs",
"params": [
"0x5ace5de3985749b6a1b2b0d3f3e1fb69"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0xb3",
"blockHash": "0xe7cd776bfee2fad031d9cc1c463ef947654a031750b56fed3d5732bee9c61998",
"blockTimestamp": "0x55ba4486",
"transactionHash": "0xff36c03c0fba8ac4204e4b975a6632c862a3f08aa01b004f570cc59679ed4689",
"transactionIndex": "0x0",
"address": "0x2e1f232a9439c3d459fceca0beef13acc8259dd8",
"data": "0x0000000000000000000000000000000000000000000000000000000000000003",
"topics": [
"0x04474795f5b996ff80cb47c148d4c5ccdbe09ef27551820caa9c2f8ed149cce3"
]
},
{
"logIndex": "0x0",
"removed": false,
"blockNumber": "0xb6",
"blockHash": "0x3f4cf35e7ed2667b0ef458cf9e0acd00269a4bc394bb78ee07733d7d7dc87afc",
"blockTimestamp": "0x55ba448c",
"transactionHash": "0x117a31d0dbcd3e2b9180c40aca476586a648bc400aa2f6039afdd0feab474399",
"transactionIndex": "0x0",
"address": "0x2e1f232a9439c3d459fceca0beef13acc8259dd8",
"data": "0x0000000000000000000000000000000000000000000000000000000000000005",
"topics": [
"0x04474795f5b996ff80cb47c148d4c5ccdbe09ef27551820caa9c2f8ed149cce3"
]
}
]
}
```
---
## `eth_getLogs`
Returns an array of [logs](../../../concepts/events-and-logs.md) matching a specified filter object.
Leave the [`--auto-log-bloom-caching-enabled`](../../options.md#auto-log-bloom-caching-enabled) command line option at the default value of `true` to improve log retrieval performance.
:::caution
Using `eth_getLogs` to get logs from a large range of blocks, especially an entire chain from its genesis block, might cause Besu to hang for an indeterminable amount of time while generating the response. We recommend setting a range limit using the [`--rpc-max-logs-range`](../../options.md#rpc-max-logs-range) option (or leaving it at its default value of 1000).
:::
### Parameters
- `filterOptions`: _object_ - Filter options object.
- `fromBlock`: _quantity | tag_ - (Optional) Integer block number or `latest`, `pending`, `earliest`. See [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
The default is `latest`.
- `toBlock`: _quantity | tag_ - (Optional) Integer block number or `latest`, `pending`, `earliest`. See [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
The default is `latest`.
- `address`: _data | array_ - (Optional) Contract address or array of addresses from which [logs](../../../concepts/events-and-logs.md) originate.
- `topics`: _array of data, 32 bytes each_ - (Optional) Array of topics by which to [filter logs](../../../concepts/events-and-logs.md#topic-filters).
- `blockHash`: _data, 32 bytes_ - (Optional) Hash of block for which to return logs. If you specify `blockHash`, you cannot specify `fromBlock` and `toBlock`.
### Returns
- List of log objects.
- `removed`: _tag_ - `true` if log removed because of a chain reorganization. `false` if a valid log.
- `logIndex`: _quantity, integer_ - Log index position in the block. `null` when log is pending.
- `transactionIndex`: _quantity, integer_ - Index position of the starting transaction for the log. `null` when log is pending.
- `transactionHash`: _data, 32 bytes_ - Hash of the starting transaction for the log. `null` when log is pending.
- `blockHash`: _data, 32 bytes_ - Hash of the block that includes the log. `null` when log is pending.
- `blockNumber`: _quantity_ - Number of block that includes the log. `null` when log is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded unix timestamp (in seconds) of the block that includes the log.
- `address`: _data, 20 bytes_ - Address the log originated from.
- `data`: _data_ - Non-indexed arguments of the log.
- `topics`: _array of data, 32 bytes each_ - [Event signature hash](../../../concepts/events-and-logs.md#event-signature-hash) and 0 to 3 [indexed log arguments](../../../concepts/events-and-logs.md#event-parameters).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [
{
"fromBlock": "0x16e2a9a",
"toBlock": "0x16e2a9a",
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"topics": []
}
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [
{
"fromBlock": "0x16e2a9a",
"toBlock": "0x16e2a9a",
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"topics": []
}
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"removed": false,
"logIndex": "0x2",
"transactionIndex": "0x0",
"transactionHash": "0xf9bde920aba1c0eb632138ae21d3f019977de264a4714a54f1ae2e337cce4e3d",
"blockHash": "0xa02851f445eea915ef51c54f1352a773c3821a1860d49c6d3e94a16659291c19",
"blockNumber": "0x16e2a9a",
"blockTimestamp": "0x693c23db",
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"data": "0x00000000000000000000000000000000000000000000000001112ea12c39c032",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378da...9d4b2b7fad"
]
},
{
"removed": false,
"logIndex": "0x6",
"transactionIndex": "0x0",
"transactionHash": "0xf9bde920aba1c0eb632138ae21d3f019977de264a4714a54f1ae2e337cce4e3d",
"blockHash": "0xa02851f445eea915ef51c54f1352a773c3821a1860d49c6d3e94a16659291c19",
"blockNumber": "0x16e2a9a",
"blockTimestamp": "0x693c23db",
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"data": "0x00000000000000000000000000000000000000000000000001112ea12c39c032",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378d...629ba9375161"
]
}
]
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{logs(filter:{fromBlock: 24000026, toBlock: 24000026, addresses: [\"0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2\"]}) {index topics data account{address} transaction{hash} }}"
}'
```
```text
{
logs(filter: {fromBlock: 24000026, toBlock: 24000026, addresses: ["0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"]}) {
index
topics
data
account {
address
}
transaction {
hash
}
}
}
```
```json
{
"data": {
"logs": [
{
"index": 2,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378...d4b2b7fad"
],
"data": "0x00000000000000000000000000000000000000000000000001112ea12c39c032",
"account": {
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
},
"transaction": {
"hash": "0xf9bde920aba1c0eb632138ae21d3f019977de264a4714a54f1ae2e337cce4e3d"
}
},
{
"index": 6,
"topics": [
"0xddf252ad1be2c89b69c2b068fc378...9ba9375161"
],
"data": "0x00000000000000000000000000000000000000000000000001112ea12c39c032",
"account": {
"address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"
},
"transaction": {
"hash": "0xf9bde920aba1c0eb632138ae21d3f019977de264a4714a54f1ae2e337cce4e3d"
}
}
]
}
}
```
---
## `eth_newBlockFilter`
Creates a filter to retrieve new block hashes. To poll for new blocks, use [`eth_getFilterChanges`](#eth_getfilterchanges).
### Parameters
- None
### Returns
- Filter ID.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_newBlockFilter",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_newBlockFilter",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x9d78b6780f844228b96ecc65a320a825"
}
```
---
## `eth_newFilter`
Creates a [log filter](../../../concepts/events-and-logs.md). To poll for logs associated with the created filter, use [`eth_getFilterChanges`](#eth_getfilterchanges). To get all logs associated with the filter, use [`eth_getFilterLogs`](#eth_getfilterlogs).
### Parameters
- `filterOptions`: _object_ - Filter options object.
- `fromBlock`: _quantity | tag_ - (Optional) Integer block number or `latest`, `pending`, `earliest`. See [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
The default is `latest`.
- `toBlock`: _quantity | tag_ - (Optional) Integer block number or `latest`, `pending`, `earliest`. See [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
The default is `latest`.
- `address`: _data | array_ - (Optional) Contract address or array of addresses from which [logs](../../../concepts/events-and-logs.md) originate.
- `topics`: _array of data, 32 bytes each_ - (Optional) Array of topics by which to [filter logs](../../../concepts/events-and-logs.md#topic-filters).
- `blockHash`: _data, 32 bytes_ - (`eth_getLogs` only) (Optional) Hash of block for which to return logs. If you specify `blockHash`, you cannot specify `fromBlock` and `toBlock`.
### Returns
- Filter ID.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_newFilter",
"params": [
{
"fromBlock": "earliest",
"toBlock": "latest",
"topics": []
}
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_newFilter",
"params": [
{
"fromBlock": "earliest",
"toBlock": "latest",
"topics": []
}
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x1ddf0c00989044e9b41cc0ae40272df3"
}
```
---
## `eth_newPendingTransactionFilter`
Creates a filter to retrieve new pending transactions hashes. To poll for new pending transactions, use [`eth_getFilterChanges`](#eth_getfilterchanges).
### Parameters
- None
### Returns
- Filter ID.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_newPendingTransactionFilter",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_newPendingTransactionFilter",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x443d6a77c4964707a8554c92f7e4debd"
}
```
---
## `eth_uninstallFilter`
Uninstalls a filter with the specified ID. When a filter is no longer required, call this method.
Filters time out when not requested by [`eth_getFilterChanges`](#eth_getfilterchanges) or [`eth_getFilterLogs`](#eth_getfilterlogs) for 10 minutes.
### Parameters
- `filterId`: _string_ - Filter ID.
### Returns
- Indicates if the filter is successfully uninstalled.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_uninstallFilter",
"params": [
"0x70355a0b574b437eaa19fe95adfedc0a"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_uninstallFilter",
"params": [
"0x70355a0b574b437eaa19fe95adfedc0a"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
---
## ETH methods
# `ETH` methods
The `ETH` API methods allow you to interact with the blockchain.
:::note
Methods with an equivalent [GraphQL](../../../how-to/use-besu-api/graphql.md) query include a GraphQL request and result in the method example.
The parameter and result descriptions apply to the JSON-RPC requests.
The GraphQL specification is defined in the [schema].
:::
The `ETH` methods are grouped into the following pages.
#### Client and network
Query client and network information.
- `eth_accounts`
- `eth_blockNumber`
- `eth_capabilities`
- `eth_chainId`
- `eth_config`
- `eth_protocolVersion`
- `eth_syncing`
#### Block
Query blocks and their contents.
- `eth_getBlockByHash`
- `eth_getBlockByNumber`
- `eth_getBlockReceipts`
- `eth_getBlockTransactionCountByHash`
- `eth_getBlockTransactionCountByNumber`
- `eth_getUncleByBlockHashAndIndex`
- `eth_getUncleByBlockNumberAndIndex`
- `eth_getUncleCountByBlockHash`
- `eth_getUncleCountByBlockNumber`
#### Transaction
Retrieve transactions and transaction receipts.
- `eth_getTransactionByBlockHashAndIndex`
- `eth_getTransactionByBlockNumberAndIndex`
- `eth_getTransactionByHash`
- `eth_getTransactionBySenderAndNonce`
- `eth_getTransactionReceipt`
#### State and account
Read account state at a given block.
- `eth_getBalance`
- `eth_getCode`
- `eth_getProof`
- `eth_getStorageAt`
- `eth_getStorageValues`
- `eth_getTransactionCount`
#### Execution
Execute calls and perform actions without changing blockchain state.
- `eth_call`
- `eth_createAccessList`
- `eth_estimateGas`
- `eth_simulateV1`
#### Fee market
Query gas price and fee market information.
- `eth_baseFee`
- `eth_blobBaseFee`
- `eth_feeHistory`
- `eth_gasPrice`
- `eth_maxPriorityFeePerGas`
#### Filter and log
Manage filters and query event logs.
- `eth_getFilterChanges`
- `eth_getFilterLogs`
- `eth_getLogs`
- `eth_newBlockFilter`
- `eth_newFilter`
- `eth_newPendingTransactionFilter`
- `eth_uninstallFilter`
#### Submit
Submit signed transactions to the network.
- `eth_sendRawTransaction`
[schema]: https://github.com/besu-eth/besu/blob/750580dcca349d22d024cc14a8171b2fa74b505a/ethereum/api/src/main/resources/schema.graphqls
---
## State and account methods
These methods read account state at a given block, including balances, nonces, contract code, storage values, and Merkle proofs.
## `eth_getBalance`
Returns the account balance of the specified address.
### Parameters
- `address`: _string_ - 20-byte account address from which to retrieve the balance.
- `blockNumber` or `blockHash`: _string_ - (Optional) Hexadecimal integer representing a block
number, block hash, or one of the string tags `latest`, `earliest`, `pending`, `finalized`, or
`safe`, as described in [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
The default is `latest`.
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- Current balance, in wei, as a hexadecimal value.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": [
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"latest"
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": [
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"latest"
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": "0x1cfe56f3795885980000"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{ account ( address: \"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73\") { balance } }"
}'
```
```text
{
account(address: "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73") {
balance
}
}
```
```json
{
"data": {
"account": {
"balance": "0x1ce96a1ffe7620d00000"
}
}
}
```
---
## `eth_getCode`
Returns the code of the smart contract at the specified address. Besu stores compiled smart contract code as a hexadecimal value.
### Parameters
- `address`: _string_ - 20-byte contract address.
- `blockNumber` or `blockHash`: _string_ - (Optional) Hexadecimal integer representing a block number,
block hash, or one of the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as
described in [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
The default is `latest`.
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- Code stored at the specified address.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getCode",
"params": [
"0xa50a51c09a5c451c52bb714527e1974b686d8e77",
"latest"
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getCode",
"params": [
"0xa50a51c09a5c451c52bb714527e1974b686d8e77",
"latest"
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": "0x60806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f2458114604d57806355241077146071575b600080fd5b348015605857600080fd5b50605f6088565b60408051918252519081900360200190f35b348015607c57600080fd5b506086600435608e565b005b60005481565b60008190556040805182815290517f199cd93e851e4c78c437891155e2112093f8f15394aa89dab09e38d6ca0727879181900360200190a1505600a165627a7a723058209d8929142720a69bde2ab3bfa2da6217674b984899b62753979743c0470a2ea70029"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{account(address: \"0xa50a51c09a5c451c52bb714527e1974b686d8e77\"){ code }}"
}'
```
```text
{
account(address: "0xa50a51c09a5c451c52bb714527e1974b686d8e77") {
code
}
}
```
```json
{
"data": {
"account": {
"code": "0x60806040526004361060485763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f2458114604d57806355241077146071575b600080fd5b348015605857600080fd5b50605f6088565b60408051918252519081900360200190f35b348015607c57600080fd5b506086600435608e565b005b60005481565b60008190556040805182815290517f199cd93e851e4c78c437891155e2112093f8f15394aa89dab09e38d6ca0727879181900360200190a1505600a165627a7a723058209d8929142720a69bde2ab3bfa2da6217674b984899b62753979743c0470a2ea70029"
}
}
}
```
---
## `eth_getProof`
Returns the account and storage values of the specified account, including the Merkle proof.
The API allows IoT devices or mobile apps which are unable to run light clients to verify responses from untrusted sources, by using a trusted block hash.
### Parameters
- `address`: _string_ - 20-byte address of the account or contract.
- `keys`: _array_ of _strings_ - List of 32-byte storage keys to generate proofs for.
- `blockNumber` or `blockHash`: _string_ - (Optional) Hexadecimal integer representing a block
number, block hash, or one of the string tags `latest`, `earliest`, `pending`, `finalized`, or
`safe`, as described in [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
The default is `latest`.
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- Account details object.
- `balance`: _string_ - Account balance.
- `codeHash`: _string_ - 32-byte hash of the account code.
- `nonce`: _string_ - Number of transactions sent from the account.
- `storageHash`: _string_ - 32-byte SHA3 of the `storageRoot`.
- `accountProof`: _array_ of _strings_ - List of RLP-encoded Merkle tree nodes, starting with the `stateRoot`.
- `storageProof`: _array_ of _objects_ - List of storage entry objects.
- `key`: _string_ - Storage key.
- `value`: _string_ - Storage value.
- `proof`: _array_ of _strings_ - List of RLP-encoded Merkle tree nodes, starting with the `storageHash`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getProof",
"params": [
"0a8156e7ee392d885d10eaa86afd0e323afdcd95",
[
"0x0000000000000000000000000000000000000000000000000000000000000347"
],
"latest"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getProof",
"params": [
"0a8156e7ee392d885d10eaa86afd0e323afdcd95",
[
"0x0000000000000000000000000000000000000000000000000000000000000347"
],
"latest"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"accountProof": [
"0xf90211a0...608d898380",
"0xf90211a0...ec33f19580",
"0xf901d1a0...9e55584480",
"0xf8718080...18e5777142"
],
"address": "0x0a8156e7ee392d885d10eaa86afd0e323afdcd95",
"balance": "0x0",
"codeHash": "0x2b6975dcaf69f9bb9a3b30bb6a37b305ce440250bf0dd2f23338cb18e5777142",
"nonce": "0x5f",
"storageHash": "0x917688de43091589aa58c1dfd315105bc9de4478b9ba7471616a4d8a43d46203",
"storageProof": [
{
"key": "0x0000000000000000000000000000000000000000000000000000000000000347",
"value": "0x0",
"proof": [
"0xf90211a0...5176779280",
"0xf901f1a0...c208d86580",
"0xf8d180a0...1ce6808080"
]
}
]
}
}
```
---
## `eth_getStorageAt`
Returns the value of a storage position at a specified address.
### Parameters
- `address`: _string_ - 20-byte storage address.
- `index`: _string_ - Integer index of the storage position.
- `blockNumber` or `blockHash`: _string_ - (Optional) Hexadecimal integer representing a block
number, block hash, or one of the string tags `latest`, `earliest`, `pending`, `finalized`, or
`safe`, as described in [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
The default is `latest`.
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- Value at the specified storage position.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getStorageAt",
"params": [
"0x3B3F3E",
"0x0",
"latest"
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getStorageAt",
"params": [
"0x3B3F3E",
"0x0",
"latest"
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{account(address: \"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73\") {storage(slot: \"0x04\")}}"
}'
```
```text
{
account(address: "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73") {
storage(slot: "0x04")
}
}
```
```json
{
"data": {
"account": {
"storage": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
}
}
```
---
## `eth_getStorageValues`
Returns storage values for multiple slots across one or more accounts in a single call.
This is a batched version of [`eth_getStorageAt`](#eth_getstorageat).
### Parameters
- `storageRequest`: _object_ - Each key is a 20-byte account address
and each value is an array of storage slot keys (as 32-byte hex strings).
The maximum total number of storage slots across all addresses is 1024.
- `blockNumber` or `blockHash`: _string_ - (Optional) Hexadecimal integer representing a block number,
block hash, or one of the string tags `latest`, `earliest`, `pending`, `finalized`, or
`safe`, as described in [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
The default is `latest`.
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- Each key is an account address and each value is an array of hex-encoded
storage values in the same order as the requested slot keys.
Unknown accounts return zero values for all requested slots.
Key order in the response object is not guaranteed to match the request.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getStorageValues",
"params": [
{
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": [
"0x0",
"0x1"
],
"0x627306090abaB3A6e1400e9345bC60c78a8BEf57": [
"0x0"
]
},
"latest"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getStorageValues",
"params": [
{
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": [
"0x0",
"0x1"
],
"0x627306090abaB3A6e1400e9345bC60c78a8BEf57": [
"0x0"
]
},
"latest"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"0x627306090abab3a6e1400e9345bc60c78a8bef57": [
"0x0000000000000000000000000000000000000000000000000000000000000000"
],
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
}
}
```
---
## `eth_getTransactionCount`
Returns the number of transactions sent from a specified address. Use the `pending` tag to get the next account nonce not used by any pending transactions.
### Parameters
- `address`: _string_ - 20-byte account address.
- `blockNumber` or `blockHash`: _string_ - (Optional) Hexadecimal integer representing a block number, block hash, or one of the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in [block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
The default is `latest`.
### Returns
- Integer representing the number of transactions sent from the specified address.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getTransactionCount",
"params": [
"0xc94770007dda54cF92009BFF0dE90c06F603a09f",
"latest"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getTransactionCount",
"params": [
"0xc94770007dda54cF92009BFF0dE90c06F603a09f",
"latest"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x1"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{ account (address:\"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73\"){transactionCount}}"
}'
```
```text
{
account(address: "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73") {
transactionCount
}
}
```
```json
{
"data": {
"account": {
"transactionCount": 5
}
}
}
```
---
## Submit methods
These methods submit signed transactions to the network.
:::info
Besu doesn't implement [`eth_sendTransaction`](../../../how-to/send-transactions.md).
[Web3Signer](https://docs.web3signer.consensys.net/) provides transaction signing and implements [`eth_sendTransaction`](https://docs.web3signer.consensys.net/reference/api/json-rpc#eth_sendtransaction).
:::
## `eth_sendRawTransaction`
Sends a [signed transaction](../../../how-to/send-transactions.md). A transaction can send ether, deploy a contract, or interact with a contract. Set the maximum transaction fee for transactions using the [`--rpc-tx-feecap`](../../options.md#rpc-tx-feecap) CLI option.
You can interact with contracts using `eth_sendRawTransaction` or [`eth_call`](execute.md#eth_call).
To avoid exposing your private key, create signed transactions offline and send the signed transaction data using `eth_sendRawTransaction`.
:::note
[Create and send transactions](../../../how-to/send-transactions.md) includes examples of creating signed transactions using the [web3.js](https://github.com/ethereum/web3.js/) library.
:::
### Parameters
- `transaction`: _string_ - Signed transaction serialized to hexadecimal format.
### Returns
- 32-byte transaction hash.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_sendRawTransaction",
"params": [
"0xf869018203e882520894f17f52151ebef6c7334fad080c5704d77216b732881bc16d674ec80000801ba02da1c48b670996dcb1f447ef9ef00b33033c48a4fe938f420bec3e56bfd24071a062e0aa78a81bf0290afbc3a9d8e9a068e6d74caa66c5e0fa8a46deaae96b0833"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_sendRawTransaction",
"params": [
"0xf869018203e882520894f17f52151ebef6c7334fad080c5704d77216b732881bc16d674ec80000801ba02da1c48b670996dcb1f447ef9ef00b33033c48a4fe938f420bec3e56bfd24071a062e0aa78a81bf0290afbc3a9d8e9a068e6d74caa66c5e0fa8a46deaae96b0833"
],
"id": 1
}
```
```json
{
"id": 1,
"jsonrpc": "2.0",
"result": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "mutation {sendRawTransaction(data: \"0xf869018203e882520894f17f52151ebef6c7334fad080c5704d77216b732881bc16d674ec80000801ba02da1c48b670996dcb1f447ef9ef00b33033c48a4fe938f420bec3e56bfd24071a062e0aa78a81bf0290afbc3a9d8e9a068e6d74caa66c5e0fa8a46deaae96b0833\")}"
}'
```
```text
mutation {
sendRawTransaction(data: "0xf869018203e882520894f17f52151ebef6c7334fad080c5704d77216b732881bc16d674ec80000801ba02da1c48b670996dcb1f447ef9ef00b33033c48a4fe938f420bec3e56bfd24071a062e0aa78a81bf0290afbc3a9d8e9a068e6d74caa66c5e0fa8a46deaae96b0833")
}
```
```json
{
"data": {
"sendRawTransaction": "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
}
}
```
---
## Transaction methods
These methods retrieve transactions and transaction receipts.
## `eth_getTransactionByBlockHashAndIndex`
Returns transaction information for the specified block hash and transaction index position.
### Parameters
- `block`: _string_ - 32-byte hash of a block.
- `index`: _string_ - Integer representing the transaction index position.
### Returns
- Transaction object, or `null` when there is no transaction.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockHashAndIndex",
"params": [
"0xbf137c3a7a1ebdfac21252765e5d7f40d115c2757e4a4abee929be88c624fdb7",
"0x2"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockHashAndIndex",
"params": [
"0xbf137c3a7a1ebdfac21252765e5d7f40d115c2757e4a4abee929be88c624fdb7",
"0x2"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"blockHash": "0xbf137c3a7a1ebdfac21252765e5d7f40d115c2757e4a4abee929be88c624fdb7",
"blockNumber": "0x1442e",
"blockTimestamp": "0x561bc2e0",
"chainId": 2018,
"from": "0x70c9217d814985faef62b124420f8dfbddd96433",
"gas": "0x3d090",
"gasPrice": "0x57148a6be",
"hash": "0xfc766a71c406950d4a4955a340a092626c35083c64c7be907060368a5e6811d6",
"input": "0x51a34eb8000000000000000000000000000000000000000000000029b9e659e41b780000",
"nonce": "0x2cb2",
"to": "0xcfdc98ec7f01dab1b67b36373524ce0208dc3953",
"transactionIndex": "0x2",
"value": "0x0",
"v": "0x2a",
"r": "0xa2d2b1021e1428740a7c67af3c05fe3160481889b25b921108ac0ac2c3d5d40a",
"s": "0x63186d2aaefe188748bfb4b46fb9493cbc2b53cf36169e8501a5bc0ed941b484"
}
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{ block(hash: \"0x9270651f9c6fa36232c379d0ecf69b519383aa275815a65f1e03114346668f69\") { transactionAt(index: 0) {block{hash} hash } } }"
}'
```
```text
{
block(hash: "0x9270651f9c6fa36232c379d0ecf69b519383aa275815a65f1e03114346668f69") {
transactionAt(index: 0) {
block {
hash
}
hash
}
}
}
```
```json
{
"data": {
"block": {
"transactionAt": {
"block": {
"hash": "0x9270651f9c6fa36232c379d0ecf69b519383aa275815a65f1e03114346668f69"
},
"hash": "0x5f5366af89e8777d5ae62a1af94a0876bdccbc22417bed0aff361eefa3e37f86"
}
}
}
}
```
---
## `eth_getTransactionByBlockNumberAndIndex`
Returns transaction information for the specified block number and transaction index position.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
- `index`: _string_ - Transaction index position.
### Returns
- Transaction object, or `null` when there is no transaction.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockNumberAndIndex",
"params": [
"0x1442e",
"0x2"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getTransactionByBlockNumberAndIndex",
"params": [
"0x1442e",
"0x2"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"blockHash": "0xbf137c3a7a1ebdfac21252765e5d7f40d115c2757e4a4abee929be88c624fdb7",
"blockNumber": "0x1442e",
"blockTimestamp": "0x561bc2e0",
"chainId": 2018,
"from": "0x70c9217d814985faef62b124420f8dfbddd96433",
"gas": "0x3d090",
"gasPrice": "0x57148a6be",
"hash": "0xfc766a71c406950d4a4955a340a092626c35083c64c7be907060368a5e6811d6",
"input": "0x51a34eb8000000000000000000000000000000000000000000000029b9e659e41b780000",
"nonce": "0x2cb2",
"to": "0xcfdc98ec7f01dab1b67b36373524ce0208dc3953",
"transactionIndex": "0x2",
"value": "0x0",
"v": "0x2a",
"r": "0xa2d2b1021e1428740a7c67af3c05fe3160481889b25b921108ac0ac2c3d5d40a",
"s": "0x63186d2aaefe188748bfb4b46fb9493cbc2b53cf36169e8501a5bc0ed941b484"
}
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{block(number:20303) {transactionAt(index: 0) {block{hash} hash}}}"
}'
```
```text
{
block(number: 20303) {
transactionAt(index: 0) {
block {
hash
}
hash
}
}
}
```
```json
{
"data": {
"block": {
"transactionAt": {
"block": {
"hash": "0x9270651f9c6fa36232c379d0ecf69b519383aa275815a65f1e03114346668f69"
},
"hash": "0x5f5366af89e8777d5ae62a1af94a0876bdccbc22417bed0aff361eefa3e37f86"
}
}
}
}
```
---
## `eth_getTransactionByHash`
Returns transaction information for the specified transaction hash.
### Parameters
- `transaction`: _string_ - 32-byte transaction hash.
### Returns
- Transaction object, or `null` when there is no transaction.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getTransactionByHash",
"params": [
"0xa52be92809541220ee0aaaede6047d9a6c5d0cd96a517c854d944ee70a0ebb44"
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getTransactionByHash",
"params": [
"0xa52be92809541220ee0aaaede6047d9a6c5d0cd96a517c854d944ee70a0ebb44"
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": {
"blockHash": "0x510efccf44a192e6e34bcb439a1947e24b86244280762cbb006858c237093fda",
"blockNumber": "0x422",
"blockTimestamp": "0x561bc2e0",
"chainId": 2018,
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0x5208",
"gasPrice": "0x3b9aca00",
"hash": "0xa52be92809541220ee0aaaede6047d9a6c5d0cd96a517c854d944ee70a0ebb44",
"input": "0x",
"nonce": "0x1",
"to": "0x627306090abab3a6e1400e9345bc60c78a8bef57",
"transactionIndex": "0x0",
"value": "0x4e1003b28d9280000",
"v": "0xfe7",
"r": "0x84caf09aefbd5e539295acc67217563438a4efb224879b6855f56857fa2037d3",
"s": "0x5e863be3829812c81439f0ae9d8ecb832b531d651fb234c848d1bf45e62be8b9"
}
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{transaction(hash : \"0x03d80b9ca0a71435399a268609d6d7896f7155d2147cc22b780672bcb59b170d\") { block{hash} gas gasPrice hash nonce value from {address} to {address} status}}"
}'
```
```text
{
transaction(hash: "0x03d80b9ca0a71435399a268609d6d7896f7155d2147cc22b780672bcb59b170d") {
block {
hash
}
gas
gasPrice
hash
nonce
value
from {
address
}
to {
address
}
status
}
}
```
```json
{
"data": {
"transaction": {
"block": {
"hash": "0xb1ef35744bade6980c3a933024b2557a8c724a19e5fdd2116bac712aa5e57198"
},
"gas": 21000,
"gasPrice": "0x2540be400",
"hash": "0x03d80b9ca0a71435399a268609d6d7896f7155d2147cc22b780672bcb59b170d",
"nonce": 6,
"value": "0x8ac7230489e80000",
"from": {
"address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"
},
"to": {
"address": "0x9d8f8572f345e1ae53db1dfa4a7fce49b467bd7f"
},
"status": 1
}
}
}
```
---
## `eth_getTransactionBySenderAndNonce`
Returns transaction information for the specified sender address and nonce.
:::note
To return transactions included in blocks, this method requires the sender and nonce index.
The index is enabled by default; you can disable it using
[`--tx-sender-nonce-index-enabled`](../../options.md#tx-sender-nonce-index-enabled).
If the index is disabled, this method only returns information for pending transactions.
:::
### Parameters
- `address`: _string_ - 20-byte sender address.
- `nonce`: _string_ - Hexadecimal integer representing the transaction nonce.
### Returns
- Transaction object, or `null` when there is no transaction.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getTransactionBySenderAndNonce",
"params": [
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"0x1"
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getTransactionBySenderAndNonce",
"params": [
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"0x1"
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": {
"blockHash": "0x510efccf44a192e6e34bcb439a1947e24b86244280762cbb006858c237093fda",
"blockNumber": "0x422",
"blockTimestamp": "0x561bc2e0",
"chainId": 2018,
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0x5208",
"gasPrice": "0x3b9aca00",
"hash": "0xa52be92809541220ee0aaaede6047d9a6c5d0cd96a517c854d944ee70a0ebb44",
"input": "0x",
"nonce": "0x1",
"to": "0x627306090abab3a6e1400e9345bc60c78a8bef57",
"transactionIndex": "0x0",
"value": "0x4e1003b28d9280000",
"v": "0xfe7",
"r": "0x84caf09aefbd5e539295acc67217563438a4efb224879b6855f56857fa2037d3",
"s": "0x5e863be3829812c81439f0ae9d8ecb832b531d651fb234c848d1bf45e62be8b9"
}
}
```
---
## `eth_getTransactionReceipt`
Returns the receipt of a transaction by transaction hash. Receipts for pending transactions are not available.
If you enabled [revert reason](../../../../private-networks/how-to/send-transactions/revert-reason.md), the receipt includes available revert reasons in the response.
### Parameters
- `transaction`: _string_ - 32-byte hash of a transaction.
### Returns
- Transaction receipt object, or `null` when there is no receipt.
- `blockHash`: _data, 32 bytes_ - Hash of block containing this transaction.
- `blockNumber`: _quantity_ - Block number of block containing this transaction.
- `blockTimestamp`: _quantity_ - Hex-encoded unix timestamp (in seconds) of the block that includes this transaction.
- `contractAddress`: _data, 20 bytes_ - Contract address created, if contract creation transaction, otherwise, `null`. A failed contract creation transaction still produces a contract address value.
- `cumulativeGasUsed`: _quantity_ - Total amount of gas used by previous transactions in the block and this transaction.
- `effectiveGasPrice`: _quantity_ - The [actual value per gas deducted](../../../concepts/transactions/types.md#eip1559-transactions) from the sender's account.
- `from`: _data, 20 bytes_ - Address of the sender.
- `gasUsed`: _quantity_ - Amount of gas used by this specific transaction.
- `logs`: _array_ - Array of log objects generated by this transaction.
- `removed`: _tag_ - `true` if log removed because of a chain reorganization. `false` if a valid log.
- `logIndex`: _quantity, integer_ - Log index position in the block. `null` when log is pending.
- `transactionIndex`: _quantity, integer_ - Index position of the starting transaction for the log. `null` when log is pending.
- `transactionHash`: _data, 32 bytes_ - Hash of the starting transaction for the log. `null` when log is pending.
- `blockHash`: _data, 32 bytes_ - Hash of the block that includes the log. `null` when log is pending.
- `blockNumber`: _quantity_ - Number of block that includes the log. `null` when log is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded unix timestamp (in seconds) of the block that includes the log.
- `address`: _data, 20 bytes_ - Address the log originated from.
- `data`: _data_ - Non-indexed arguments of the log.
- `topics`: _array of data, 32 bytes each_ - [Event signature hash](../../../concepts/events-and-logs.md#event-signature-hash) and 0 to 3 [indexed log arguments](../../../concepts/events-and-logs.md#event-parameters).
- `logsBloom`: _data, 256 bytes_ - Bloom filter for light clients to quickly retrieve related logs.
- `status`: _quantity_ - Either `0x0` (failure), `0x1` (success), or `0x2` (invalid).
- `to`: _data, 20 bytes_ - Address of the receiver, if sending ether, otherwise, null.
- `transactionHash`: _data, 32 bytes_ - Hash of the transaction.
- `transactionIndex`: _quantity, integer_ - Index position of transaction in the block.
- `transactionType`: _string_ - [Transaction type](../../../concepts/transactions/types.md).
- `revertReason`: _string_ - ABI-encoded string that displays the [reason for reverting the transaction](../../../../private-networks/how-to/send-transactions/revert-reason.md). Only available if revert reason is [enabled](../../options.md#revert-reason-enabled).
- `type`: _quantity_ - Transaction type, `0x00` for legacy transactions, `0x01` for access list types, `0x02` for dynamic fees, and `0x03` for blob transactions.
- `root`: _data, 32 bytes_ - Pre-Byzantium transactions return this field instead of `status`. Post-transaction state root.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": [
"0x504ce587a65bdbdb6414a0c6c16d86a04dd79bfcc4f2950eec9634b30ce5370f"
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": [
"0x504ce587a65bdbdb6414a0c6c16d86a04dd79bfcc4f2950eec9634b30ce5370f"
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"blockHash": "0xe7212a92cfb9b06addc80dec2a0dfae9ea94fd344efeb157c41e12994fcad60a",
"blockNumber": "0x50",
"blockTimestamp": "0x55ba43bb",
"contractAddress": null,
"cumulativeGasUsed": "0x5208",
"from": "0x627306090abab3a6e1400e9345bc60c78a8bef57",
"gasUsed": "0x5208",
"effectiveGasPrice": "0x1",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0xf17f52151ebef6c7334fad080c5704d77216b732",
"transactionHash": "0xc00e97af59c6f88de163306935f7682af1a34c67245e414537d02e422815efc3",
"transactionIndex": "0x0"
}
}
```
```bash
curl -X POST http://localhost:8547/graphql \
-H "Content-Type: application/json" \
--data '{
"query": "{transaction(hash: \"0x5f5366af89e8777d5ae62a1af94a0876bdccbc22417bed0aff361eefa3e37f86\") {block{hash logsBloom} hash createdContract{address} cumulativeGasUsed gas gasUsed logs{topics} from{address} to{address} index}}"
}'
```
```text
{
transaction(hash: "0x5f5366af89e8777d5ae62a1af94a0876bdccbc22417bed0aff361eefa3e37f86") {
block {
hash
logsBloom
}
hash
createdContract {
address
}
cumulativeGasUsed
gas
gasUsed
logs {
topics
}
from {
address
}
to {
address
}
index
}
}
```
```json
{
"data": {
"transaction": {
"block": {
"hash": "0x9270651f9c6fa36232c379d0ecf69b519383aa275815a65f1e03114346668f69",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
},
"hash": "0x5f5366af89e8777d5ae62a1af94a0876bdccbc22417bed0aff361eefa3e37f86",
"createdContract": null,
"cumulativeGasUsed": 21000,
"gas": 21000,
"gasUsed": 21000,
"effectiveGasPrice": "0x1",
"logs": [],
"from": {
"address": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"
},
"to": {
"address": "0x9d8f8572f345e1ae53db1dfa4a7fce49b467bd7f"
},
"index": 0
}
}
}
```
---
## Besu JSON-RPC API reference
The Besu JSON-RPC API methods are grouped by namespace:
| Namespace | Description |
| --- | --- |
| [`ADMIN`](admin.md) | Administrative functionality to manage your node. |
| [`DEBUG`](debug/index.md) | Inspect and debug the network. |
| [`ETH`](eth/index.md) | Interact with the blockchain, including querying blocks, transactions, logs, and account state. |
| [`MINER`](miner.md) | Control the node's block creation settings. |
| [`NET`](net.md) | Network-related information. |
| [`PLUGINS`](plugins.md) | Plugin-related functionality. |
| [`TRACE`](trace.md) | Concise alternative to the `DEBUG` API for tracing transactions. |
| [`TXPOOL`](txpool.md) | Inspect the contents of the transaction pool. |
| [`WEB3`](web3.md) | Functionality for the Ethereum ecosystem. |
:::caution Important
- This reference contains API methods that apply to both public and private networks. For private-network-specific API methods, see the [private network API reference](../../../private-networks/reference/api/index.md).
- All JSON-RPC HTTP examples use the default host and port endpoint `http://127.0.0.1:8545`. If using the [--rpc-http-host](../options.md#rpc-http-host) or [--rpc-http-port](../options.md#rpc-http-port) options, update the endpoint.
- Most example requests are made against private networks. Depending on network configuration and activity, your example results might be different.
:::
## Miscellaneous methods
### `rpc_modules`
Lists [enabled APIs](../../how-to/use-besu-api/json-rpc.md#api-methods-enabled-by-default) and the version of each.
#### Parameters
- None
#### Returns
- Enabled APIs and their versions.
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "rpc_modules",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "rpc_modules",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"web3": "1.0",
"eth": "1.0",
"net": "1.0"
}
}
```
---
## MINER methods
# `MINER` methods
The `MINER` API methods allow you to control settings related to block creation.
:::note
The `MINER` API is not enabled by default for JSON-RPC.
Enable it using the [`--rpc-http-api`](../options.md#rpc-http-api) or [`--rpc-ws-api`](../options.md#rpc-ws-api) option.
:::
## `miner_changeTargetGasLimit`
Updates the target gas limit set using the [`--target-gas-limit`](../options.md#target-gas-limit) command line option.
### Parameters
- `gasPrice`: _number_ - Target gas price in wei.
### Returns
- `Success` or `error`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "miner_changeTargetGasLimit",
"params": [
800000
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "miner_changeTargetGasLimit",
"params": [
800000
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## `miner_getExtraData`
Retrieves the current extra data field that is used when producing blocks.
### Parameters
- None
### Returns
- Hexadecimal string representation of the extra data bytes.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "miner_getExtraData",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "miner_getExtraData",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x68656c6c6f20776f726c64"
}
```
---
## `miner_getMinGasPrice`
Gets the minimum gas price (in wei) offered by a transaction to be included in a block.
The initial value is set using the [`--min-gas-price`](../options.md#min-gas-price) command line
option, or is set to `1000` if the command line option is not specified.
Use [`miner_setMinGasPrice`](#miner_setmingasprice) to change the current value of the gas price.
### Parameters
- None
### Returns
- Minimum gas price (in wei) as a hexadecimal string.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "miner_getMinGasPrice",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "miner_getMinGasPrice",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x3e8"
}
```
---
## `miner_getMinPriorityFee`
Gets the minimum priority fee per gas (in wei) offered by a transaction to be included in a block. The initial value is set using the [`--min-priority-fee`](../options.md#min-priority-fee) command line option, or is set to `0` if the command line option is not specified.
Use [`miner_setMinPriorityFee`](#miner_setminpriorityfee) to change the current value of the fee.
### Parameters
- None
### Returns
- Minimum priority fee per gas (in wei) as a hexadecimal string.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "miner_getMinPriorityFee",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "miner_getMinPriorityFee",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x1"
}
```
---
## `miner_setExtraData`
Sets a new value for the extra data field that is used when producing blocks.
### Parameters
- `extraData`: _string_ - Hexadecimal representation of the extra data field, with a maximum of 32 bytes.
### Returns
- `true` or `false`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "miner_setExtraData",
"params": [
"0x0010203"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "miner_setExtraData",
"params": [
"0x0010203"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"params": ["0x0010203"],
"id": 1,
"result": "true"
}
```
---
## `miner_setMinGasPrice`
Sets the minimum gas price (in wei) offered by a transaction to be included in a block.
The initial value is set using the [`--min-gas-price`](../options.md#min-gas-price) command line
option, or is set to `1000` if the command line option is not specified.
Use [`miner_getMinGasPrice`](#miner_getmingasprice) to get the current value of the gas price.
### Parameters
- `minGasPrice`: _string_ - Minimum gas price in hexadecimal.
### Returns
- `true` when the gas price is set.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "miner_setMinGasPrice",
"params": [
"0x5dc"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "miner_setMinGasPrice",
"params": [
"0x5dc"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
---
## `miner_setMinPriorityFee`
Sets the minimum priority fee per gas (in wei) offered by a transaction to be included in a block.
The initial value is set using the [`--min-priority-fee`](../options.md#min-priority-fee) command line option, or is set to `0` if the command line option is not specified.
Use [`miner_getMinPriorityFee`](#miner_getminpriorityfee) to get the current value of the fee.
### Parameters
- `minPriorityFeePerGas`: _string_ - Minimum priority fee per gas in hexadecimal.
### Returns
- `true` when the fee is set.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "miner_setMinPriorityFee",
"params": [
"0x0a"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "miner_setMinPriorityFee",
"params": [
"0x0a"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
---
## NET methods
# `NET` methods
The `NET` API methods provide network-related information.
## `net_enode`
Returns the [enode URL](../../concepts/node-keys.md#enode-url).
### Parameters
- None
### Returns
- [Enode URL](../../concepts/node-keys.md#enode-url) of the node.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "net_enode",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "net_enode",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "enode://6a63160d0ccef5e4986d270937c6c8d60a9a4d3b25471cda960900d037c61988ea14da67f69dbfb3497c465d0de1f001bb95598f74b68a39a5156a608c42fa1b@127.0.0.1:30303"
}
```
---
## `net_listening`
Whether the client is actively listening for network connections.
### Parameters
- None
### Returns
- Indicates if the client is actively listening for network connections.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "net_listening",
"params": [],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "net_listening",
"params": [],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": true
}
```
---
## `net_peerCount`
Returns the number of peers currently connected to the client.
### Parameters
- None
### Returns
- Number of connected peers in hexadecimal.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "net_peerCount",
"params": [],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "net_peerCount",
"params": [],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": "0x5"
}
```
---
## `net_services`
Returns enabled services (for example, `jsonrpc`) and the host and port for each service.
:::note
The [`--nat-method`](../options.md#nat-method) setting affects the JSON-RPC and P2P host and port values, but not the metrics host and port values.
:::
### Parameters
- None
### Returns
- Enabled services.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "net_services",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "net_services",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"jsonrpc": {
"host": "127.0.0.1",
"port": "8545"
},
"p2p": {
"host": "127.0.0.1",
"port": "30303"
},
"metrics": {
"host": "127.0.0.1",
"port": "9545"
}
}
}
```
---
## `net_version`
Returns the [network ID](../../concepts/network-and-chain-id.md).
### Parameters
- None
### Returns
- Current network ID.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "net_version",
"params": [],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "net_version",
"params": [],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 51,
"result": "1"
}
```
---
## PLUGINS methods
# `PLUGINS` methods
The `PLUGINS` API methods provide plugin-related functionality.
:::note
The `PLUGINS` API is not enabled by default for JSON-RPC.
Enable it using the [`--rpc-http-api`](../options.md#rpc-http-api) or [`--rpc-ws-api`](../options.md#rpc-ws-api) option.
:::
## `plugins_reloadPluginConfig`
When you call this method without parameters, all plugins are reloaded. If you specify names, only
those plugins are reloaded. This method awaits all reloads before returning its result.
### Parameters
- `plugin`: _string_ - (Optional) Plugin name.
### Returns
- `Success` if the plugins reload.
If one or more plugins fail, the error response provides a comma-separated list of `:success` or `:failure (reason)`.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "plugins_reloadPluginConfig",
"params": [
"tech.pegasys.plus.plugin.kafka.KafkaPlugin"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "plugins_reloadPluginConfig",
"params": [
"tech.pegasys.plus.plugin.kafka.KafkaPlugin"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## TRACE methods(Api)
# `TRACE` methods
The `TRACE` API is a more concise alternative to the [`DEBUG` API](debug/index.md).
:::note
The `TRACE` API is not enabled by default for JSON-RPC.
Enable it using the [`--rpc-http-api`](../options.md#rpc-http-api) or [`--rpc-ws-api`](../options.md#rpc-ws-api) option.
:::
## `trace_block`
Provides transaction processing of type [`trace`](#trace) for the specified block.
:::info note
Your node must be an [archive node](../../concepts/node-sync.md#archive-nodes), or
the requested block must be within the number of
[blocks retained](../options.md#bonsai-historical-block-limit) when using
[Bonsai](../../concepts/data-storage-formats.md#bonsai-tries) (by default, 512 from the head of the chain).
:::
Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
Returns
- List of [calls to other contracts](#trace) containing one object per call, in transaction execution order; if revert reason is enabled with [`--revert-reason-enabled`](../options.md#revert-reason-enabled), the returned list items include the [revert reason](../../../private-networks/how-to/send-transactions/revert-reason.md).
Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "trace_block",
"params": [
"0x6"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "trace_block",
"params": [
"0x6"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"result": [
{
"action": {
"callType": "call",
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0xffad82",
"input": "0x0000000000000000000000000000000000000999",
"to": "0x0020000000000000000000000000000000000000",
"value": "0x0"
},
"blockHash": "0x71512d31e18f828cef069a87bc2c7514a8ca334f9ee72625efdf5cc2d43768dd",
"blockNumber": 6,
"result": {
"gasUsed": "0x7536",
"output": "0x"
},
"subtraces": 1,
"traceAddress": [],
"transactionHash": "0x91eeabc671e2dd2b1c8ddebb46ba59e8cb3e7d189f80bcc868a9787728c6e59e",
"transactionPosition": 0,
"type": "call"
},
{
"action": {
"address": "0x0020000000000000000000000000000000000000",
"balance": "0x300",
"refundAddress": "0x0000000000000999000000000000000000000000"
},
"blockHash": "0x71512d31e18f828cef069a87bc2c7514a8ca334f9ee72625efdf5cc2d43768dd",
"blockNumber": 6,
"result": null,
"subtraces": 0,
"traceAddress": [0],
"transactionHash": "0x91eeabc671e2dd2b1c8ddebb46ba59e8cb3e7d189f80bcc868a9787728c6e59e",
"transactionPosition": 0,
"type": "suicide"
},
{
"action": {
"author": "0x0000000000000000000000000000000000000000",
"rewardType": "block",
"value": "0x1bc16d674ec80000"
},
"blockHash": "0x71512d31e18f828cef069a87bc2c7514a8ca334f9ee72625efdf5cc2d43768dd",
"blockNumber": 6,
"result": null,
"subtraces": 0,
"traceAddress": [],
"transactionHash": null,
"transactionPosition": null,
"type": "reward"
}
],
"id": 1
}
```
---
## `trace_call`
Executes the given call and returns a number of possible traces for it.
:::info note
When using [Bonsai](../../concepts/data-storage-formats.md#bonsai-tries), the requested block must
be within the number of [blocks retained](../options.md#bonsai-historical-block-limit) (by
default, 512 from the head of the chain).
:::
Parameters
- `call`: _object_ - Transaction call object.
- `from`: _data, 20 bytes_ - Address of the sender.
- `to`: _data, 20 bytes_ - Address of the action receiver.
- `gas`: _quantity, integer_ - Gas provided by the sender. `eth_call` consumes zero gas, but other executions might need this parameter. `eth_estimateGas` ignores this value.
- `gasPrice`: _quantity, integer_ - Gas price, in Wei, provided by the sender. The default is `0`. Used only in non-[`EIP1559`](../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Can be used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxFeePerGas`.
- `maxFeePerGas`: _quantity, integer_ - Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Can be used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions). If used, must specify `maxPriorityFeePerGas`.
- `maxFeePerBlobGas`: _quantity, integer_ - Maximum fee the sender is willing to pay per blob gas. Only used for blob transactions introduced in [EIP-4844]( https://eips.ethereum.org/EIPS/eip-4844).
- `nonce`: _quantity, integer_ - Number of transactions made by the sender before this one. The default is the sender's nonce.
- `value`: _quantity, integer_ - Value transferred, in Wei.
- `data`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `input` if both parameters are provided.
- `input`: _data_ - Hash of the method signature and encoded parameters. For details, see [Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html). Must be equal to `data` if both parameters are provided.
- `accessList`: _array_ - List of addresses and storage keys that the transaction plans to access. Used only in non-[`FRONTIER`](../../concepts/transactions/types.md#frontier-transactions) transactions.
- `strict`: _tag_ - Determines if the sender account balance is considered during gas estimation. If `true`, the sender's balance is checked against the transaction's gas parameters. This ensures the estimated gas reflects what the sender can actually afford. If `false`, the balance checks are skipped. The default is `true`.
- `blobVersionedHashes`: _array_ - List of references to blobs introduced in [EIP-4844]( https://eips.ethereum.org/EIPS/eip-4844).
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
- `options`: _array_ of _strings_ - List of tracing options; tracing options are [`trace`](#trace), [`vmTrace`](#vmtrace), and [`stateDiff`](#statediff). Specify any combination of the three options including none of them.
Returns
- Object containing the trace results for the call, depending on the requested `options`.
- `output`: _data_ - Return value of the call.
- `stateDiff`: _object_ - [State changes in the requested block](#statediff), or `null` if `stateDiff` wasn't a requested option.
- `trace`: _array_ - [Ordered list of calls to other contracts](#trace), or an empty array if `trace` wasn't a requested option.
- `vmTrace`: _object_ - [Ordered list of EVM actions](#vmtrace), or `null` if `vmTrace` wasn't a requested option.
Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "trace_call",
"params": [
{
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"to": "0x0010000000000000000000000000000000000000",
"gas": "0xfffff2",
"gasPrice": "0xef",
"value": "0x0",
"data": "0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002",
"nonce": "0x0"
},
[
"trace"
],
"latest"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "trace_call",
"params": [
{
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"to": "0x0010000000000000000000000000000000000000",
"gas": "0xfffff2",
"gasPrice": "0xef",
"value": "0x0",
"data": "0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002",
"nonce": "0x0"
},
[
"trace"
],
"latest"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"result": {
"output" : "0x",
"stateDiff" : null,
"trace" : [ {
"action" : {
"callType" : "call",
"from" : "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas" : "0xffabba",
"input" : "0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002",
"to" : "0x0010000000000000000000000000000000000000",
"value" : "0x0"
},
"result" : {
"gasUsed" : "0x9c58",
"output" : "0x"
},
"subtraces" : 0,
"traceAddress" : [ ],
"type" : "call"
} ],
"vmTrace" : null
},
"id" : 2
},
```
---
## `trace_callMany`
Performs multiple call traces on top of the same block. You can trace dependent transactions.
:::info note
When using [Bonsai](../../concepts/data-storage-formats.md#bonsai-tries), the requested block must
be within the number of [blocks retained](../options.md#bonsai-historical-block-limit) (by
default, 512 from the head of the chain).
:::
Parameters
- `options`: _array_ of _strings_ - List of tracing options; tracing options are [`trace`](#trace), [`vmTrace`](#vmtrace), and [`stateDiff`](#statediff). Specify any combination of the three options including none of them.
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
Returns
- List of objects containing the trace results for each call, in the order the calls were specified, one object per call, depending on the requested `options`.
- `output`: _data_ - Return value of the call.
- `stateDiff`: _object_ - [State changes in the requested block](#statediff), or `null` if `stateDiff` wasn't a requested option.
- `trace`: _array_ - [Ordered list of calls to other contracts](#trace), or an empty array if `trace` wasn't a requested option.
- `vmTrace`: _object_ - [Ordered list of EVM actions](#vmtrace), or `null` if `vmTrace` wasn't a requested option.
Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "trace_callMany",
"params": [
[
[
{
"from": "0x407d73d8a49eeb85d32cf465507dd71d507100c1",
"to": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"value": "0x186a0"
},
[
"trace"
]
],
[
{
"from": "0x407d73d8a49eeb85d32cf465507dd71d507100c1",
"to": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"value": "0x186a0"
},
[
"trace"
]
]
],
"latest"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "trace_callMany",
"params": [
[
[
{
"from": "0x407d73d8a49eeb85d32cf465507dd71d507100c1",
"to": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"value": "0x186a0"
},
[
"trace"
]
],
[
{
"from": "0x407d73d8a49eeb85d32cf465507dd71d507100c1",
"to": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"value": "0x186a0"
},
[
"trace"
]
]
],
"latest"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"result": [
{
"output" : "0x",
"stateDiff" : null,
"trace" : [ {
"action" : {
"callType" : "call",
"from" : "0x407d73d8a49eeb85d32cf465507dd71d507100c1",
"gas" : "0x1dcd12f8",
"input" : "0x",
"to" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"value" : "0x186a0"
},
"result" : {
"gasUsed" : "0x0",
"output" : "0x"
},
"subtraces" : 0,
"traceAddress" : [ ],
"type" : "call"
} ],
"vmTrace" : null
},
{
"output" : "0x",
"stateDiff" : null,
"trace" : [ {
"action" : {
"callType" : "call",
"from" : "0x407d73d8a49eeb85d32cf465507dd71d507100c1",
"gas" : "0x1dcd12f8",
"input" : "0x",
"to" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"value" : "0x186a0"
},
"result" : {
"gasUsed" : "0x0",
"output" : "0x"
},
"subtraces" : 0,
"traceAddress" : [ ],
"type" : "call"
} ],
"vmTrace" : null
},
],
"id" : 1
},
```
---
## `trace_filter`
Returns traces matching the specified filter. The maximum number of blocks you can supply to `trace_filter` is 1000 by default. You can adjust this limit using the [`--rpc-max-trace-filter-range`](../options.md#rpc-max-trace-filter-range) option.
:::info note
Your node must be an [archive node](../../concepts/node-sync.md#archive-nodes), or
the requested blocks must be within the number of
[blocks retained](../options.md#bonsai-historical-block-limit) when using
[Bonsai](../../concepts/data-storage-formats.md#bonsai-tries) (by default, 512 from the head of the chain).
:::
Parameters
- `traceFilterOptions`: _object_ - Trace filter options object.
- `fromBLock`: _String | Tag_ - Trace starts at this block.
- `toBlock`: _String | Tag_ - Trace stops at this block.
- `fromAddress`: _string_ - Include only traces sent from this address.
- `toAddress`: _string_ - Include only traces with this destination address.
- `after`: _quantity_ - The offset trace number.
- `count`: _integer_ - Number of traces to display in a batch.
Returns
- List of [calls to other contracts](#trace) containing one object per call, in transaction execution order.
Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "trace_filter",
"params": [
{
"fromBlock": "0x1",
"toBlock": "0x21",
"after": 2,
"count": 2,
"fromAddress": [
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"
]
}
],
"id": 415
}'
```
```json
{
"jsonrpc": "2.0",
"method": "trace_filter",
"params": [
{
"fromBlock": "0x1",
"toBlock": "0x21",
"after": 2,
"count": 2,
"fromAddress": [
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"
]
}
],
"id": 415
}
```
```json
{
"jsonrpc": "2.0",
"result": [
{
"action": {
"callType": "call",
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0xffad82",
"input": "0x0000000000000000000000000000000000000999",
"to": "0x0020000000000000000000000000000000000000",
"value": "0x0"
},
"blockHash": "0xcd5d9c7acdcbd3fb4b24a39e05a38e32235751bb0c9e4f1aa16dc598a2c2a9e4",
"blockNumber": 6,
"result": {
"gasUsed": "0x7536",
"output": "0x"
},
"subtraces": 1,
"traceAddress": [],
"transactionHash": "0x91eeabc671e2dd2b1c8ddebb46ba59e8cb3e7d189f80bcc868a9787728c6e59e",
"transactionPosition": 0,
"type": "call"
},
{
"action": {
"callType": "call",
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0xffad52",
"input": "0xf000000000000000000000000000000000000000000000000000000000000001",
"to": "0x0030000000000000000000000000000000000000",
"value": "0x0"
},
"blockHash": "0xeed85fe57db751442c826cfe4fdf43b10a5c2bc8b6fd3a8ccced48eb3fb35885",
"blockNumber": 7,
"result": {
"gasUsed": "0x1b",
"output": "0xf000000000000000000000000000000000000000000000000000000000000002"
},
"subtraces": 0,
"traceAddress": [],
"transactionHash": "0x47f4d445ea1812cb1ddd3464ab23d2bfc6ed408a8a9db1c497f94e8e06e85286",
"transactionPosition": 0,
"type": "call"
}
],
"id": 415
}
```
---
## `trace_get`
Returns a trace at the given position.
:::info note
Your node must be an [archive node](../../concepts/node-sync.md#archive-nodes), or
the requested transaction must be contained in a block within the number of
[blocks retained](../options.md#bonsai-historical-block-limit) when using
[Bonsai](../../concepts/data-storage-formats.md#bonsai-tries) (by default, 512 from the head of the chain).
:::
Parameters
- `transaction`: _string_ - Transaction hash.
- `indexPositions`: _array_ - Index positions of the traces.
Returns
- List of [calls to other contracts](#trace) containing one object per call, in the order called by the transaction.
Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "trace_get",
"params": [
"0x17104ac9d3312d8c136b7f44d4b8b47852618065ebfa534bd2d3b5ef218ca1f3",
[
"0x0"
]
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "trace_get",
"params": [
"0x17104ac9d3312d8c136b7f44d4b8b47852618065ebfa534bd2d3b5ef218ca1f3",
[
"0x0"
]
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"result": {
"action" : {
"callType" : "call",
"from" : "0x1c39ba39e4735cb65978d4db400ddd70a72dc750",
"gas" : "0x13e99",
"input" : "0x16c72721",
"to" : "0x2bd2326c993dfaef84f696526064ff22eba5b362",
"value" : "0x0"
},
"blockHash" : "0x7eb25504e4c202cf3d62fd585d3e238f592c780cca82dacb2ed3cb5b38883add"
"blockNumber": 3068185,
"result": {
"gasUsed": "0x183",
"output" : "0x0000000000000000000000000000000000000000000000000000000000000001"
},
"subtraces" : 0,
"traceAddress" : [
0
],
"transactionHash": "0x17104ac9d3312d8c136b7f44d4b8b47852618065ebfa534bd2d3b5ef218ca1f3",
"transactionPosition": 2,
"type" : "call"
},
"id" : 1
},
```
---
## `trace_rawTransaction`
Traces a call to `eth_sendRawTransaction` without making the call, returning the traces.
:::info note
When using [Bonsai](../../concepts/data-storage-formats.md#bonsai-tries), the requested transaction
must be contained in a block within the number of
[blocks retained](../options.md#bonsai-historical-block-limit) (by default, 512 from the head of
the chain).
:::
Parameters
- `data` - _string_ - Raw transaction data.
- `options`: _array_ of _strings_ - List of tracing options; tracing options are [`trace`](#trace), [`vmTrace`](#vmtrace), and [`stateDiff`](#statediff). Specify any combination of the three options including none of them.
Returns
- Object containing the trace results for the transaction, depending on the requested `options`.
- `output`: _data_ - Return value of the transaction.
- `from`: _data, 20 bytes_ - Address of the transaction sender.
- `stateDiff`: _object_ - [State changes in the requested block](#statediff), or `null` if `stateDiff` wasn't a requested option.
- `trace`: _array_ - [Ordered list of calls to other contracts](#trace), or an empty array if `trace` wasn't a requested option.
- `vmTrace`: _object_ - [Ordered list of EVM actions](#vmtrace), or `null` if `vmTrace` wasn't a requested option.
Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "trace_rawTransaction",
"params": [
"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675",
[
"trace"
]
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "trace_rawTransaction",
"params": [
"0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675",
[
"trace"
]
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"result": {
"output" : "0x"
"stateDiff": null,
"from" : "0x1c39ba39e4735cb65978d4db400ddd70a72dc750",
"trace": [{
"action": { ... },
"result": {
"gasUsed": "0x0",
"output": "0x"
}
"subtraces": 0,
"traceAddress": [],
"type": "call"
}],
"vmTrace": null
},
"id" : 1
},
```
---
## `trace_replayBlockTransactions`
Provides transaction processing tracing per block.
:::info note
When using [Bonsai](../../concepts/data-storage-formats.md#bonsai-tries), the requested block must
be within the number of [blocks retained](../options.md#bonsai-historical-block-limit) (by
default, 512 from the head of the chain).
:::
Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
- `options`: _array_ of _strings_ - List of tracing options; tracing options are [`trace`](#trace), [`vmTrace`](#vmtrace), and [`stateDiff`](#statediff). Specify any combination of the three options including none of them.
Returns
- List of transaction trace objects containing one object per transaction, in transaction execution order; if revert reason is enabled with [`--revert-reason-enabled`](../options.md#revert-reason-enabled), the [`trace`](#trace) list items in the returned transaction trace object include the [revert reason](../../../private-networks/how-to/send-transactions/revert-reason.md).
- `output`: _boolean_ - Transaction result. 1 for success and 0 for failure.
- `stateDiff`: _object_ - [State changes in the requested block](#statediff).
- `trace`: _array_ - [Ordered list of calls to other contracts](#trace).
- `vmTrace`: _object_ - [Ordered list of EVM actions](#vmtrace).
- `transactionHash`: _data, 32 bytes_ - Hash of the replayed transaction.
Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x12",
[
"trace",
"vmTrace",
"stateDiff"
]
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "trace_replayBlockTransactions",
"params": [
"0x12",
[
"trace",
"vmTrace",
"stateDiff"
]
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result":[
{
"output":"0x",
"vmTrace":{
"code":"0x7f3940be4289e4c3587d88c1856cc95352461992db0a584c281226faefe560b3016000527f14c4d2c102bdeb2354bfc3dc96a95e4512cf3a8461e0560e2272dbf884ef3905601052600851",
"ops":[
{
"cost":3,
"ex":{
"mem":null,
"push":[
"0x8"
],
"store":null,
"used":16756175
},
"pc":72,
"sub":null
},
...
]
},
"trace":[
{
"action":{
"callType":"call",
"from":"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas":"0xffadea",
"input":"0x",
"to":"0x0100000000000000000000000000000000000000",
"value":"0x0"
},
"result":{
"gasUsed":"0x1e",
"output":"0x"
},
"subtraces":0,
"traceAddress":[
],
"type":"call"
}
],
"stateDiff":{
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73":{
"balance":{
"*":{
"from":"0xffffffffffffffffffffffffffffffffc3e12a20b",
"to":"0xffffffffffffffffffffffffffffffffc3dc5f091"
}
},
"code":"=",
"nonce":{
"*":{
"from":"0x14",
"to":"0x15"
}
},
"storage":{
}
}
},
"transactionHash":"0x2a5079cc535c429f668f13a7fb9a28bdba6831b5462bd04f781777b332a8fcbd",
},
{...}
]
}
```
---
## `trace_transaction`
Provides transaction processing of type [`trace`](#trace) for the specified transaction.
:::info note
Your node must be an [archive node](../../concepts/node-sync.md#archive-nodes), or
the requested transaction must be contained in a block within the number of
[blocks retained](../options.md#bonsai-historical-block-limit) when using
[Bonsai](../../concepts/data-storage-formats.md#bonsai-tries) (by default, 512 from the head of the chain).
:::
Parameters
- `transaction`: _string_ - Transaction hash.
Returns
- List of [calls to other contracts](#trace) containing one object per call, in the order called by the transaction; if revert reason is enabled with [`--revert-reason-enabled`](../options.md#revert-reason-enabled), the returned list items include the [revert reason](../../../private-networks/how-to/send-transactions/revert-reason.md).
Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "trace_transaction",
"params": [
"0x4c253746668dca6ac3f7b9bc18248b558a95b5fc881d140872c2dff984d344a7"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "trace_transaction",
"params": [
"0x4c253746668dca6ac3f7b9bc18248b558a95b5fc881d140872c2dff984d344a7"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"result": [
{
"action": {
"creationMethod": "create",
"from": "0x627306090abab3a6e1400e9345bc60c78a8bef57",
"gas": "0xff2e26",
"init": "0x60006000600060006000732c2b9c9a4a25e24b174f26114e8926a9f2128fe45af2600060006000600060007300a00000000000000000000000000000000000005af2",
"value": "0x0"
},
"blockHash": "0x7e9a993adc6f043c0a9b6a385e6ed3fa370586c55823251b8fa7033cf89d414e",
"blockNumber": 19,
"result": {
"address": "0x30753e4a8aad7f8597332e813735def5dd395028",
"code": "0x",
"gasUsed": "0x1c39"
},
"subtraces": 2,
"traceAddress": [],
"transactionHash": "0x4c253746668dca6ac3f7b9bc18248b558a95b5fc881d140872c2dff984d344a7",
"transactionPosition": 3,
"type": "create"
},
{
"action": {
"callType": "callcode",
"from": "0x30753e4a8aad7f8597332e813735def5dd395028",
"gas": "0xfb2ea9",
"input": "0x",
"to": "0x2c2b9c9a4a25e24b174f26114e8926a9f2128fe4",
"value": "0x0"
},
"blockHash": "0x7e9a993adc6f043c0a9b6a385e6ed3fa370586c55823251b8fa7033cf89d414e",
"blockNumber": 19,
"result": {
"gasUsed": "0x138e",
"output": "0x"
},
"subtraces": 1,
"traceAddress": [0],
"transactionHash": "0x4c253746668dca6ac3f7b9bc18248b558a95b5fc881d140872c2dff984d344a7",
"transactionPosition": 3,
"type": "call"
},
{
"action": {
"address": "0x30753e4a8aad7f8597332e813735def5dd395028",
"balance": "0x0",
"refundAddress": "0x0000000000000000000000000000000000000000"
},
"blockHash": "0x7e9a993adc6f043c0a9b6a385e6ed3fa370586c55823251b8fa7033cf89d414e",
"blockNumber": 19,
"result": null,
"subtraces": 0,
"traceAddress": [0, 0],
"transactionHash": "0x4c253746668dca6ac3f7b9bc18248b558a95b5fc881d140872c2dff984d344a7",
"transactionPosition": 3,
"type": "suicide"
},
{
"action": {
"callType": "callcode",
"from": "0x30753e4a8aad7f8597332e813735def5dd395028",
"gas": "0xfb18a5",
"input": "0x",
"to": "0x00a0000000000000000000000000000000000000",
"value": "0x0"
},
"blockHash": "0x7e9a993adc6f043c0a9b6a385e6ed3fa370586c55823251b8fa7033cf89d414e",
"blockNumber": 19,
"result": {
"gasUsed": "0x30b",
"output": "0x"
},
"subtraces": 0,
"traceAddress": [1],
"transactionHash": "0x4c253746668dca6ac3f7b9bc18248b558a95b5fc881d140872c2dff984d344a7",
"transactionPosition": 3,
"type": "call"
}
],
"id": 1
}
```
---
## Trace types
### `trace`
An ordered list of calls to other contracts, excluding precompiled contracts.
Each item in the list is an object with the following fields.
- `action`: _object_ - Transaction details.
- `callType`: _string_ - Whether the transaction is `call` or `create`.
- `from`: _data, 20 bytes_ - Address of the transaction sender.
- `gas`: _quantity_ - Gas provided by sender.
- `input`: _data_ - Transaction data.
- `to`: _data, 20 bytes_ - Target of the transaction.
- `value`: _quantity_ - Value transferred in the transaction.
- `result`: _object_ - Transaction result.
- `gasUsed`: _quantity_ - Gas used by the transaction. Includes any refunds of unused gas.
- `output`: _data_ - Return value of the contract call. Contains only the actual value sent by a `RETURN` operation. If a `RETURN` was not executed, the output is empty bytes.
- `subtraces`: _integer_ - Traces of contract calls made by the transaction.
- `traceAddress`: _array_ - Tree list address of where the call occurred, address of the parents, and order of the current sub call.
- `type`: _string_ - Whether the transaction is a `CALL` or `CREATE` series operation.
#### Example
```json
"trace":[
{
"action":{
"callType":"call",
"from":"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas":"0xffadea",
"input":"0x",
"to":"0x0100000000000000000000000000000000000000",
"value":"0x0"
},
"result":{
"gasUsed":"0x1e",
"output":"0x"
},
"subtraces":0,
"traceAddress":[
],
"type":"call"
}
]
```
### `vmTrace`
An object containing the following fields.
- `code`: _data_ - Code executed by the EVM.
- `ops`: _array_ - Sequence of EVM operations (opcodes) executed in the transaction.
- `cost`: _quantity_ - Gas cost of the opcode. Includes memory expansion costs but not gas refunds. For precompiled contract calls, reports only the actual cost.
- `ex`: _object_ - Executed operations.
- `mem`: _object_ - Memory read or written by the operation.
- `push`: _array_ - Adjusted stack items. For swap, includes all intermediate values and the result. Otherwise, is the value pushed onto the stack.
- `store`: _object_ - Account storage written by the operation.
- `used`: _quantity_ - Remaining gas taking into account the all but 1/64th rule for calls.
- `pc`: _quantity_ - Program counter.
- `sub`: _object_ - Sub call operations.
`vmTrace` only reports actual data returned from a `RETURN` opcode and does not return the contents of the reserved output space for the call operations. As a result:
- `vmTrace` reports `null` when a call operation ends because of a `STOP`, `HALT`, `REVERT`, running out of instructions, or any exceptional halts.
- When a `RETURN` operation returns data of a different length to the space reserved by the call, `vmTrace` reports only the data passed to the `RETURN` operation and does not include pre-existing memory data or trim the returned data.
For out of gas operations, `vmTrace` reports the operation that caused the out of gas exception, including the calculated gas cost. `vmTrace` does not report `ex` values because the operation is not executed.
#### Example
```json
"vmTrace":{
"code":"0x7f3940be4289e4c3587d88c1856cc95352461992db0a584c281226faefe560b3016000527f14c4d2c102bdeb2354bfc3dc96a95e4512cf3a8461e0560e2272dbf884ef3905601052600851",
"ops":[
{
"cost":3,
"ex":{
"mem":null,
"push":[
"0x8"
],
"store":null,
"used":16756175
},
"pc":72,
"sub":null
},
...
]
}
```
### `stateDiff`
State changes in the requested block for each transaction represented as a map of accounts to an object.
Besu lists the balance, code, nonce, and storage changes from immediately before the transaction to after the transaction.
- `balance`: _string or object_ - Change of balance.
- `code`: _string or object_ - Change to the account's code.
- `nonce`: _string or object_ - Change of nonce.
- `storage`: _object_ - Map of each changed storage slot key to its diff value.
Each of the `balance`, `code`, and `nonce` values, and each changed storage slot in `storage`, uses one of the following notations, depending on the type of change:
- `"="` - The value didn't change.
- `{"+": }` - The value didn't exist before the transaction and now has the specified value.
- `{"-": }` - The value existed before the transaction and was deleted.
- `{"*": {"from": , "to": }}` - The value changed from one value to another.
An absent value is distinct from zero when creating accounts or clearing storage.
#### Example
```json
"stateDiff":{
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73":{
"balance":{
"*":{
"from":"0xffffffffffffffffffffffffffffffffc3e12a20b",
"to":"0xffffffffffffffffffffffffffffffffc3dc5f091"
}
},
"code":"=",
"nonce":{
"*":{
"from":"0x14",
"to":"0x15"
}
},
"storage":{
}
}
}
```
---
## TXPOOL methods
# `TXPOOL` methods
The `TXPOOL` API methods allow you to inspect the contents of the transaction pool.
:::note
The `TXPOOL` API is not enabled by default for JSON-RPC.
Enable it using the [`--rpc-http-api`](../options.md#rpc-http-api) or [`--rpc-ws-api`](../options.md#rpc-ws-api) option.
:::
## `txpool_besuPendingTransactions`
Lists pending transactions that match the supplied filter conditions.
### Parameters
- `numResults`: _number_ - Integer representing the maximum number of results to return.
- `fields`: _object_ - Object of fields used to create the filter condition.
Each field in the object corresponds to a field name containing an operator, and a value for the operator.
A field name can only be specified once, and can only contain one operator.
For example, you cannot query transactions with a gas price between 8 and 9 Gwei by using both the `gt` and `lt` operator in the same field name instance.
All filters must be satisfied for a transaction to be returned.
:::note
The available operators are `eq` (equal to), `lt` (less than), `gt` (greater than), and `action`.
The only supported `action` is `"contract_creation"`.
:::
- `from`: _data, 20 bytes_ - Address of the sender. Supported operator: `eq`.
- `to`: _data, 20 bytes_ - Address of the receiver, or `"contract_creation"`.
Supported operators: `eq`, `action`.
- `gas`: _quantity_ - Gas provided by the sender.
Supported operators: `eq`, `gt`, `lt`.
- `gasPrice`: _quantity_ - Gas price, in wei, provided by the sender.
Supported operators: `eq`, `gt`, `lt`.
- `value`: _quantity_ - Value transferred, in wei.
Supported operators: `eq`, `gt`, `lt`.
- `nonce`: _quantity_ - Number of transactions made by the sender.
Supported operators: `eq`, `gt`, `lt`.
### Returns
- List of objects with details of the pending transaction.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in wei, provided by the sender. Not used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionType`: _string_ - [Transaction type](../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "txpool_besuPendingTransactions",
"params": [
2,
{
"from": {
"eq": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"
},
"gas": {
"lt": "0x5209"
},
"nonce": {
"gt": "0x1"
}
}
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "txpool_besuPendingTransactions",
"params": [
2,
{
"from": {
"eq": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"
},
"gas": {
"lt": "0x5209"
},
"nonce": {
"gt": "0x1"
}
}
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0x5208",
"gasPrice": "0xab5d04c00",
"hash": "0xb7b2f4306c1c228ec94043da73b582594007091a7dfe024b1f8d6d772284e54b",
"input": "0x",
"nonce": "0x2",
"to": "0xf8be4ebda7f62d79a665294ec1263bfdb59aabf2",
"value": "0x0",
"v": "0xfe8",
"r": "0x5beb711e652c6cf0a589d3cea904eefc4f45ce4372652288701d08cc4412086d",
"s": "0x3af14a56e63aa5fb7dcb444a89708363a9d2c1eba1f777c67690288415080ded"
}
]
}
```
---
## `txpool_besuStatistics`
Lists statistics about the node transaction pool.
### Parameters
- None
### Returns
- Transaction pool statistics object.
- `maxSize`: _number_ - Maximum number of transactions kept in the transaction pool; use the [`--tx-pool-max-size`](../options.md#tx-pool-max-size) option to configure the maximum size.
- `localCount`: _number_ - Number of transactions submitted directly to this node.
- `remoteCount`: _number_ - Number of transactions received from remote nodes.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "txpool_besuStatistics",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "txpool_besuStatistics",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"maxSize": 4096,
"localCount": 1,
"remoteCount": 0
}
}
```
---
## `txpool_besuTransactions`
Lists transactions in the node transaction pool.
### Parameters
- None
### Returns
- List of transactions.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "txpool_besuTransactions",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "txpool_besuTransactions",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"hash": "0x8a66830098be4006a3f63a03b6e9b67aa721e04bd6b46d420b8f1937689fb4f1",
"isReceivedFromLocalSource": true,
"addedToPoolAt": "2019-03-21T01:35:50.911Z"
},
{
"hash": "0x41ee803c3987ceb5bcea0fad7a76a8106a2a6dd654409007d9931032ea54579b",
"isReceivedFromLocalSource": true,
"addedToPoolAt": "2019-03-21T01:36:00.374Z"
}
]
}
```
---
## `txpool_content`
Returns all pending and queued transactions in the pool, grouped by
sender address and sorted by nonce.
### Parameters
- None
### Returns
- Transaction pool content object.
- `pending`: _object_ - Map of sender addresses to maps of nonces to transaction objects,
for transactions pending inclusion in the next block.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
- `queued`: _object_ - Map of sender addresses to maps of nonces to transaction objects,
for transactions scheduled for future execution.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "txpool_content",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "txpool_content",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"pending": {
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"6": {
"blockHash": null,
"blockNumber": null,
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0x5208",
"gasPrice": "0xab5d04c00",
"hash": "0xb7b2f4306c1c228ec94043da73b582594007091a7dfe024b1f8d6d772284e54b",
"input": "0x",
"nonce": "0x6",
"to": "0xf8be4ebda7f62d79a665294ec1263bfdb59aabf2",
"transactionIndex": null,
"value": "0xde0b6b3a7640000",
"v": "0xfe8",
"r": "0x5beb711e652c6cf0a589d3cea904eefc4f45ce4372652288701d08cc4412086d",
"s": "0x3af14a56e63aa5fb7dcb444a89708363a9d2c1eba1f777c67690288415080ded"
}
}
},
"queued": {
"0x1932c48b2bf8102ba33b4a6b545c32236e342f34": {
"12": {
"blockHash": null,
"blockNumber": null,
"from": "0x1932c48b2bf8102ba33b4a6b545c32236e342f34",
"gas": "0x15f90",
"gasPrice": "0x2cb417800",
"hash": "0x7b959f5d8d906b74f646b9e6c43d808c3a13f72ae39ee2ca5531f6a83e38e0cf",
"input": "0x",
"nonce": "0xc",
"to": "0x27f1e53f9861ab84aa62a2c8b9f5f0617edddfeb",
"transactionIndex": null,
"value": "0x0",
"v": "0xfe7",
"r": "0x78c32e3f5bba7cf08b2700c3ca37a2c80d2f073ff9b47f54e31d64e05e0a5b3d",
"s": "0x517a04dbc67f9de1f76d5e3d3a1b0fda61869b8fad04bef40f07e24e10cbfdee"
}
}
}
}
}
```
---
## `txpool_contentFrom`
Returns the pending and queued transactions for a given sender address.
### Parameters
- `address`: _string_ - Sender address.
### Returns
- Transaction pool content for the given address.
- `pending`: _object_ - Map of nonces to transaction objects, for pending transactions from the given address.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
- `queued`: _object_ - Map of nonces to transaction objects for queued transactions from the given address.
- `accessList`: _array_ - (Optional) List of addresses and storage keys the transaction plans to access. Used in [`ACCESS_LIST` transactions](../../concepts/transactions/types.md#access_list-transactions) and may be used in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `blockHash`: _data, 32 bytes_ - Hash of the block containing this transaction. `null` when transaction is pending.
- `blockNumber`: _quantity_ - Block number of the block containing this transaction. `null` when transaction is pending.
- `blockTimestamp`: _quantity_ - Hex-encoded Unix timestamp (in seconds) of the block containing this transaction. `null` when transaction is pending.
- `chainId`: _quantity_ - [Chain ID](../../concepts/network-and-chain-id.md).
- `from`: _data, 20 bytes_ - Address of the sender.
- `gas`: _quantity_ - Gas provided by the sender.
- `gasPrice`: _quantity_ - (Optional) Gas price, in Wei, provided by the sender. Used only in non-[`EIP1559`](../../concepts/transactions/types.md#eip1559-transactions) transactions.
- `maxPriorityFeePerGas`: _quantity, integer_ - (Optional) Maximum fee, in Wei, the sender is willing to pay per gas above the base fee. Used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `maxFeePerGas`: _quantity, integer_ - (Optional) Maximum total fee (base fee + priority fee), in Wei, the sender is willing to pay per gas. Used only in [`EIP1559` transactions](../../concepts/transactions/types.md#eip1559-transactions).
- `hash`: _data, 32 bytes_ - Hash of the transaction.
- `input`: _data_ - Data sent with the transaction to create or invoke a contract.
- `nonce`: _quantity_ - Number of transactions made by the sender before this one.
- `to`: _data, 20 bytes_ - Address of the receiver. `null` if a contract creation transaction.
- `transactionIndex`: _quantity, integer_ - Index position of the transaction in the block. `null` when transaction is pending.
- `transactionType`: _string_ - [Transaction type](../../concepts/transactions/types.md).
- `value`: _quantity_ - Value transferred, in Wei.
- `v`: _quantity_ - ECDSA Recovery ID.
- `r`: _data, 32 bytes_ - ECDSA signature r.
- `s`: _data, 32 bytes_ - ECDSA signature s.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "txpool_contentFrom",
"params": [
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "txpool_contentFrom",
"params": [
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"pending": {
"0": {
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0x5208",
"gasPrice": "0xab5d04c00",
"hash": "0xb7b2f4306c1c228ec94043da73b582594007091a7dfe024b1f8d6d772284e54b",
"input": "0x",
"nonce": "0x0",
"to": "0xf8be4ebda7f62d79a665294ec1263bfdb59aabf2",
"value": "0x0",
"v": "0xfe8",
"r": "0x5beb711e652c6cf0a589d3cea904eefc4f45ce4372652288701d08cc4412086d",
"s": "0x3af14a56e63aa5fb7dcb444a89708363a9d2c1eba1f777c67690288415080ded"
},
"1": {
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0x5208",
"gasPrice": "0xab5d04c00",
"hash": "0x1234abcd5678ef901234abcd5678ef901234abcd5678ef901234abcd5678ef90",
"input": "0x",
"nonce": "0x1",
"to": "0xf8be4ebda7f62d79a665294ec1263bfdb59aabf2",
"value": "0x0",
"v": "0xfe8",
"r": "0x1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"s": "0x2bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
}
},
"queued": {
"3": {
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0x5208",
"gasPrice": "0xab5d04c00",
"hash": "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
"input": "0x",
"nonce": "0x3",
"to": "0xf8be4ebda7f62d79a665294ec1263bfdb59aabf2",
"value": "0x0",
"v": "0xfe8",
"r": "0x3ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
"s": "0x4ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
}
}
}
}
```
---
## `txpool_inspect`
Returns a textual summary of all pending and queued transactions in the pool, grouped by sender
address and sorted by nonce.
The summary is free form, implementation-dependent, and meant to be consumed by humans.
For programmatic access to the transaction pool, use [`txpool_content`](#txpool_content).
### Parameters
- None
### Returns
- Transaction pool inspect object.
- `pending`: _object_ - Map of sender addresses to maps of nonces to human-readable transaction
summary strings, for transactions pending inclusion in the next block.
- `queued`: _object_ - Map of sender addresses to maps of nonces to human-readable transaction
summary strings, for transactions scheduled for future execution.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "txpool_inspect",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "txpool_inspect",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"pending": {
"0x67ee9a8c19f7873125a875f61add461b4a505d8c": {
"5": "{sequence: 68178, addedAt: 1775837774160, isLocal=false, hasPriority=false, score=127, 0xfbee0231c6140f9db3bbcef774b3626556f6f5528a6a49dcd38e1f7f86c79368={MessageCall, 5, 0x67ee9a8c19f7873125a875f61add461b4a505d8c, EIP1559, mf: 300.00 kwei, pf: 300.00 kwei, gl: 70926, v: 0 wei, to: 0xe9f8133e47d42bc9962e469721faaf75e385af31}}",
"6": "{sequence: 68179, addedAt: 1775837774160, isLocal=false, hasPriority=false, score=127, 0x3474c0582722ed751dba809363f58c8d1acea415831b81bc0b0b9f29afb19c19={MessageCall, 6, 0x67ee9a8c19f7873125a875f61add461b4a505d8c, EIP1559, mf: 2.00 mwei, pf: 2.00 mwei, gl: 90617, v: 0 wei, to: 0x1eb4a2620b909a8838e0e24a8e912bd32f4a47a3}}"
}
},
"queued": {
"0x5fa84846743cc07ab16106ceabad8e4e0ec1c1b6": {
"29": "{sequence: 2208499, addedAt: 1775952461706, isLocal=false, hasPriority=false, score=127, 0x2bb5f69f2b9737a99a3674018cd2aac5035b907a753a0c797051bc9df0b2a152={MessageCall, 29, 0x5fa84846743cc07ab16106ceabad8e4e0ec1c1b6, EIP1559, mf: 1.40 gwei, pf: 417.90 mwei, gl: 63209, v: 0 wei, to: 0xdac17f958d2ee523a2206206994597c13d831ec7}}",
"31": "{sequence: 1766002, addedAt: 1775931135467, isLocal=false, hasPriority=false, score=127, 0xdd250f166c086412fae187ef52dfbe1c4ff9405818781ac50f89d67a77a2d432={MessageCall, 31, 0x5fa84846743cc07ab16106ceabad8e4e0ec1c1b6, EIP1559, mf: 47.74 gwei, pf: 9.28 gwei, gl: 21000, v: 0 wei, to: 0x5fa84846743cc07ab16106ceabad8e4e0ec1c1b6}}"
}
}
}
}
```
---
## `txpool_status`
Returns the number of pending and queued transactions in the pool.
### Parameters
- None
### Returns
- Transaction count details.
- `pending`: _string_ - Count of the transactions currently pending for inclusion in the next
block or blocks.
- `queued`: _string_ - Count of the transactions that are scheduled for future execution
(transactions with nonce gaps).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "txpool_status",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "txpool_status",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"pending": "0xa",
"queued": "0x7"
}
}
```
---
## WEB3 methods
# `WEB3` methods
The `WEB3` API methods provide functionality for the Ethereum ecosystem.
## `web3_clientVersion`
Returns the current client version.
### Parameters
- None
### Returns
- Current client version.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "web3_clientVersion",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "web3_clientVersion",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": "besu/"
}
```
---
## `web3_sha3`
Returns a [SHA3](https://en.wikipedia.org/wiki/SHA-3) hash of the specified data. The result value is a [Keccak-256](https://keccak.team/keccak.html) hash, not the standardized SHA3-256.
### Parameters
- `data`: _string_ - Data to convert to a SHA3 hash.
### Returns
- SHA3 result of the input data.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "web3_sha3",
"params": [
"0x68656c6c6f20776f726c00"
],
"id": 53
}'
```
```json
{
"jsonrpc": "2.0",
"method": "web3_sha3",
"params": [
"0x68656c6c6f20776f726c00"
],
"id": 53
}
```
```json
{
"jsonrpc": "2.0",
"id": 53,
"result": "0x5e39a0a66544c0668bde22d61c47a8710000ece931f13b84d3b2feb44ec96d3f"
}
```
---
## Security disclosure policy
At Besu, security is a priority. But regardless of how much effort we put into system security, there might still be vulnerabilities present. If you discover a vulnerability, we need to know about it so we can take steps to address it as quickly as possible. We would like you to help us better protect our clients and our systems.
Please follow the process explained on [defect response wiki page](https://lf-hyperledger.atlassian.net/wiki/spaces/SEC/pages/20283618/Defect+Response).
---
## Engine API
# Engine API methods
[Consensus and execution clients](../concepts/node-clients.md#execution-and-consensus-clients) communicate with each other using the Engine API.
See [how to use the Engine API](../how-to/use-engine-api.md) to communicate with a consensus client.
:::info
The Engine API is enabled by default.
:::
Besu supports the following list of Engine API methods.
Each method links to its definition in the
[Ethereum execution APIs specification](https://ethereum.github.io/execution-apis/),
which documents the full request parameters, response fields, and examples.
Several methods have multiple versions because the Engine API adds a new versioned method whenever a hard fork changes a payload or parameter shape.
A consensus client calls the version appropriate for the network's currently active fork.
- [`engine_exchangeCapabilities`](https://ethereum.github.io/execution-apis/api/methods/engine_exchangeCapabilities) -
Exchanges a list of supported Engine API methods between the consensus client and Besu.
- [`engine_exchangeTransitionConfigurationV1`](https://ethereum.github.io/execution-apis/api/methods/engine_exchangeTransitionConfigurationV1) -
Sends the transition configuration to the consensus client to verify the configuration between both clients.
- [`engine_forkchoiceUpdatedV1`](https://ethereum.github.io/execution-apis/api/methods/engine_forkchoiceUpdatedV1), [`V2`](https://ethereum.github.io/execution-apis/api/methods/engine_forkchoiceUpdatedV2), [`V3`](https://ethereum.github.io/execution-apis/api/methods/engine_forkchoiceUpdatedV3), [`V4`](https://ethereum.github.io/execution-apis/api/methods/engine_forkchoiceUpdatedV4) - Updates the fork choice with the consensus client.
- [`engine_getBlobsV1`](https://ethereum.github.io/execution-apis/api/methods/engine_getBlobsV1), [`V2`](https://ethereum.github.io/execution-apis/api/methods/engine_getBlobsV2), [`V3`](https://ethereum.github.io/execution-apis/api/methods/engine_getBlobsV3) - Returns the blobs corresponding to the specified blob versioned hashes.
- [`engine_getClientVersionV1`](https://github.com/ethereum/execution-apis/blob/main/src/engine/identification.md#engine_getclientversionv1) - Exchanges the current client version.
- [`engine_getPayloadV1`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadV1), [`V2`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadV2), [`V3`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadV3),
[`V4`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadV4),
[`V5`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadV5),
[`V6`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadV6) - Prepares the payload to send to the consensus client.
- [`engine_getPayloadBodiesByHashV1`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadBodiesByHashV1), [`V2`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadBodiesByHashV2) - Returns execution payload bodies for the specified block hashes.
- [`engine_getPayloadBodiesByRangeV1`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadBodiesByRangeV1), [`V2`](https://ethereum.github.io/execution-apis/api/methods/engine_getPayloadBodiesByRangeV2) - Returns execution payload bodies for the specified range of block numbers.
- [`engine_newPayloadV1`](https://ethereum.github.io/execution-apis/api/methods/engine_newPayloadV1),
[`V2`](https://ethereum.github.io/execution-apis/api/methods/engine_newPayloadV2),
[`V3`](https://ethereum.github.io/execution-apis/api/methods/engine_newPayloadV3),
[`V4`](https://ethereum.github.io/execution-apis/api/methods/engine_newPayloadV4),
[`V5`](https://ethereum.github.io/execution-apis/api/methods/engine_newPayloadV5) - Executes the payload with the consensus client.
---
## EVM tool options
# EVM tool reference
This reference describes [options](#options) and [subcommands](#subcommands) for the
[EVM tool](../how-to/troubleshoot/evm-tool.md).
:::note
Option names that include `trace`, such as [`--trace`](#json-trace) and [`--trace.[no]memory`](#nomemory-tracenomemory) exist to support [`t8ntool`](https://ethereum-tests.readthedocs.io/en/latest/t8ntool.html) reference testing, and are interchangeable with their standard option names.
:::
## Options
### `code`
```bash
--code=
```
```bash
--code=5B600080808060045AFA50600056
```
The code to be executed, in compiled hex code form. Execution fails if this is not set.
### `gas`
```bash
--gas=
```
```bash
--gas=100000000
```
Amount of gas to make available to the EVM. The default is 10 billion, a number unlikely to be seen in any production blockchain.
### `price`
```bash
--price=
```
```bash
--price=10
```
Price of gas in Gwei. The default is `0`. If set to a non-zero value, the sender account must have enough value to cover the gas fees.
### `sender`
```bash
--sender=
```
```bash
--sender=0xfe3b557e8fb62b89f4916b721be55ceb828dbd73
```
The account the invocation is sent from. The specified account must exist in the world state, which, unless specified by [`--genesis`](#genesis), is the set of [accounts used for testing](../../private-networks/reference/accounts-for-testing.md).
### `receiver`
```bash
--receiver=
```
```bash
--receiver=0x588108d3eab34e94484d7cda5a1d31804ca96fe7
```
The account the invocation is sent to. The specified account does not need to exist.
### `input`
```bash
--input=
```
```bash
--input=9064129300000000000000000000000000000000000000000000000000000000
```
The data passed into the call. Corresponds to the `data` field of the transaction and is returned by the `CALLDATA` and related opcodes.
### `value`
```bash
--value=
```
```bash
--value=1000000000000000000
```
The value, in wei, attached to this transaction. For operations that query the value or transfer it to other accounts this is the amount that is available. The amount is not reduced to cover intrinsic cost and gas fees.
### `json`, `trace`
```bash
--json
```
Provides an operation-by-operation trace of the command in JSON.
`--trace` is an alias for `--json`.
### `json-alloc`
```bash
--json-alloc
```
Outputs a JSON summary of the post-execution world state and allocations.
### `[no]memory`, `trace.[no]memory`
```bash
--nomemory, --memory
```
Setting `--nomemory` disables tracing the memory output for each operation. Setting `--memory` enables it. Memory traces are disabled by default.
For memory heavy scripts, disabling memory traces may reduce the volume of JSON output.
`--trace.[no]memory` is an alias for `--[no]memory`.
### `trace.[no]stack`
```bash
--trace.nostack, --trace.stack
```
Setting `--trace.nostack` disables tracing the operand stack for each operation. Setting `--trace.stack` enables it. Stack traces are enabled by default.
### `trace.[no]returndata`
```bash
--trace.noreturndata, --trace.returndata
```
Setting `--trace.noreturndata` disables tracing the return data for each operation. Setting `--trace.returndata` enables it. Return data traces are enabled by default.
### `[no]time`
```bash
--notime, --time
```
Setting `--notime` disables including time data in the summary output. Setting `--time` enables it.
This is useful for testing and differential evaluations.
### `genesis`
```bash
--genesis=
```
```bash
--genesis=/opt/besu/genesis.json
```
The [Besu genesis file](genesis-items.md) to use when evaluating the EVM. Most useful are the `alloc` items that set up accounts and their stored memory states.
`--prestate` is a deprecated alias for `--genesis`.
### `chain`
```bash
--chain=
```
```bash
--chain=sepolia
```
The well-known network genesis file to use when evaluating the EVM. These values are an alternative to the [`--genesis`](#genesis) option for well-known networks.
### `repeat`
```bash
--repeat=
```
```bash
--repeat=1000
```
Number of times to repeat the contract before gathering timing information. This is useful when benchmarking EVM operations. The default is `0`.
### `revert-reason-enabled`
```bash
--revert-reason-enabled
```
Enables tracing the reason included in `REVERT` operations. The revert reason is enabled by default.
### `fork`
```bash
--fork=
```
```bash
--fork=FutureEips
```
Specific fork to evaluate, overriding network settings.
### `key-value-storage`
```bash
--key-value-storage=
```
```bash
--key-value-storage=rocksdb
```
Kind of key value storage to use.
It might be useful to execute isolated EVM calls in the context of an actual world state. The default is `memory`, which executes the call only in the context of the world provided by [`--genesis`](#genesis) or [`--chain`](#chain) at block zero.
When set to `rocksdb` and combined with [`--data-path`](#data-path), [`--block-number`](#block-number), and [`--genesis`](#genesis), a Besu node that isn't currently running can be used to provide the appropriate world state for a transaction. This is useful when evaluating consensus failures.
### `data-path`
```bash
--data-path=
```
```bash
--data-path=/opt/besu/data
```
When [`--key-value-storage`](#key-value-storage) is set to `rocksdb`, specifies the location of the database on disk.
### `block-number`
```bash
--block-number=
```
```bash
--block-number=10000000
```
The block number to evaluate the code against. Used to ensure that the EVM is evaluating the code against the correct fork, or to specify the world state when [`--key-value-storage`](#key-value-storage) is set to `rocksdb`.
### `version`
```bash
--version
```
Displays the version information.
`-v` is an alias for `--version`.
## Subcommands
:::caution
The following subcommands are used for testing code bases and not meant for typical user interactions.
:::
### `code-validate`
```bash
evmtool code-validate --file=
```
```bash
evmtool code-validate --file=eof.txt
```
Allows [Ethereum object formatted (EOF)](https://eips.ethereum.org/EIPS/eip-3540) code to be validated.
You can specify a file containing one or more EOF containers or EVM bytecode using the `--file` option.
Each line in the file is considered a separate program.
#### Use command arguments
If you use command arguments, each argument is considered a separate program.
If a code segment includes spaces, it must be contained in quotes.
```bash
docker run --rm hyperledger/besu-evmtool:develop code-validate "0xef0001 010008 020002-0007-0002 030000 00 00000002-02010002 59-59-b00001-50-b1 03-b1" 0xef0002 0xef00010100040200010001030000000000000000
```
```bash
evmtool code-validate "0xef0001 010008 020002-0007-0002 030000 00 00000002-02010002 59-59-b00001-50-b1 03-b1" 0xef0002 0xef00010100040200010001030000000000000000
```
#### Use standard input
If no reference tests are passed in using the command line, the EVM tool loads and validates code
from standard input.
Each line is considered a separate program.
Comment lines and blanks are ignored.
### `state-test`
Allows the [Ethereum state tests](https://github.com/ethereum/execution-spec-tests/tree/main/tests/static/state_tests)
to be evaluated.
Run `evmtool state-test --help` for the full list of supported options.
Notable options are [`--json`](#json-trace) and [`--nomemory`](#nomemory-tracenomemory).
Set `--json` for EVM Lab Fuzzing.
Whether or not `--json` is set, a summary JSON object is printed to standard output for each state
test executed.
#### Use command arguments
If you use command arguments, you can list one or more state tests.
All the state tests are evaluated in the order they are specified.
```bash
docker run --rm -v ${PWD}:/opt/referencetests hyperledger/besu-evmtool:develop --json state-test /opt/referencetests/GeneralStateTests/stExample/add11.json
```
```bash
evmtool --json state-test stExample/add11.json
```
#### Use standard input
If no reference tests are passed in using the command line, the EVM tool loads one complete JSON
object from standard input and executes that state test.
```bash
docker run --rm -i hyperledger/besu-evmtool:develop --json state-test < stExample/add11.json
```
```bash
evmtool --json state-test < stExample/add11.json
```
### `transition`, `t8n`, `t8n-server`
Allows the Ethereum state transition and blockchain tests to be evaluated.
See the [transition tool reference](https://ethereum-tests.readthedocs.io/en/develop/t8ntool-ref.html)
and [Execution Spec Tests](https://ethereum.github.io/execution-spec-tests/v1.0.6/) for more
information about this subcommand.
---
## Genesis file items
The [Besu genesis file](../concepts/genesis-file.md) contains [network configuration items](#configuration-items) and [genesis block parameters](#genesis-block-parameters).
:::note
Genesis item names are case-insensitive, except account addresses in `alloc`.
The examples on this page use the casing used in Besu's built-in genesis files.
:::
## Configuration items
Network configuration items are specified in the genesis file in the `config` object.
| Item | Description |
|----------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Milestone blocks | [Protocol milestone activation points](#milestone-configuration-items) for the network. |
| `chainId` | [Chain ID](../concepts/network-and-chain-id.md) for the network. |
| `ibft2` | Specifies that the network uses [IBFT 2.0](/private-networks/how-to/configure/consensus/ibft) and contains [IBFT 2.0 configuration items](/private-networks/how-to/configure/consensus/ibft#genesis-file). |
| `qbft` | Specifies that the network uses [QBFT](/private-networks/how-to/configure/consensus/qbft) and contains [QBFT configuration items](/private-networks/how-to/configure/consensus/qbft#genesis-file). |
| `transitions` | Specifies the block at which to [change IBFT 2.0 or QBFT validators](../../private-networks/how-to/configure/consensus/add-validators-without-voting.md). |
| `contractSizeLimit` | Maximum contract size in bytes. Specify in [free gas networks](/private-networks/how-to/configure/free-gas). The default is `24576` and the maximum size is `2147483647`. |
| `evmStackSize` | Maximum stack size. Specify to increase the maximum stack size in private networks with complex smart contracts. The default is `1024`. |
| `ecCurve` | Specifies [the elliptic curve to use](/private-networks/how-to/configure/curves). The default is `secp256k1`. |
| `discovery` | Specifies [discovery configuration items](#discovery-configuration-items). The `discovery` object can be left empty. |
| `zeroBaseFee` | Specifies a base fee of `0` for [free gas networks](/private-networks/how-to/configure/free-gas#4-enable-zero-base-fee-if-using-london-fork-or-later). |
| `fixedBaseFee` | Specifies a constant base fee for blocks, overriding the dynamic base fee calculation of [Ethereum Improvement Proposal 1559 (EIP-1559)](../concepts/transactions/types.md#eip1559-transactions). |
| `depositContractAddress` | Address for the Ethereum staking contract. |
| `withdrawalRequestContractAddress` | Address for the withdrawal request contract. |
| `consolidationRequestContractAddress` | Address for the consolidation request contract. |
| `blobSchedule` | Specifies [blob schedule configuration items](#blob-schedule-configuration-items). |
## Genesis block parameters
Genesis block parameters are specified as top-level fields in the genesis file, outside of `config`.
| Item | Description |
|-------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `alloc` | Defines [accounts with balances](/private-networks/reference/accounts-for-testing) or [contracts](/private-networks/how-to/configure/contracts). |
| `baseFeePerGas` | Genesis block base fee per gas, in Wei. Specify as a decimal or hexadecimal string. If omitted and `londonBlock` is `0`, Besu uses `1000000000`. |
| `blobGasUsed` | Blob gas used in the genesis block. Besu applies this value when Cancun is active at genesis. The default is `0x0`. |
| `coinbase` | Beneficiary address in the genesis block. If omitted, Besu uses the zero address. |
| `difficulty` | Difficulty value in the genesis block. The required value depends on the consensus protocol. |
| `excessBlobGas` | Excess blob gas in the genesis block. Besu applies this value when Cancun is active at genesis. The default is `0x0`. |
| `extraData` | Extra data in the genesis block. For IBFT 2.0 and QBFT, this contains the validator list and consensus metadata. |
| `gasLimit` | Block gas limit. Total gas limit for all transactions in a block. |
| `mixHash` | Mix hash value in the genesis block. The required value depends on the consensus protocol. |
| `nonce` | Used in block computation. Can be any value in the genesis block. The default is `0x0`. |
| `parentBeaconBlockRoot` | Parent beacon block root in the genesis block. Besu applies this value when Cancun is active at genesis. The default is the zero hash. |
| `parentHash` | Parent hash in the genesis block. |
| `slotNumber` | Slot number in the genesis block. Besu applies this value when Amsterdam is active at genesis. The default is `0x0`. |
| `timestamp` | Creation date and time of the genesis block. Must be before the next block, so we recommend specifying `0x0`. |
:::caution
If a `Supplied genesis block does not match stored chain data` error occurs, use the genesis file matching the genesis block of the data directory, or use the [`--data-path`](../reference/options.md#data-path) option to specify a different data directory.
:::
## Milestone configuration items
Milestone items activate protocol changes for the network.
Use `terminalTotalDifficulty` for the Paris transition (The Merge).
Use block-number milestone items for pre-merge forks and timestamp milestone
items for post-merge forks (Shanghai and later).
See the Ethereum execution specs
[protocol history](https://github.com/ethereum/execution-specs/blob/master/docs/specs/protocol_history.md#mainnet-hardforks)
for Mainnet activation blocks and timestamps.
```json title="Ethereum Mainnet milestone items"
{
"config": {
"homesteadBlock": 1150000,
"daoForkBlock": 1920000,
"eip150Block": 2463000,
"eip158Block": 2675000,
"byzantiumBlock": 4370000,
"constantinopleBlock": 7280000,
"constantinopleFixBlock": 7280000,
"istanbulBlock": 9069000,
"muirGlacierBlock": 9200000,
"berlinBlock": 12244000,
"londonBlock": 12965000,
"arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000,
"terminalTotalDifficulty": 58750000000000000000000,
"shanghaiTime": 1681338455,
"cancunTime": 1710338135,
"pragueTime": 1746612311,
"osakaTime": 1764798551,
"bpo1Time": 1765290071,
"bpo2Time": 1767747671
}
}
```
:::caution
Ensure you include a milestone far enough in advance in the genesis file. Not doing so can lead to unexpected and inconsistent behavior without specific errors.
:::
In private networks, the milestone block defines the protocol version for the network.
```json title="Private network milestone block"
{
"config": {
...
"berlinBlock": 0,
...
},
}
```
:::note
In private networks, we recommend specifying the latest milestone block. It's implied this includes the preceding milestones. This ensures you use the most up-to-date protocol and have access to the most recent opcodes.
:::
## Blob schedule configuration items
Use the `blobSchedule` object to configure blob gas parameters for Cancun,
Prague, and Blob Parameter Only (BPO) forks.
| Item | Description |
|-------------------------|:----------------------------------------------------------------------|
| `target` | Target number of blobs per block for the fork. |
| `max` | Maximum number of blobs per block for the fork. |
| `baseFeeUpdateFraction` | Denominator used to update the blob base fee for the fork. |
```json title="Blob schedule example"
{
"config": {
"blobSchedule": {
"cancun": {
"target": 3,
"max": 6,
"baseFeeUpdateFraction": 3338477
},
"prague": {
"target": 6,
"max": 9,
"baseFeeUpdateFraction": 5007716
}
}
}
}
```
## Discovery configuration items
Use the `discovery` configuration items to specify the [`bootnodes`](options.md#bootnodes) and [`discovery-dns-url`](options.md#discovery-dns-url) in the genesis file, in place of using CLI options or listing them in the configuration file.
The genesis file can take discovery v4 bootnodes (specified as [enode URLs](../concepts/node-keys.md#enode-url) using the `bootnodes` option) and discovery v5 bootnodes (specified as [ENR URLs](../concepts/node-keys.md#enr-url) using the `v5Bootnodes` option).
:::tip Early access feature
To use discovery v5 bootnodes, set the early access option `--Xv5-discovery-enabled` to `true`.
:::
If any option is specified using the command line or [configuration file](../how-to/configure-besu/index.md), it takes precedence over the genesis file.
```json
{
"config": {
"discovery": {
"bootnodes": [
"enode://c35c3...d615f@1.2.3.4:30303",
"enode://f42c13...fc456@1.2.3.5:30303"
],
"v5Bootnodes": [
"enr:-Mq4QL...DdWRwgiMo",
"enr:-Ku4QLV...IN1ZHCCIyk"
],
"dns": "enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@nodes.example.org"
}
}
}
```
---
## Configuration options
This reference describes the syntax of the Besu configuration options.
:::warning Important
This reference contains options that apply to both public and private networks. For private-network-specific options, see the [private network options reference](../../private-networks/reference/options.md).
:::
You can specify options:
- On the command line.
Options are part of the command line interface (CLI); run `besu --help` to display all options and [subcommands](subcommands.md).
- As an environment variable.
- In a [configuration file](../how-to/configure-besu/index.md).
If you specify an option in more than one place, the order of priority is command line, environment variable, configuration file.
If using Bash or Z shell, you can view option suggestions by entering `--` and pressing the Tab key twice.
```bash
besu --Tab+Tab
```
:::warning
Characters such as smart quotes and long (em) hyphens don't work in Besu command line options. Ensure quotes aren't automatically converted to smart quotes, or double hyphens combined into em hyphens.
:::
---
## `api-gas-price-blocks`
```bash
--api-gas-price-blocks=50
```
```bash
BESU_API_GAS_PRICE_BLOCKS=50
```
```bash
api-gas-price-blocks=50
```
Number of blocks back from the head block to examine for
[`eth_gasPrice`](api/eth/fee.md#eth_gasprice) and
[`eth_maxPriorityFeePerGas`](api/eth/fee.md#eth_maxpriorityfeepergas).
The default is `100`.
Set to `0` to return the lower-bound value (next block's base fee or configured minimum
gas price) without sampling any historical blocks.
:::note
In Besu 26.6.1 and earlier, setting `--api-gas-price-blocks=0` was incorrectly treated as
`1`, causing Besu to sample one block.
If you relied on that behavior, set `--api-gas-price-blocks=1` instead.
:::
---
## `api-gas-price-max`
```bash
--api-gas-price-max=20000
```
```bash
BESU_API_GAS_PRICE_MAX=20000
```
```bash
api-gas-price-max=20000
```
Maximum gas price to return for [`eth_gasPrice`](api/eth/fee.md#eth_gasprice), regardless of the percentile value measured. The default is `500000000000` (500 GWei).
---
## `api-gas-price-percentile`
```bash
--api-gas-price-percentile=75
```
```bash
BESU_API_GAS_PRICE_PERCENTILE=75
```
```bash
api-gas-price-percentile=75
```
Percentile value to measure for [`eth_gasPrice`](api/eth/fee.md#eth_gasprice). The default is `50.0`.
For [`eth_gasPrice`](api/eth/fee.md#eth_gasprice), to return the:
- Highest gas price in [`--api-gas-price-blocks`](#api-gas-price-blocks), set to `100`.
- Lowest gas price in [`--api-gas-price-blocks`](#api-gas-price-blocks), set to `0`.
---
## `auto-log-bloom-caching-enabled`
```bash
--auto-log-bloom-caching-enabled=false
```
```bash
BESU_AUTO_LOG_BLOOM_CACHING_ENABLED=false
```
```bash
auto-log-bloom-caching-enabled=false
```
Enables or disables automatic log bloom caching. APIs such as [`eth_getLogs`](api/eth/filter.md#eth_getlogs) and [`eth_getFilterLogs`](api/eth/filter.md#eth_getfilterlogs) use the cache for improved performance.
The default is `true`.
If automatic log bloom caching is enabled and a log bloom query reaches the end of the cache, Besu
performs an uncached query for logs not yet written to the cache.
Automatic log bloom caching has a small impact on performance. If you are not querying logs blooms for a large number of blocks, you might want to disable automatic log bloom caching.
---
## `banned-node-ids`
```bash
--banned-node-ids=0xc35c3...d615f,0xf42c13...fc456
```
```bash
BESU_BANNED_NODE_IDS=0xc35c3...d615f,0xf42c13...fc456
```
```bash
banned-node-ids=["0xc35c3...d615f","0xf42c13...fc456"]
```
A list of node IDs with which this node will not peer. The node ID is the public key of the node. You can specify the banned node IDs with or without the `0x` prefix.
:::tip
The singular `--banned-node-id` and plural `--banned-node-ids` are available and are two names for the same option.
:::
---
## `block-txs-selection-max-time`
```bash
--block-txs-selection-max-time=1700
```
```bash
BESU_BLOCK_TXS_SELECTION_MAX_TIME=1700
```
```bash
block-txs-selection-max-time=1700
```
The maximum time, in milliseconds, that can be spent selecting transactions to be included in a block.
This value must be less than or equal to the default, `5000`.
:::note
This option only applies to proof-of-stake networks.
For proof-of-authority networks, see
[`--poa-block-txs-selection-max-time`](../../private-networks/reference/options.md#poa-block-txs-selection-max-time).
:::
---
## `bonsai-historical-block-limit`
```bash
--bonsai-historical-block-limit=256
```
```bash
BESU_BONSAI_HISTORICAL_BLOCK_LIMIT=256
```
```bash
bonsai-historical-block-limit=256
```
When using [Bonsai Tries](../concepts/data-storage-formats.md#bonsai-tries), the
[maximum number of previous blocks](../concepts/data-storage-formats.md#accessing-data) for which
Bonsai can reconstruct a historical state.
The default is `512`.
:::note
If you plan on querying historical blocks or state using the [JSON-RPC API](api/index.md), you might need to adjust the default value or your configured value to avoid errors.
:::
---
## `bonsai-limit-trie-logs-enabled`
```bash
--bonsai-limit-trie-logs-enabled=false
```
```bash
BESU_BONSAI_LIMIT_TRIE_LOGS_ENABLED=false
```
```bash
bonsai-limit-trie-logs-enabled=false
```
Enables or disables limiting the number of
[Bonsai Trie](../concepts/data-storage-formats.md#bonsai-tries) logs that are retained.
When enabled, this limit is set to the value of
[`--bonsai-historical-block-limit`](#bonsai-historical-block-limit).
The default is `true`, unless [`--sync-mode=FULL`](#sync-mode) is set, in which case this option is
disallowed and must be set to `false`.
---
## `bonsai-parallel-tx-processing-enabled`
```bash
--bonsai-parallel-tx-processing-enabled=false
```
```bash
BESU_BONSAI_PARALLEL_TX_PROCESSING_ENABLED=false
```
```bash
bonsai-parallel-tx-processing-enabled=false
```
Enables [parallelization of transactions](../concepts/parallel-transaction-execution) to optimize
processing speed.
This applies to Besu instances configured to the [Bonsai Trie](../concepts/data-storage-formats.md#bonsai-tries)
data storage format, otherwise this option is ignored.
The default is `true`.
---
## `bonsai-trie-logs-pruning-window-size`
```bash
--bonsai-trie-logs-pruning-window-size=100000
```
```bash
BESU_BONSAI_TRIE_LOGS_PRUNING_WINDOW_SIZE=100000
```
```bash
bonsai-trie-logs-pruning-window-size=100000
```
When using [`--bonsai-limit-trie-logs-enabled`](#bonsai-limit-trie-logs-enabled), the number of trie
logs to prune during one pruning operation.
A larger value might impact node performance.
The default is `30000`.
---
## `bootnodes`
```bash
--bootnodes=enode://c35c3...d615f@1.2.3.4:30303,enode://f42c13...fc456@1.2.3.5:30303
```
```bash
BESU_BOOTNODES=enode://c35c3...d615f@1.2.3.4:30303,enode://f42c13...fc456@1.2.3.5:30303
```
```bash
bootnodes=["enode://c35c3...d615f@1.2.3.4:30303","enode://f42c13...fc456@1.2.3.5:30303"]
```
A list of comma-separated sources for [P2P discovery bootstrap](../../private-networks/how-to/configure/bootnodes.md),
where each source can be one of the following:
- A direct [enode URL](../concepts/node-keys.md#enode-url) or [ENR URL](../concepts/node-keys.md#enr-url)
- A local file path: `/path/to/bootnodes.txt`
- A file URI: `file:///path/to/bootnodes.txt`
- An HTTP(S) URL: `https://example.com/bootnodes.txt`
Each file or URL must contain one enode or ENR URL per line. Blank lines and lines starting with `#` are ignored.
The `--bootnodes` list can mix sources, but must specify all enode URLs (for discovery v4) or all ENR URLs (for discovery v5).
:::tip Early access feature
To use discovery v5 bootnodes, set the early access option `--Xv5-discovery-enabled` to `true`.
:::
When connecting to Mainnet or public testnets, the default is a predefined list of bootnodes.
In private networks defined using [`--genesis-file`](#genesis-file) or when using
[`--network=dev`](#network), the default is an empty list of bootnodes.
---
## `cache-last-blocks`
```bash
--cache-last-blocks=2048
```
```bash
BESU_CACHE_LAST_BLOCKS=2048
```
```bash
cache-last-blocks=2048
```
The number of recent blocks to cache.
Using this option can improve the performance of several RPC calls including: [`eth_getBlockByNumber`](api/eth/block.md#eth_getblockbynumber), [`eth_getBlockByHash`](api/eth/block.md#eth_getblockbyhash), [`eth_getTransactionReceipt`](api/eth/transaction.md#eth_gettransactionreceipt), and especially [`eth_feeHistory`](api/eth/fee.md#eth_feehistory).
The default is `0`.
---
## `cache-last-block-headers`
```bash
--cache-last-block-headers=50000
```
```bash
BESU_CACHE_LAST_BLOCK_HEADERS=50000
```
```bash
cache-last-block-headers=50000
```
The number of last block headers to cache from the blocks persisted to the blockchain.
When used with [`--cache-last-block-headers-preload-enabled`](#cache-last-block-headers-preload-enabled), this value defines how many block headers are preloaded into the cache at startup.
The default is `0`.
---
## `cache-last-block-headers-preload-enabled`
```bash
--cache-last-block-headers-preload-enabled=true
```
```bash
BESU_CACHE_LAST_BLOCK_HEADERS_PRELOAD_ENABLED=true
```
```bash
cache-last-block-headers-preload-enabled=true
```
Enables preloading the block headers cache at startup.
Only has effect when [`--cache-last-block-headers`](#cache-last-block-headers) is set to a value greater than `0`; the number of block headers preloaded is defined by that option.
The default is `false`.
---
## `color-enabled`
```bash
--color-enabled=false
```
```bash
BESU_COLOR_ENABLED=false
```
```bash
color-enabled=false
```
Enables or disables color output to console.
The default is `true`.
---
## `config-file`
```bash
--config-file=/home/me/me_node/config.toml
```
```bash
BESU_CONFIG_FILE=/home/me/me_node/config.toml
```
The path to the [TOML configuration file](../how-to/configure-besu/index.md). The default is `none`.
---
## `data-path`
```bash
--data-path=/home/me/me_node
```
```bash
BESU_DATA_PATH=/home/me/me_node
```
```bash
data-path="/home/me/me_node"
```
The path to the Besu data directory. The default is the directory you installed Besu in, or `/opt/besu/database` if using the [Besu Docker image](../get-started/install/run-docker-image.md).
---
## `data-storage-format`
```bash
--data-storage-format=FOREST
```
```bash
BESU_DATA_STORAGE_FORMAT=FOREST
```
```bash
data-storage-format="BONSAI"
```
The [data storage format](../concepts/data-storage-formats.md) to use. Set to `BONSAI` for Bonsai Tries or `FOREST` for Forest of Tries. The default is `BONSAI`.
---
## `discovery-dns-url`
```bash
--discovery-dns-url=
```
```bash
BESU_DISCOVERY_DNS_URL=enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@nodes.example.org
```
```bash
discovery-dns-url="enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@nodes.example.org"
```
The `enrtree` URL of the DNS node list for [node discovery via DNS](https://eips.ethereum.org/EIPS/eip-1459).
By default, Besu uses the value of the [`discovery.dns`](genesis-items.md#discovery-configuration-items) item in the network's genesis configuration file.
To disable DNS-based discovery, set `discovery-dns-url` to an empty string (`""`) or remove the `discovery.dns` entry in the genesis file.
---
## `discovery-enabled`
```bash
--discovery-enabled=false
```
```bash
BESU_DISCOVERY_ENABLED=false
```
```bash
discovery-enabled=false
```
Enables or disables P2P discovery.
The default is `true`.
:::note
You can override the default DNS server if it's unreliable or doesn't serve TCP DNS requests, using the [early access option](#xhelp) `--Xp2p-dns-discovery-server=`.
:::
---
## `engine-host-allowlist`
```bash
--engine-host-allowlist=localhost,127.0.0.1
```
```bash
BESU_ENGINE_HOST_ALLOWLIST=localhost,127.0.0.1
```
```bash
engine-host-allowlist=["localhost","127.0.0.1"]
```
A comma-separated list of hostnames to allow for Engine API access (applies to both HTTP and WebSocket).
:::tip
To allow all hostnames, use `"*"`. We don't recommend allowing all hostnames in production environments.
:::
---
## `engine-jwt-disabled`
```bash
--engine-jwt-disabled=true
```
```bash
BESU_ENGINE_JWT_DISABLED=true
```
```bash
engine-jwt-disabled=true
```
Disables or enables [authentication](../how-to/use-engine-api.md#authentication) for Engine APIs.
The default is `false` (authentication is enabled by default).
---
## `engine-jwt-secret`
```bash
--engine-jwt-secret=jwt.hex
```
```bash
BESU_ENGINE_JWT_SECRET="jwt.hex"
```
```bash
engine-jwt-secret="jwt.hex"
```
Shared secret used to authenticate [consensus clients](../concepts/node-clients.md#consensus-clients) when using the Engine JSON-RPC API (both HTTP and WebSocket). Contents of file must be at least 32 hex-encoded bytes and not begin with `0x`. May be a relative or absolute path. See an [example of how to generate this](../get-started/connect/mainnet.md#1-generate-the-shared-secret).
---
## `engine-rpc-enabled`
```bash
--engine-rpc-enabled
```
```bash
BESU_ENGINE_RPC_ENABLED=true
```
```bash
engine-rpc-enabled=true
```
Enables or disables the [Engine API](engine-api.md).
The default is `false`.
On post-Merge networks (including Mainnet and public testnets), Besu
enables the Engine API automatically whether or not you set this option.
---
## `engine-rpc-port`
```bash
--engine-rpc-port=8551
```
```bash
BESU_ENGINE_RPC_PORT=8551
```
```bash
engine-rpc-port="8551"
```
The listening port for the Engine API calls (`ENGINE`, `ETH`) for JSON-RPC over HTTP and WebSocket. The default is `8551`.
---
## `era1-data-uri`
```bash
--era1-data-uri=https://mainnet.era1.nimbus.team/
```
```bash
BESU_ERA1_DATA_URI=https://mainnet.era1.nimbus.team/
```
```bash
era1-data-uri="https://mainnet.era1.nimbus.team/"
```
The URI or local path to attempt to [import ERA1 files](../how-to/era1-file-full-sync.md) from. For local files, a simple path may be used
(for example, `/home/user/era1`). The default is `https://mainnet.era1.nimbus.team/`.
---
## `era1-import-prepipeline-concurrency`
```bash
--era1-import-prepipeline-concurrency=2
```
```bash
BESU_ERA1_IMPORT_PREPIPELINE_CONCURRENCY=2
```
```bash
era1-import-prepipeline-concurrency=2
```
Number of parallel processes used to [import ERA1 archive files](../how-to/era1-file-full-sync.md) before full synchronization begins.
Increasing this may improve performance when loading files from remote sources or on systems with
high I/O capacity. The default is `1`.
In most cases, we recommend using the default unless slow file downloads are a limiting factor.
---
## `era1-import-prepipeline-enabled`
```bash
--era1-import-prepipeline-enabled=true
```
```bash
BESU_ERA1_IMPORT_PREPIPELINE_ENABLED=true
```
```bash
era1-import-prepipeline-enabled=true
```
Enables [importing pre-merge blocks from ERA1 archive files](../how-to/era1-file-full-sync.md) before full sync begins. Files are loaded from the location specified by[`--era1-data-uri`](#era1-data-uri) (supports local paths and HTTP URLs).
This option only applies when [`--sync-mode=FULL`](#sync-mode); it has no effect in other sync modes.
The default is `false`.
Use this to accelerate syncing from genesis or to restore full historical data without relying on peer-to-peer downloads.
---
## `estimate-gas-tolerance-ratio`
```bash
--estimate-gas-tolerance-ratio=0.015
```
```bash
BESU_ESTIMATE_GAS_TOLERANCE_RATIO=0.015
```
```bash
estimate-gas-tolerance-ratio=0.015
```
Defines the tolerance used when estimating gas for the [`eth_estimateGas`](api/eth/execute.md#eth_estimategas) JSON-RPC method.
Lower values increase accuracy but take longer to compute.
Higher values speed up estimation but might provide less precise results.
The default is `0.015`. Set to `0.0` to disable tolerance and prioritize maximum accuracy.
---
## `ethstats`
```bash
--ethstats=Dev-Node-1:secret@127.0.0.1:3001
```
```bash
BESU_ETHSTATS=Dev-Node-1:secret@127.0.0.1:3001
```
```bash
ethstats="Dev-Node-1:secret@127.0.0.1:3001"
```
Reporting URL of an [Ethstats](../../private-networks/how-to/deploy/ethstats.md) server.
If specified without a port, the default port is 443 for SSL connections and 80 for non-SSL connections.
You can optionally specify `ws://` or `wss://` in the Ethstats URL.
If you specify this scheme, the connection doesn't need to switch from SSL to non-SSL on each retry logic.
---
## `ethstats-cacert-file`
```bash
--ethstats-cacert-file=./root.cert
```
```bash
BESU_ETHSTATS_CACERT_FILE=./root.cert
```
```bash
ethstats-cacert-file="./root.cert"
```
Path to the root certificate authority (CA) certificate file of the Ethstats server specified by [`--ethstats`](#ethstats). This option is useful in non-production environments.
---
## `ethstats-contact`
```bash
--ethstats-contact=contact@mail.com
```
```bash
BESU_ETHSTATS_CONTACT=contact@mail.com
```
```bash
ethstats-contact="contact@mail.com"
```
Contact email address to send to the Ethstats server specified by [`--ethstats`](#ethstats).
---
## `ethstats-report-interval`
```bash
--ethstats-report-interval=10
```
```bash
BESU_ETHSTATS_REPORT_INTERVAL=10
```
```bash
ethstats-report-interval=10
```
Interval (in seconds) at which Besu sends status updates to the EthStats server.
The default is `5`.
---
## `genesis-file`
```bash
--genesis-file=/home/me/me_node/customGenesisFile.json
```
```bash
BESU_GENESIS_FILE=/home/me/me_node/customGenesisFile.json
```
```bash
genesis-file="/home/me/me_node/customGenesisFile.json"
```
The path to the [genesis file](../concepts/genesis-file.md).
:::caution
You can't use the [`--genesis-file`](#genesis-file) and [`--network`](#network) options at the same time.
:::
---
## `genesis-state-hash-cache-enabled`
```bash
--genesis-state-hash-cache-enabled=true
```
```bash
BESU_GENESIS_STATE_HASH_CACHE_ENABLED=true
```
```bash
genesis-state-hash-cache-enabled=true
```
Enables or disables fast startup from an existing genesis state hash.
The default is `false`.
:::warning
Enabling this option avoids validating the genesis state hash, trading off security for faster node startup times. We only recommend using this option if you are certain that you have not modified your genesis file or database and understand the security implications.
:::
---
## `graphql-http-cors-origins`
```bash
--graphql-http-cors-origins="http://medomain.com","https://meotherdomain.com"
```
```bash
BESU_GRAPHQL_HTTP_CORS_ORIGINS="http://medomain.com","https://meotherdomain.com"
```
```bash
graphql-http-cors-origins=["http://medomain.com","https://meotherdomain.com"]
```
A list of comma-separated origin domain URLs for CORS validation. The default is none.
---
## `graphql-http-enabled`
```bash
--graphql-http-enabled
```
```bash
BESU_GRAPHQL_HTTP_ENABLED=true
```
```bash
graphql-http-enabled=true
```
Enables or disables the GraphQL HTTP service.
The default is `false`.
The default GraphQL HTTP service endpoint is `http://127.0.0.1:8547/graphql` if set to `true`.
---
## `graphql-http-host`
```bash
# to listen on all interfaces
--graphql-http-host=0.0.0.0
```
```bash
# to listen on all interfaces
BESU_GRAPHQL_HTTP_HOST=0.0.0.0
```
```bash
graphql-http-host="0.0.0.0"
```
The host on which GraphQL HTTP listens. The default is `127.0.0.1`.
To allow remote connections, set to `0.0.0.0`.
---
## `graphql-http-port`
```bash
# to listen on port 6175
--graphql-http-port=6175
```
```bash
# to listen on port 6175
BESU_GRAPHQL_HTTP_PORT=6175
```
```bash
graphql-http-port="6175"
```
The port (TCP) on which GraphQL HTTP listens. The default is `8547`. Ports must be [exposed appropriately](../how-to/connect/configure-ports.md).
---
## `graphql-mtls-enabled`
```bash
--graphql-mtls-enabled=true
```
```bash
BESU_GRAPHQL_MTLS_ENABLED=true
```
```bash
graphql-mtls-enabled=true
```
Enables or disables mTLS for the GraphQL HTTP service.
The default is `false`.
:::note
[`--graphql-http-enabled`](#graphql-http-enabled) must be enabled.
:::
---
## `graphql-tls-enabled`
```bash
--graphql-tls-enabled=true
```
```bash
BESU_GRAPHQL_TLS_ENABLED=true
```
```bash
graphql-tls-enabled=true
```
Enables or disables TLS for the GraphQL HTTP service.
The default is `false`.
:::note
[`--graphql-http-enabled`](#graphql-http-enabled) must be enabled.
:::
---
## `graphql-tls-keystore-file`
```bash
--graphql-tls-keystore-file=/home/me/me_node/keystore.pfx
```
```bash
BESU_GRAPHQL_TLS_KEYSTORE_FILE=/home/me/me_node/keystore.pfx
```
```bash
graphql-tls-keystore-file="/home/me/me_node/keystore.pfx"
```
Path to the keystore file when enabling TLS for the GraphQL HTTP service.
The keystore file contains the private key and certificate presented to the client during authentication.
Specify the keystore password file using [`--graphql-tls-keystore-password-file`](#graphql-tls-keystore-password-file).
---
## `graphql-tls-keystore-password-file`
```bash
--graphql-tls-keystore-password-file=/home/me/me_node/password
```
```bash
BESU_GRAPHQL_TLS_KEYSTORE_PASSWORD_FILE=/home/me/me_node/password
```
```bash
graphql-tls-keystore-password-file="/home/me/me_node/password"
```
Path to the file containing the password for the keystore specified in [`--graphql-tls-keystore-file`](#graphql-tls-keystore-file),
when enabling TLS for the GraphQL HTTP service.
---
## `graphql-tls-truststore-file`
```bash
--graphql-tls-truststore-file=/home/me/me_node/truststore.pfx
```
```bash
BESU_GRAPHQL_TLS_TRUSTSTORE_FILE=/home/me/me_node/truststore.pfx
```
```bash
graphql-tls-truststore-file="/home/me/me_node/truststore.pfx"
```
Path to the truststore file when enabling TLS for the GraphQL HTTP service.
Specify the truststore password file using [`--graphql-tls-truststore-password-file`](#graphql-tls-truststore-password-file).
---
## `graphql-tls-truststore-password-file`
```bash
--graphql-tls-truststore-password-file=/home/me/me_node/password
```
```bash
BESU_GRAPHQL_TLS_TRUSTSTORE_PASSWORD_FILE=/home/me/me_node/password
```
```bash
graphql-tls-truststore-password-file="/home/me/me_node/password"
```
Path to the file containing the password for the truststore specified in [`--graphql-tls-truststore-file`](#graphql-tls-truststore-file),
when enabling TLS for the GraphQL HTTP service.
---
## `help`
```bash
-h, --help
```
Show the help message and exit.
---
## `history-expiry-prune`
```bash
--history-expiry-prune=true
```
```bash
BESU_HISTORY_EXPIRY_PRUNE=true
```
```bash
history-expiry-prune=true
```
Enables or disables [online pruning of historical block data](../how-to/pre-merge-history-expiry.md#online-pruning)
for pre-merge Proof of Work (PoW) blocks, retaining only the headers.
The option also activates garbage collection settings that works for both online and offline pruning
mechanisms, so that the reclaimed storage is compacted quickly, freeing disk space without manual intervention.
The default is `false`.
:::caution Deprecated
`--history-expiry-prune` is deprecated in Besu version 26.1.0 and will be removed in a future release.
:::
---
## `host-allowlist`
```bash
--host-allowlist=medomain.com,meotherdomain.com
```
```bash
BESU_HOST_ALLOWLIST=medomain.com,meotherdomain.com
```
```bash
host-allowlist=["medomain.com", "meotherdomain.com"]
```
A comma-separated list of hostnames to [access the JSON-RPC API](../how-to/use-besu-api/index.md#host-allowlist) and [pull Besu metrics](../how-to/monitor/metrics.md). By default, Besu accepts requests from `localhost` and `127.0.0.1`.
:::info
This isn't a permissioning feature. To restrict access to the API, we recommend using the [Besu authentication mechanism](../how-to/use-besu-api/authenticate.md) with username and password authentication or JWT public key authentication.
:::
:::note
If using [Prometheus](https://prometheus.io/) to pull metrics from a node, you must specify all the other nodes you want to pull metrics from in the list of allowed hostnames.
:::
:::tip
To allow all hostnames, use `"*"`. We don't recommend allowing all hostnames for production environments.
:::
---
## `identity`
```bash
--identity=MyNode
```
```bash
BESU_IDENTITY=MyNode
```
```bash
identity="MyNode"
```
The name for the node. If specified, it's the second section of the client ID provided by some Ethereum network explorers. For example, in the client ID `besu/MyNode/v1.3.4/linux-x86_64/oracle_openjdk-java-11`, the node name is `MyNode`.
If a name is not specified, the name section is not included in the client ID. For example, `besu/v1.3.4/linux-x86_64/oracle_openjdk-java-11`.
---
## `json-pretty-print-enabled`
```bash
--json-pretty-print-enabled=true
```
```bash
BESU_JSON_PRETTY_PRINT_ENABLED=true
```
```bash
json-pretty-print-enabled=true
```
Enables or disables the pretty-print output for HTTP and WebSocket responses.
The default is `false`.
---
## `key-value-storage`
```bash
--key-value-storage=rocksdb
```
```bash
BESU_KEY_VALUE_STORAGE=rocksdb
```
```bash
key-value-storage="rocksdb"
```
The key-value storage to use. Use this option only if using a storage system provided with a plugin. The default is `rocksdb`.
For development use only, the `memory` option provides ephemeral storage for sync testing and debugging.
---
## `kzg-trusted-setup`
```bash
--kzg-trusted-setup=/etc/besu/kzg-trusted-setup.txt
```
```bash
BESU_KZG_TRUSTED_SETUP=/etc/besu/kzg-trusted-setup.txt
```
```bash
kzg-trusted-setup=/etc/besu/kzg-trusted-setup.txt
```
The path to the [C-KZG-4844](https://github.com/ethereum/c-kzg-4844) trusted setup file. Use this option to pass a custom setup file for custom networks or to override the default setup file for named networks.
---
## `logging`
```bash
--logging=DEBUG
```
```bash
BESU_LOGGING=DEBUG
```
```bash
logging="DEBUG"
```
Sets logging verbosity. Log levels are `OFF`, `FATAL`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`, `ALL`. The default is `INFO`.
---
## `max-blobs-per-block`
```bash
--max-blobs-per-block=8
```
```bash
BESU_MAX_BLOBS_PER_BLOCK=8
```
```bash
max-blobs-per-block=8
```
Maximum number of [blobs](../concepts/transactions/types.md#blob-transactions) allowed per block.
The default is determined by the hard fork you're on, defined in the genesis file.
Use this option if you want to apply a limit smaller than the default value.
You can use this option starting from the [Osaka hard fork](https://eips.ethereum.org/EIPS/eip-7607).
---
## `max-blobs-per-transaction`
```bash
--max-blobs-per-transaction=2
```
```bash
BESU_MAX_BLOBS_PER_TRANSACTION=2
```
```bash
max-blobs-per-transaction=2
```
Maximum number of [blobs](../concepts/transactions/types.md#blob-transactions) allowed per transaction.
The default is 6.
You can use this option starting from the [Osaka hard fork](https://eips.ethereum.org/EIPS/eip-7607).
---
## `max-peers`
```bash
--max-peers=42
```
```bash
BESU_MAX_PEERS=42
```
```bash
max-peers=42
```
The maximum number of P2P connections you can establish. The default is 25.
---
## `metrics-category`
```bash
--metrics-category=BLOCKCHAIN,PEERS,PROCESS
```
```bash
BESU_METRICS_CATEGORY=BLOCKCHAIN,PEERS,PROCESS
```
```bash
metrics-category=["BLOCKCHAIN","PEERS","PROCESS"]
```
A comma-separated list of categories for which to track metrics. The defaults are `BLOCKCHAIN`, `ETHEREUM`, `EXECUTORS`, `JVM`, `NETWORK`, `PEERS`, `PERMISSIONING`, `PROCESS`, `PRUNER`, `RPC`, `SYNCHRONIZER`, and `TRANSACTION_POOL`.
Other categories are `KVSTORE_ROCKSDB`, `KVSTORE_PRIVATE_ROCKSDB`, `KVSTORE_ROCKSDB_STATS`, and `KVSTORE_PRIVATE_ROCKSDB_STATS`.
---
## `metrics-enabled`
```bash
--metrics-enabled
```
```bash
BESU_METRICS_ENABLED=true
```
```bash
metrics-enabled=true
```
Enables or disables the [metrics exporter](../how-to/monitor/metrics.md).
The default is `false`.
You can't specify `--metrics-enabled` with [`--metrics-push-enabled`](#metrics-push-enabled). That is, you can enable either Prometheus polling or Prometheus push gateway support, but not both at once.
---
## `metrics-host`
```bash
--metrics-host=127.0.0.1
```
```bash
BESU_METRICS_HOST=127.0.0.1
```
```bash
metrics-host="127.0.0.1"
```
The host on which [Prometheus](https://prometheus.io/) accesses [Besu metrics](../how-to/monitor/metrics.md). The metrics server respects the [`--host-allowlist` option](#host-allowlist).
The default is `127.0.0.1`.
---
## `metrics-port`
```bash
--metrics-port=6174
```
```bash
BESU_METRICS_PORT=6174
```
```bash
metrics-port="6174"
```
The port (TCP) on which [Prometheus](https://prometheus.io/) accesses [Besu metrics](../how-to/monitor/metrics.md). The default is `9545`. Ports must be [exposed appropriately](../how-to/connect/configure-ports.md).
---
## `metrics-protocol`
```bash
--metrics-protocol=OPENTELEMETRY
```
```bash
BESU_METRICS_PROTOCOL=OPENTELEMETRY
```
```bash
metrics-protocol="OPENTELEMETRY"
```
Metrics protocol to use: `PROMETHEUS`, `OPENTELEMETRY`, or `NONE`. The default is `PROMETHEUS`.
---
## `metrics-push-enabled`
```bash
--metrics-push-enabled=true
```
```bash
BESU_METRICS_PUSH_ENABLED=true
```
```bash
metrics-push-enabled=true
```
Enables or disables [push gateway integration].
The default is `false`.
You can't specify `--metrics-push-enabled` with [`--metrics-enabled`](#metrics-enabled). That is, you can enable either Prometheus polling or Prometheus push gateway support, but not both at once.
---
## `metrics-push-host`
```bash
--metrics-push-host=127.0.0.1
```
```bash
BESU_METRICS_PUSH_HOST=127.0.0.1
```
```bash
metrics-push-host="127.0.0.1"
```
The host of the [Prometheus Push Gateway](https://github.com/prometheus/pushgateway). The default is `127.0.0.1`. The metrics server respects the [`--host-allowlist` option](#host-allowlist).
:::note
When pushing metrics, ensure you set `--metrics-push-host` to the machine on which the push gateway is. Generally, this is a different machine to the machine on which Besu is running.
:::
---
## `metrics-push-interval`
```bash
--metrics-push-interval=30
```
```bash
BESU_METRICS_PUSH_INTERVAL=30
```
```bash
metrics-push-interval=30
```
The interval, in seconds, to push metrics when in `push` mode. The default is 15.
---
## `metrics-push-port`
```bash
--metrics-push-port=6174
```
```bash
BESU_METRICS_PUSH_PORT=6174
```
```bash
metrics-push-port="6174"
```
The port (TCP) of the [Prometheus Push Gateway](https://github.com/prometheus/pushgateway). The default is `9001`. Ports must be [exposed appropriately](../how-to/connect/configure-ports.md).
---
## `metrics-push-prometheus-job`
```bash
--metrics-push-prometheus-job="my-custom-job"
```
```bash
BESU_METRICS_PUSH_PROMETHEUS_JOB="my-custom-job"
```
```bash
metrics-push-prometheus-job="my-custom-job"
```
The job name when in `push` mode. The default is `besu-client`.
---
## `min-block-occupancy-ratio`
```bash
--min-block-occupancy-ratio=0.5
```
```bash
BESU_MIN_BLOCK_OCCUPANCY_RATIO=0.5
```
```bash
min-block-occupancy-ratio="0.5"
```
Minimum occupancy ratio for a mined block if the transaction pool is not empty. When filling a block during mining, the occupancy ratio indicates the threshold at which the node stops waiting for smaller transactions to fill the remaining space. The default is 0.8.
:::warning Deprecated
The `--min-block-occupancy-ratio` option is deprecated and will be removed in a
future release.
Besu recognizes this option, but it has no effect.
:::
---
## `min-gas-price`
```bash
--min-gas-price=1337
```
```bash
BESU_MIN_GAS_PRICE=1337
```
```bash
min-gas-price=1337
```
The minimum price (in wei) a transaction offers to include it in a mined block.
The minimum gas price is the lowest value [`eth_gasPrice`](api/eth/fee.md#eth_gasprice) can return.
The default is `1000`.
For a running node, use:
* [`miner_getMinGasPrice`](api/miner.md#miner_getmingasprice) to get the value.
* [`miner_setMinGasPrice`](api/miner.md#miner_setmingasprice) to change the value.
:::tip
In a [free gas network](../../private-networks/how-to/configure/free-gas.md), ensure the minimum
gas price is set to zero for every node.
Any node with a minimum gas price set higher than zero will silently drop transactions with a zero
gas price.
You can query a node's gas configuration using [`eth_gasPrice`](api/eth/fee.md#eth_gasprice).
:::
---
## `min-priority-fee`
```bash
--min-priority-fee=7
```
```bash
BESU_MIN_PRIORITY_FEE=7
```
```bash
min-priority-fee=7
```
The minimum priority fee per gas (in wei) offered by a transaction to be included in a block.
The default is `0`.
For a running node, use:
* [`miner_getMinPriorityFee`](api/miner.md#miner_getminpriorityfee) to get the value.
* [`miner_setMinPriorityFee`](api/miner.md#miner_setminpriorityfee) to change the value.
---
## `miner-extra-data`
```bash
--miner-extra-data=0x444F4E27542050414E4943202120484F444C2C20484F444C2C20484F444C2021
```
```bash
BESU_MINER_EXTRA_DATA=0x444F4E27542050414E4943202120484F444C2C20484F444C2C20484F444C2021
```
```bash
miner-extra-data="0x444F4E27542050414E4943202120484F444C2C20484F444C2C20484F444C2021"
```
A hex string representing the 32 bytes included in the extra data field of a created block.
The default is `0x`.
---
## `nat-method`
```bash
--nat-method=UPNP
```
```bash
nat-method="UPNP"
```
Specify the method for handling [NAT environments](../how-to/connect/specify-nat.md). The options are:
- [`UPNP`](../how-to/connect/specify-nat.md#upnp)
- [`UPNPP2PONLY`](../how-to/connect/specify-nat.md#upnp)
- [`DOCKER`](../how-to/connect/specify-nat.md#docker)
- [`AUTO`](../how-to/connect/specify-nat.md#auto)
- [`NONE`](../how-to/connect/specify-nat.md#none).
The default is `AUTO`. `NONE` disables NAT functionality.
:::tip
UPnP support is often disabled by default in networking firmware. If disabled by default, explicitly enable UPnP support.
:::
:::tip
Use `UPNPP2PONLY` if you wish to enable UPnP for P2P traffic but not JSON-RPC.
:::
:::note
Specifying `UPNP` might introduce delays during node startup, especially on networks without a UPnP gateway device.
You must specify `DOCKER` when using the [Besu Docker image](../get-started/install/run-docker-image.md).
:::
---
## `net-restrict`
```bash
--net-restrict=192.168.1.0/24,10.0.0.0/8,fd00::/64
```
```bash
BESU_NET_RESTRICT=192.168.1.0/24,10.0.0.0/8,fd00::/64
```
```bash
net-restrict=["192.168.1.0/24","10.0.0.0/8","fd00::/64"]
```
A comma-separated list of allowed IP subnets.
Peers whose IP addresses fall within the specified subnets are granted permission to interact with the node.
If not specified, no subnet-based peer permission restrictions are applied.
:::tip
This option accepts both IPv4 and IPv6 addresses.
:::
---
## `network`
```bash
--network=sepolia
```
```bash
BESU_NETWORK=sepolia
```
```bash
network="sepolia"
```
The predefined network configuration. The default is `mainnet`.
Possible values include the following:
| Network | Chain | Type | Default sync mode | Consensus mechanism | Description |
|:-----------|:------|:------------|:---------------------|:--------------------|:-------------------------------------------------------------------------------|
| `mainnet` | ETH | Production | [`SNAP`](#sync-mode) | PoS network | The main [Ethereum network](https://ethereum.org/en/developers/docs/networks/) |
| `hoodi` | ETH | Test | [`SNAP`](#sync-mode) | PoS network | Multi-client Ethereum testnet [Hoodi](https://hoodi.ethpandaops.io/) |
| `sepolia` | ETH | Test | [`SNAP`](#sync-mode) | PoS network | Multi-client Ethereum testnet [Sepolia](https://sepolia.dev) |
| `dev` | ETH | Development | [`FULL`](#sync-mode) | Dev mode | Local development network for testing |
| `ephemery` | ETH | Test | [`SNAP`](#sync-mode) | PoS network | Multi-client Ethereum testnet [Ephemery](https://ephemery.dev)
| `linea_mainnet` | Linea | Production | [`SNAP`](#sync-mode) | Sequencer-based (zkEVM rollup) | The main [Linea network](https://docs.linea.build/get-started/build/network-info) |
| `linea_sepolia` | Linea | Test | [`SNAP`](#sync-mode) | Sequencer-based (zkEVM rollup) | Linea [Sepolia testnet](https://docs.linea.build/get-started/build/network-info/) |
| `lukso` | Lukso | Production | [`SNAP`](#sync-mode) | PoS network | Network for the [Lukso chain](https://lukso.network/) |
:::tip
Values are case-insensitive, so either `mainnet` or `MAINNET` works.
:::
:::info
- You can't use the `--network` and [`--genesis-file`](#genesis-file) options at the same time.
- The following networks and testnets are deprecated: ETC (Ethereum Classic) and Mordor.
:::
---
## `network-id`
```bash
--network-id=8675309
```
```bash
BESU_NETWORK_ID=8675309
```
```bash
network-id="8675309"
```
The [P2P network identifier](../concepts/network-and-chain-id.md).
Use this option to override the default network ID. The default value is the same as the chain ID defined in the genesis file.
---
## `node-private-key-file`
```bash
--node-private-key-file=/home/me/me_node/myPrivateKey
```
```bash
BESU_NODE_PRIVATE_KEY_FILE=/home/me/me_node/myPrivateKey
```
```bash
node-private-key-file="/home/me/me_node/myPrivateKey"
```
The private key file for the node. The default is the key file in the [data directory](#data-path). If no key file exists, Besu creates a key file containing the generated private key, otherwise, the existing key file specifies the node private key.
:::danger
The private key is not encrypted.
:::
This option is ignored if [`--security-module`](#security-module) is set to a non-default value.
---
## `p2p-enabled`
```bash
--p2p-enabled=false
```
```bash
BESU_P2P_ENABLED=false
```
```bash
p2p-enabled=false
```
Enables or disables all P2P communication.
The default is `true`.
---
## `p2p-host`
```bash
# to listen on all interfaces
--p2p-host=0.0.0.0
```
```bash
# to listen on all interfaces
BESU_P2P_HOST=0.0.0.0
```
```bash
p2p-host="0.0.0.0"
```
The advertised host that can be used to access the node from outside the network in [P2P communication](../how-to/connect/configure-ports.md#p2p-networking).
The default is `127.0.0.1`.
:::tip Early access feature
This option can take an IPv4 or IPv6 host.
To use IPv6 (discovery v5), set the early access option `--Xv5-discovery-enabled` to `true`.
If you specify an IPv6 host using `--p2p-host`, do not set [`--p2p-host-ipv6`](#p2p-host-ipv6).
:::
:::info
If [`--nat-method`](#nat-method) is set to [`NONE`](../how-to/connect/specify-nat.md), `--p2p-host` is not overridden and must be specified for the node to be accessed from outside the network.
:::
---
## `p2p-host-ipv6`
```bash
--p2p-host-ipv6=2001:db8:85a3::8a2e:370:7334
```
```bash
BESU_P2P_HOST_IPV6=2001:db8:85a3::8a2e:370:7334
```
```bash
p2p-host-ipv6="2001:db8:85a3::8a2e:370:7334"
```
The advertised IPv6 host that can be used to access the node from outside the network in [P2P communication](../how-to/connect/configure-ports.md#p2p-networking).
:::tip Early access feature
To use an IPv6 host (discovery v5), set the early access option `--Xv5-discovery-enabled` to `true`.
If you set `--p2p-host-ipv6`, do not specify an IPv6 host using [`--p2p-host`](#p2p-host).
:::
---
## `p2p-interface`
```bash
--p2p-interface=192.168.1.132
```
```bash
BESU_P2P_INTERFACE=192.168.1.132
```
```bash
p2p-interface="192.168.1.132"
```
The network interface on which the node listens for [P2P communication](../how-to/connect/configure-ports.md#p2p-networking). Use the option to specify the required network interface when the device that Besu is running on has multiple network interfaces. The default is 0.0.0.0 (all interfaces).
:::tip Early access feature
This option can take an IPv4 or IPv6 interface.
To use IPv6 (discovery v5), set the early access option `--Xv5-discovery-enabled` to `true`.
If you specify an IPv6 interface using `--p2p-interface`, do not set [`--p2p-interface-ipv6`](#p2p-interface-ipv6).
:::
---
## `p2p-interface-ipv6`
```bash
--p2p-interface-ipv6=2001:db8:85a3::1/64
```
```bash
BESU_P2P_INTERFACE_IPV6=2001:db8:85a3::1/64
```
```bash
p2p-interface-ipv6="2001:db8:85a3::1/64"
```
The IPv6 network interface on which the node listens for [P2P communication](../how-to/connect/configure-ports.md#p2p-networking).
Use the option to specify the required network interface when the device that Besu is running on has multiple network interfaces.
:::tip Early access feature
To use an IPv6 interface (discovery v5), set the early access option `--Xv5-discovery-enabled` to `true`.
If you set `--p2p-interface-ipv6`, do not specify an IPv6 interface using [`--p2p-interface`](#p2p-interface).
:::
---
## `p2p-ipv6-outbound-enabled`
```bash
--p2p-ipv6-outbound-enabled=true
```
```bash
BESU_P2P_IPV6_OUTBOUND_ENABLED=true
```
```bash
p2p-ipv6-outbound-enabled=true
```
Enables or disables preferring IPv6 addresses for outbound P2P connections when peers advertise both IPv4 and IPv6.
When set to `true`, IPv6 is preferred.
When omitted or set to `false`, IPv4 is preferred.
If a peer only advertises one address family, it is always used.
:::tip Early access feature
To use IPv6 addresses (discovery v5), set the early access option `--Xv5-discovery-enabled` to `true`.
:::
---
## `p2p-port`
```bash
# to listen on port 1789
--p2p-port=1789
```
```bash
# to listen on port 1789
BESU_P2P_PORT=1789
```
```bash
p2p-port="1789"
```
The P2P listening ports (UDP and TCP). The default is `30303`. You must [expose ports appropriately](../how-to/connect/configure-ports.md).
:::tip Early access feature
To use IPv6 (discovery v5), set the early access option `--Xv5-discovery-enabled` to `true`.
:::
---
## `p2p-port-ipv6`
```bash
# to listen on port 1789
--p2p-port-ipv6=1789
```
```bash
# to listen on port 1789
BESU_P2P_PORT_IPV6=1789
```
```bash
p2p-port-ipv6="1789"
```
The IPv6 P2P listening ports (UDP and TCP).
The default is `30404`.
You must [expose ports appropriately](../how-to/connect/configure-ports.md).
:::tip Early access feature
To use IPv6 (discovery v5), set the early access option `--Xv5-discovery-enabled` to `true`.
:::
---
## `p2p-tx-feecap`
```bash
--p2p-tx-feecap=1200000000000000000
```
```bash
BESU_P2P_TX_FEECAP=1200000000000000000
```
```bash
p2p-tx-feecap=1200000000000000000
```
The maximum transaction fee (in wei) accepted for transactions received from peers over the P2P network.
Transactions with a gas price (or, for EIP-1559 transactions, the max fee per gas) exceeding this value are rejected.
Rejected transactions never enter the transaction pool and aren't re-broadcast to peers.
The default has no practical limit, so the cap is effectively disabled.
Set this option to `0` to reject any transaction with a positive gas price.
---
## `plugin-block-txs-selection-max-time`
```bash
--plugin-block-txs-selection-max-time=50
```
```bash
BESU_PLUGIN_BLOCK_TXS_SELECTION_MAX_TIME=50
```
```bash
plugin-block-txs-selection-max-time=50
```
Maximum time, as a percentage of the overall block creation time, that [plugins](../../plugins/index.md) can use to propose their own transactions during block creation.
The default is `50`: limiting plugins to up to 50% of the total block creation time.
---
## `plugin-continue-on-error`
```bash
--plugin-continue-on-error=true
```
```bash
BESU_PLUGIN_CONTINUE_ON_ERROR=true
```
```bash
plugin-continue-on-error=true
```
Enables or disables continuing to run Besu if a [plugin](../../plugins/index.md)
fails during registration or other startup lifecycle stages.
If set to `true` and any plugin fails, Besu logs an error and continues running.
If set to `false` and any plugin fails, Besu logs an error and stops running.
The default is `false`.
---
## `plugins-verification-mode`
```bash
--plugins-verification-mode="FULL"
```
```bash
BESU_PLUGINS_VERIFICATION_MODE="FULL"
```
```bash
plugins-verification-mode=FULL
```
Controls whether Besu fails to start if a [plugin's](../../plugins/index.md) verification fails at
startup.
Verification mode options are `NONE` or `FULL`:
- If set to `NONE` and plugin verification fails, Besu logs a warning and continues running.
- If set to `FULL` and any plugin verification fails, Besu logs an error and stops running.
The default is `NONE`.
---
## `plugins`
```bash
--plugins=essential-plugin,security-plugin
```
```bash
BESU_PLUGINS=essential-plugin,security-plugin
```
```bash
plugins=["essential-plugin","security-plugin"]
```
Comma-separated list of [plugin](../../plugins/index.md) names to load. Each plugin must reside in
the `plugins` directory. If you omit this option, Besu automatically loads all plugins found in that directory.
The plugin name is case-sensitive, and is the name of the class that implements
[`BesuPlugin`](https://javadoc.io/doc/org.hyperledger.besu/plugin-api/latest/org/hyperledger/besu/plugin/BesuPlugin.html)
in the plugin source code.
If the specified plugin is not found, Besu exits with an error identifying the missing plugin.
---
## `print-paths-and-exit`
```bash
--print-paths-and-exit
```
Prints the Besu data directory paths and exits without starting the node.
---
## `profile`
```bash
--profile=STAKER
```
```bash
BESU_PROFILE=STAKER
```
```bash
profile="STAKER"
```
Loads a pre-configured TOML file containing custom settings for a specific user profile.
Possible values are:
- [`MINIMALIST_STAKER`](../how-to/configure-besu/profile.md#minimalist-staker-profile)
- [`STAKER`](../how-to/configure-besu/profile.md#staker-profile)
- [`ENTERPRISE` or `PRIVATE`](../how-to/configure-besu/profile.md#enterpriseprivate-profile) (aliases for the same profile)
- [`PERFORMANCE`](../how-to/configure-besu/profile.md#performance-profiles)
- [`PERFORMANCE_RPC`](../how-to/configure-besu/profile.md#performance-profiles)
- File name of an [external profile](../how-to/configure-besu/profile.md#load-external-profiles),
without the `.toml` extension.
The default is `null`.
---
## `random-peer-priority-enabled`
```bash
--random-peer-priority-enabled=true
```
```bash
BESU_RANDOM_PEER_PRIORITY_ENABLED=true
```
```bash
random-peer-priority-enabled=true
```
Enables or disables random prioritization of incoming connections. Enable in small, stable networks to prevent closed groups of peers forming.
The default is `false`.
---
## `receipt-compaction-enabled`
```bash
--receipt-compaction-enabled=true
```
```bash
BESU_RECEIPT_COMPACTION_ENABLED=true
```
```bash
receipt-compaction-enabled=true
```
Enables or disables receipt compaction.
Compacting receipts reduces storage by trimming unnecessary data from transaction receipts.
The default is `true`.
---
## `remote-connections-limit-enabled`
```bash
--remote-connections-limit-enabled=false
```
```bash
BESU_REMOTE_CONNECTIONS_LIMIT_ENABLED=false
```
```bash
remote-connections-limit-enabled=false
```
Enables or disables using the [`--remote-connections-max-percentage`](#remote-connections-max-percentage) option to limit the percentage of remote P2P connections initiated by peers.
The default is `true`.
:::tip
In private and permissioned networks with a level of trust between peers, disabling the remote connection limits may increase the speed at which nodes can join the network.
:::
:::danger
To prevent eclipse attacks, ensure you enable the remote connections limit when connecting to any public network, and especially when using [`--sync-mode`](#sync-mode) and [`--sync-min-peers`](#sync-min-peers).
:::
---
## `remote-connections-max-percentage`
```bash
--remote-connections-max-percentage=25
```
```bash
BESU_REMOTE_CONNECTIONS_MAX_PERCENTAGE=25
```
```bash
remote-connections-max-percentage=25
```
The percentage of remote P2P connections you can establish with the node. Must be between 0 and 100, inclusive. The default is 60.
---
## `reorg-logging-threshold`
```bash
--reorg-logging-threshold=3
```
```bash
BESU_REORG_LOGGING_THRESHOLD=3
```
```bash
reorg-logging-threshold=3
```
Minimum depth of chain reorganizations to log. The default is 6.
---
## `required-block`
```bash
--required-block=6485846=0x43f0cd1e5b1f9c4d5cda26c240b59ee4f1b510d0a185aa8fd476d091b0097a80
```
```bash
BESU_REQUIRED_BLOCK=6485846=0x43f0cd1e5b1f9c4d5cda26c240b59ee4f1b510d0a185aa8fd476d091b0097a80
```
```bash
required-block=["6485846=0x43f0cd1e5b1f9c4d5cda26c240b59ee4f1b510d0a185aa8fd476d091b0097a80"]
```
Requires a peer with the specified block number to have the specified hash when connecting, or Besu rejects that peer.
---
## `revert-reason-enabled`
```bash
--revert-reason-enabled=true
```
```bash
BESU_REVERT_REASON_ENABLED=true
```
```bash
revert-reason-enabled=true
```
Enables or disables including the [revert reason](../../private-networks/how-to/send-transactions/revert-reason.md) in the transaction receipt, [`eth_estimateGas`](api/eth/execute.md#eth_estimategas) error response, [`eth_call`](api/eth/execute.md#eth_call) error response, and [`trace`](api/trace.md#trace) response.
The default is `false`.
:::caution
Enabling revert reason may use a significant amount of memory. We don't recommend enabling revert reason when connected to public Ethereum networks.
:::
---
## `rpc-filter-timeout-seconds`
```bash
--rpc-filter-timeout-seconds=60
```
```bash
BESU_RPC_FILTER_TIMEOUT_SECONDS=60
```
```bash
rpc-filter-timeout-seconds=60
```
The number of seconds a [filter](api/eth/filter.md) can remain active without being polled before Besu removes it. Polling the filter with [`eth_getFilterChanges`](api/eth/filter.md#eth_getfilterchanges) or [`eth_getFilterLogs`](api/eth/filter.md#eth_getfilterlogs) resets the timer. The value must be greater than `0`. The default is `120` (two minutes).
Once a filter is removed, requests that use its filter ID fail. The client must create a new filter.
---
## `rpc-gas-cap`
```bash
--rpc-gas-cap=50000000
```
```bash
BESU_RPC_GAS_CAP=50000000
```
```bash
rpc-gas-cap=50000000
```
Sets a limit on the amount of gas for transaction simulation RPC methods.
This option allows users to override the transaction's gas limit.
This can prevent the simulation of transactions with high gas usage by setting a predefined cap, preventing DoS attacks.
Its value must be greater than or equal to `0`.
The default is `100000000`. You can set this to `0` to indicate there is no limit.
This cap prevents [`eth_call`](api/eth/execute.md#eth_call) requests from using excessive resources.
---
## `rpc-http-api`
```bash
--rpc-http-api=ETH,NET,WEB3
```
```bash
BESU_RPC_HTTP_API=ETH,NET,WEB3
```
```bash
rpc-http-api=["ETH","NET","WEB3"]
```
A comma-separated list of APIs to enable on the JSON-RPC HTTP channel. When you use this option you must also specify the `--rpc-http-enabled` option. The available API options are: `ADMIN`, `DEBUG`, `ENGINE`, `ETH`, `IBFT`, `MINER`, `NET`, `PERM`, `PLUGINS`, `QBFT`, `TRACE`, `TXPOOL`, and `WEB3`. The default is: `ETH`, `NET`, `WEB3`.
:::tip
The singular `--rpc-http-api` and plural `--rpc-http-apis` are available and are two names for the same option.
:::
---
## `rpc-http-api-methods-no-auth`
```bash
--rpc-http-api-methods-no-auth=admin_peers,debug_traceCall
```
```bash
BESU_RPC_HTTP_API_METHODS_NO_AUTH=admin_peers,debug_traceCall
```
```bash
rpc-http-api-methods-no-auth=["admin_peers","debug_traceCall"]
```
A comma-separated list of JSON-RPC API methods to exclude from [authentication services](../how-to/use-besu-api/authenticate.md).
:::note
You must enable JSON-RPC HTTP authentication using [`--rpc-http-authentication-enabled`](#rpc-http-authentication-enabled).
:::
---
## `rpc-http-authentication-credentials-file`
```bash
--rpc-http-authentication-credentials-file=/home/me/me_node/auth.toml
```
```bash
BESU_RPC_HTTP_AUTHENTICATION_CREDENTIALS_FILE=/home/me/me_node/auth.toml
```
```bash
rpc-http-authentication-credentials-file="/home/me/me_node/auth.toml"
```
The [credentials file](../how-to/use-besu-api/authenticate.md#1-create-the-credentials-file) for JSON-RPC API [authentication](../how-to/use-besu-api/authenticate.md).
---
## `rpc-http-authentication-enabled`
```bash
--rpc-http-authentication-enabled=true
```
```bash
BESU_RPC_HTTP_AUTHENTICATION_ENABLED=true
```
```bash
rpc-http-authentication-enabled=true
```
Enables or disables [authentication](../how-to/use-besu-api/authenticate.md) for the JSON-RPC HTTP service.
The default is `false`.
---
## `rpc-http-authentication-jwt-algorithm`
```bash
--rpc-http-authentication-jwt-algorithm=ES256
```
```bash
BESU_RPC_HTTP_AUTHENTICATION_JWT_ALGORITHM=ES256
```
```bash
rpc-http-authentication-jwt-algorithm="ES256"
```
The [JWT key algorithm](../how-to/use-besu-api/authenticate.md#1-generate-a-private-and-public-key-pair)
used to generate the keypair for JSON-RPC HTTP authentication.
Possible values are `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, and `ES512`.
The default is `RS256`.
---
## `rpc-http-authentication-jwt-public-key-file`
```bash
--rpc-http-authentication-jwt-public-key-file=publicKey.pem
```
```bash
BESU_RPC_HTTP_AUTHENTICATION_JWT_PUBLIC_KEY_FILE="publicKey.pem"
```
```bash
rpc-http-authentication-jwt-public-key-file="publicKey.pem"
```
The [JWT provider's public key file] used for JSON-RPC HTTP authentication with an external JWT.
---
## `rpc-http-cors-origins`
```bash
--rpc-http-cors-origins=http://medomain.com,http://remix.ethereum.org
```
```bash
BESU_RPC_HTTP_CORS_ORIGINS=http://medomain.com,https://meotherdomain.com
```
```bash
rpc-http-cors-origins=["http://medomain.com","https://meotherdomain.com"]
```
A comma-separated list of domain URLs for CORS validation.
Listed domains can access the node using JSON-RPC. If your client interacts with Besu using a browser app (such as Remix or a block explorer), add the client domain to the list.
The default value is `"none"`. If you do not list any domains, browser apps cannot interact with your Besu node.
:::note
To run a local Besu node with MetaMask, set `--rpc-http-cors-origins` to `chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn`.
Remember to also include the dapp domain MetaMask interacts with, for example if your app is deployed on Remix and you're using MetaMask to interact with the contract, use `--rpc-http-cors-origins=chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn,http://remix.ethereum.org`
:::
:::tip
For testing and development purposes, use `"all"` or `"*"` to accept requests from any domain. We don't recommend accepting requests from any domain for production environments.
:::
---
## `rpc-http-enabled`
```bash
--rpc-http-enabled=true
```
```bash
BESU_RPC_HTTP_ENABLED=true
```
```bash
rpc-http-enabled=true
```
Enables or disables the JSON-RPC HTTP service.
The default is `false`.
---
## `rpc-http-host`
```bash
# to listen on all interfaces
--rpc-http-host=0.0.0.0
```
```bash
BESU_RPC_HTTP_HOST=0.0.0.0
```
```bash
rpc-http-host="0.0.0.0"
```
The host on which JSON-RPC HTTP listens. The default is `127.0.0.1`.
To allow remote connections, set to `0.0.0.0`.
:::caution
Setting the host to `0.0.0.0` exposes the RPC connection on your node to any remote connection. In a production environment, ensure you are using a firewall to avoid exposing your node to the internet.
:::
---
## `rpc-http-max-active-connections`
```bash
--rpc-http-max-active-connections=100
```
```bash
BESU_RPC_HTTP_MAX_ACTIVE_CONNECTIONS=100
```
```toml
rpc-http-max-active-connections=100
```
The maximum number of allowed JSON-RPC HTTP connections. Once this limit is reached, incoming connections are rejected. The default is 80.
---
## `rpc-http-max-request-content-length`
```bash
--rpc-http-max-request-content-length=2097152
```
```bash
BESU_RPC_HTTP_MAX_REQUEST_CONTENT_LENGTH=2097152
```
```toml
rpc-http-max-request-content-length=2097152
```
The maximum request content length.
Besu only accepts JSON-RPC API requests with a body size less than or equal to this value.
The default is 5242880 (5 MB).
---
## `rpc-http-max-batch-size`
```bash
--rpc-http-max-batch-size=1200
```
```bash
BESU_RPC_HTTP_MAX_BATCH_SIZE=1200
```
```toml
rpc-http-max-batch-size=1200
```
The maximum number of allowed requests in a [RPC batch request](../how-to/use-besu-api/json-rpc.md#http). The default limit is `1024`, and `-1` specifies no limit.
---
## `rpc-http-port`
```bash
# to listen on port 3435
--rpc-http-port=3435
```
```bash
BESU_RPC_HTTP_PORT=3435
```
```bash
rpc-http-port="3435"
```
The port (TCP) on which JSON-RPC HTTP listens. The default is `8545`. You must [expose ports appropriately](../how-to/connect/configure-ports.md).
---
## `rpc-http-tls-ca-clients-enabled`
```bash
--rpc-http-tls-ca-clients-enabled=true
```
```bash
BESU_RPC_HTTP_TLS_CA_CLIENTS_ENABLED=true
```
```bash
rpc-http-tls-ca-clients-enabled=true
```
Enables or disables clients with trusted CA certificates to connect.
The default is `false`.
:::note
You must enable client authentication using the [`--rpc-http-tls-client-auth-enabled`](#rpc-http-tls-client-auth-enabled) option.
:::
---
## `rpc-http-tls-client-auth-enabled`
```bash
--rpc-http-tls-client-auth-enabled=true
```
```bash
BESU_RPC_HTTP_TLS_CLIENT_AUTH_ENABLED=true
```
```bash
rpc-http-tls-client-auth-enabled=true
```
Enables or disables TLS client authentication for the JSON-RPC HTTP service.
The default is `false`.
:::note
You must specify [`--rpc-http-tls-ca-clients-enabled`](#rpc-http-tls-ca-clients-enabled) and/or [`rpc-http-tls-known-clients-file`](#rpc-http-tls-known-clients-file).
:::
---
## `rpc-http-tls-cipher-suite`
```bash
--rpc-http-tls-cipher-suite=TLS_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
```
```bash
BESU_RPC_HTTP_TLS_CIPHER_SUITE=TLS_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
```
```bash
rpc-http-tls-cipher-suite=["TLS_AES_256_GCM_SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"]
```
A list of comma-separated TLS cipher suites to support.
:::tip
The singular `--rpc-http-tls-cipher-suite` and plural `--rpc-http-tls-cipher-suites` are available and are two names for the same option.
:::
---
## `rpc-http-tls-enabled`
```bash
--rpc-http-tls-enabled=true
```
```bash
BESU_RPC_HTTP_TLS_ENABLED=true
```
```bash
rpc-http-tls-enabled=true
```
Enables or disables TLS for the JSON-RPC HTTP service.
The default is `false`.
:::note
[`--rpc-http-enabled`](#rpc-http-enabled) must be enabled.
:::
---
## `rpc-http-tls-keystore-file`
```bash
--rpc-http-tls-keystore-file=/home/me/me_node/keystore.pfx
```
```bash
BESU_RPC_HTTP_TLS_KEYSTORE_FILE=/home/me/me_node/keystore.pfx
```
```bash
rpc-http-tls-keystore-file="/home/me/me_node/keystore.pfx"
```
Path to the keystore file (in PKCS #12 format) when enabling TLS for the JSON-RPC HTTP service.
The keystore file contains the private key and certificate presented to the client during authentication.
Specify the keystore password file using [`--rpc-http-tls-keystore-password-file`](#rpc-http-tls-keystore-password-file).
---
## `rpc-http-tls-keystore-password-file`
```bash
--rpc-http-tls-keystore-password-file=/home/me/me_node/password
```
```bash
BESU_RPC_HTTP_TLS_KEYSTORE_PASSWORD_FILE=/home/me/me_node/password
```
```bash
rpc-http-tls-keystore-password-file="/home/me/me_node/password"
```
Path to the file containing the password for the keystore specified in [`--rpc-http-tls-keystore-file`](#rpc-http-tls-keystore-file),
when enabling TLS for the JSON-RPC HTTP service.
---
## `rpc-http-tls-known-clients-file`
```bash
--rpc-http-tls-known-clients-file=/home/me/me_node/knownClients
```
```bash
BESU_RPC_HTTP_TLS_KNOWN_CLIENTS_FILE=/home/me/me_node/knownClients
```
```bash
rpc-http-tls-known-clients-file="/home/me/me_node/knownClients"
```
Path to the file used to [authenticate clients](../../private-networks/how-to/configure/tls.md#create-the-known-clients-file) using self-signed certificates or non-public certificates.
Must contain the certificate's Common Name, and SHA-256 fingerprint in the format ``.
:::note
You must enable client authentication using the [`--rpc-http-tls-client-auth-enabled`](#rpc-http-tls-client-auth-enabled) option.
:::
---
## `rpc-http-tls-protocol`
```bash
--rpc-http-tls-protocol=TLSv1.3,TLSv1.2
```
```bash
BESU_RPC_HTTP_TLS_PROTOCOL=TLSv1.3,TLSv1.2
```
```bash
rpc-http-tls-protocol=["TLSv1.3","TLSv1.2"]
```
A list of comma-separated TLS protocols to support. The default is `DEFAULT_TLS_PROTOCOLS`, a list which includes `TLSv1.3` and `TLSv1.2`.
:::tip
The singular `--rpc-http-tls-protocol` and plural `--rpc-http-tls-protocols` are available and are two names for the same option.
:::
---
## `rpc-http-tls-truststore-file`
```bash
--rpc-http-tls-truststore-file=/home/me/me_node/truststore.pfx
```
```bash
BESU_RPC_HTTP_TLS_TRUSTSTORE_FILE=/home/me/me_node/truststore.pfx
```
```bash
rpc-http-tls-truststore-file="/home/me/me_node/truststore.pfx"
```
Path to the truststore file when enabling TLS for the JSON-RPC HTTP service.
Specify the truststore password file using [`--rpc-http-tls-truststore-password-file`](#rpc-http-tls-truststore-password-file).
---
## `rpc-http-tls-truststore-password-file`
```bash
--rpc-http-tls-truststore-password-file=/home/me/me_node/password
```
```bash
BESU_RPC_HTTP_TLS_TRUSTSTORE_PASSWORD_FILE=/home/me/me_node/password
```
```bash
rpc-http-tls-truststore-password-file="/home/me/me_node/password"
```
Path to the file containing the password for the truststore specified in [`--rpc-http-tls-truststore-file`](#rpc-http-tls-truststore-file),
when enabling TLS for the JSON-RPC HTTP service.
---
## `rpc-max-active-filters`
```bash
--rpc-max-active-filters=1000
```
```bash
BESU_RPC_MAX_ACTIVE_FILTERS=1000
```
```bash
rpc-max-active-filters=1000
```
The maximum number of concurrently active [filters](api/eth/filter.md) created using [`eth_newFilter`](api/eth/filter.md#eth_newfilter), [`eth_newBlockFilter`](api/eth/filter.md#eth_newblockfilter), and [`eth_newPendingTransactionFilter`](api/eth/filter.md#eth_newpendingtransactionfilter). The value must be equal to or greater than `0`. Setting this option to `0` indicates there is no limit. The default is `1000`.
Once this limit is reached, requests to create a filter return an error until an existing filter is uninstalled using [`eth_uninstallFilter`](api/eth/filter.md#eth_uninstallfilter) or removed after the period specified by [`--rpc-filter-timeout-seconds`](#rpc-filter-timeout-seconds).
---
## `rpc-max-logs-range`
```bash
--rpc-max-logs-range=500
```
```bash
BESU_RPC_MAX_LOGS_RANGE=500
```
```bash
rpc-max-logs-range=500
```
When using [`eth_getLogs`](api/eth/filter.md#eth_getlogs), the maximum number of blocks to retrieve logs from. Set to 0 to specify no limit. The default is 5000.
:::caution
Using `eth_getLogs` to get logs from a large range of blocks, especially an entire chain from its
genesis block, might cause Besu to stop responding for an indeterminable amount of time while
generating the response.
We recommend setting a range limit or leaving this option at its default value.
:::
---
## `rpc-max-trace-filter-range`
```bash
--rpc-max-trace-filter-range=100
```
```bash
--BESU_RPC_MAX_TRACE_FILTER_RANGE=100
```
```bash
rpc-max-trace-filter-range=100
```
The maximum number of blocks you can supply to the [`trace_filter`](api/trace.md#trace_filter) method. The value must be equal to or greater than `0`. Setting this option to `0` indicates there is no limit. The default is `1000`.
---
## `rpc-tx-feecap`
```bash
--rpc-tx-feecap=1200000000000000000
```
```bash
BESU_RPC_TX_FEECAP=1200000000000000000
```
```bash
rpc-tx-feecap=1200000000000000000
```
The maximum transaction fee (in wei) accepted for transactions submitted through the [`eth_sendRawTransaction`](api/eth/submit.md#eth_sendrawtransaction) RPC method. The default is `1000000000000000000` (1 ether).
If set to `0`, then this option is ignored and no cap is applied.
---
## `rpc-ws-api`
```bash
--rpc-ws-api=ETH,NET,WEB3
```
```bash
BESU_RPC_WS_API=ETH,NET,WEB3
```
```bash
rpc-ws-api=["ETH","NET","WEB3"]
```
A comma-separated list of APIs to enable on the WebSockets channel. When you use this option you must also specify the `--rpc-ws-enabled` option. The available API options are: `ADMIN`, `DEBUG`, `ENGINE`, `ETH`, `IBFT`, `MINER`, `NET`, `PERM`, `PLUGINS`, `QBFT`, `TRACE`, `TXPOOL`, and `WEB3`. The default is: `ETH`, `NET`, `WEB3`.
:::tip
The singular `--rpc-ws-api` and plural `--rpc-ws-apis` options are available and are two names for the same option.
:::
---
## `rpc-ws-api-methods-no-auth`
```bash
--rpc-ws-api-methods-no-auth=admin_peers,debug_traceCall
```
```bash
BESU_RPC_WS_API_METHODS_NO_AUTH=admin_peers,debug_traceCall
```
```bash
rpc-ws-api-methods-no-auth=["admin_peers","debug_traceCall"]
```
A comma-separated list of JSON-RPC API methods to exclude from [authentication services](../how-to/use-besu-api/authenticate.md).
:::note
You must enable JSON-RPC WebSocket authentication using [`--rpc-ws-authentication-enabled`](#rpc-ws-authentication-enabled).
:::
---
## `rpc-ws-authentication-credentials-file`
```bash
--rpc-ws-authentication-credentials-file=/home/me/me_node/auth.toml
```
```bash
BESU_RPC_WS_AUTHENTICATION_CREDENTIALS_FILE=/home/me/me_node/auth.toml
```
```bash
rpc-ws-authentication-credentials-file="/home/me/me_node/auth.toml"
```
The path to the [credentials file](../how-to/use-besu-api/authenticate.md#1-create-the-credentials-file) for JSON-RPC API [authentication](../how-to/use-besu-api/authenticate.md).
---
## `rpc-ws-authentication-enabled`
```bash
--rpc-ws-authentication-enabled=true
```
```bash
BESU_RPC_WS_AUTHENTICATION_ENABLED=true
```
```bash
rpc-ws-authentication-enabled=true
```
Enables or disables [authentication](../how-to/use-besu-api/authenticate.md) for the JSON-RPC WebSocket service.
The default is `false`.
:::note
`wscat` doesn't support headers. [Authentication](../how-to/use-besu-api/authenticate.md) requires you to pass an authentication token in the request header. To use authentication with WebSockets, you need an app that supports headers.
:::
---
## `rpc-ws-authentication-jwt-algorithm`
```bash
--rpc-ws-authentication-jwt-algorithm=ES256
```
```bash
BESU_RPC_WS_AUTHENTICATION_JWT_ALGORITHM=ES256
```
```bash
rpc-ws-authentication-jwt-algorithm="ES256"
```
The [JWT key algorithm](../how-to/use-besu-api/authenticate.md#1-generate-a-private-and-public-key-pair)
used to generate the keypair for JSON-RPC WebSocket authentication.
Possible values are `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, and `ES512`.
The default is `RS256`.
---
## `rpc-ws-authentication-jwt-public-key-file`
```bash
--rpc-ws-authentication-jwt-public-key-file=publicKey.pem
```
```bash
BESU_RPC_WS_AUTHENTICATION_JWT_PUBLIC_KEY_FILE="publicKey.pem"
```
```bash
rpc-ws-authentication-jwt-public-key-file="publicKey.pem"
```
The [JWT provider's public key file] used for JSON-RPC WebSocket authentication with an external JWT.
---
## `rpc-ws-enabled`
```bash
--rpc-ws-enabled=true
```
```bash
BESU_RPC_WS_ENABLED=true
```
```bash
rpc-ws-enabled=true
```
Enables or disables the WebSocket JSON-RPC service.
The default is `false`.
---
## `rpc-ws-host`
```bash
# to listen on all interfaces
--rpc-ws-host=0.0.0.0
```
```bash
BESU_RPC_WS_HOST=0.0.0.0
```
```bash
rpc-ws-host="0.0.0.0"
```
The host on which WebSocket JSON-RPC listens.
The default is `127.0.0.1`.
To allow remote connections, set to `0.0.0.0`
---
## `rpc-ws-max-active-connections`
```bash
--rpc-ws-max-active-connections=100
```
```bash
BESU_RPC_WS_MAX_ACTIVE_CONNECTIONS=100
```
```toml
rpc-ws-max-active-connections=100
```
The maximum number of WebSocket connections allowed for JSON-RPC. Once this limit is reached, incoming connections are rejected. The default is 80.
---
## `rpc-ws-max-active-subscriptions`
```bash
--rpc-ws-max-active-subscriptions=1000
```
```bash
BESU_RPC_WS_MAX_ACTIVE_SUBSCRIPTIONS=1000
```
```toml
rpc-ws-max-active-subscriptions=1000
```
The maximum number of active [RPC Pub/Sub subscriptions](../how-to/use-besu-api/rpc-pubsub.md) allowed for JSON-RPC, counted across all WebSocket connections. The value must be equal to or greater than `0`. Setting this option to `0` indicates there is no limit. The default is `100000`.
Once this limit is reached, [`eth_subscribe`](../how-to/use-besu-api/rpc-pubsub.md#subscribe) requests return an error until clients [unsubscribe](../how-to/use-besu-api/rpc-pubsub.md#unsubscribe) or their connections close.
---
## `rpc-ws-max-frame-size`
```bash
--rpc-ws-max-frame-size=65536
```
```bash
BESU_RPC_WS_MAX_FRAME_SIZE=65536
```
```toml
rpc-ws-max-frame-size=65536
```
The maximum size in bytes for JSON-RPC WebSocket frames. If this limit is exceeded, the WebSocket disconnects. The default is 1048576 (or 1 MB).
---
## `rpc-ws-port`
```bash
# to listen on port 6174
--rpc-ws-port=6174
```
```bash
BESU_RPC_WS_PORT=6174
```
```bash
rpc-ws-port="6174"
```
The port (TCP) on which WebSocket JSON-RPC listens. The default is `8546`. You must [expose ports appropriately](../how-to/connect/configure-ports.md).
---
## `rpc-ws-ssl-cert-file`
```bash
--rpc-ws-ssl-cert-file=/home/me/me_node/websocket-cert.pem
```
```bash
BESU_RPC_WS_SSL_CERT_FILE="/home/me/me_node/websocket-cert.pem"
```
```bash
rpc-ws-ssl-cert-file="/home/me/me_node/websocket-cert.pem"
```
Path to the PEM certificate file enabling SSL/TLS for the WebSocket JSON-RPC service.
This file contains the public certificate that is used to establish the identity of the server to clients.
Specify the private key file using [`--rpc-ws-ssl-key-file`](#rpc-ws-ssl-key-file).
Required if [`--rpc-ws-ssl-keystore-type`](#rpc-ws-ssl-keystore-type) is `PEM`.
---
## `rpc-ws-ssl-client-auth-enabled`
```bash
--rpc-ws-ssl-client-auth-enabled=true
```
```bash
BESU_RPC_WS_SSL_CLIENT_AUTH_ENABLED=true
```
```bash
rpc-ws-ssl-client-auth-enabled=true
```
Enables or disables client authentication for the WebSocket JSON-RPC service.
The default is `false`.
:::note
When enabling client authentication, specify the truststore type using [`--rpc-ws-ssl-truststore-type`](#rpc-ws-ssl-truststore-type)
and provide the appropriate file path for the truststore or trust certificate using either
[`--rpc-ws-ssl-truststore-file`](#rpc-ws-ssl-truststore-file) (for JKS or PKCS12) or
[`--rpc-ws-ssl-trustcert-file`](#rpc-ws-ssl-trustcert-file) (for PEM).
If using JKS or PKCS12, specify the truststore password using [`--rpc-ws-ssl-truststore-password`](#rpc-ws-ssl-truststore-password).
:::
---
## `rpc-ws-ssl-enabled`
```bash
--rpc-ws-ssl-enabled=true
```
```bash
BESU_RPC_WS_SSL_ENABLED=true
```
```bash
rpc-ws-ssl-enabled=true
```
Enables or disables server SSL/TLS authentication for the WebSocket JSON-RPC service.
The default is `false`.
Set the appropriate keystore type using [`--rpc-ws-ssl-keystore-type`](#rpc-ws-ssl-keystore-type).
---
## `rpc-ws-ssl-key-file`
```bash
--rpc-ws-ssl-key-file=/home/me/me_node/websocket-cert.pem
```
```bash
BESU_RPC_WS_SSL_KEY_FILE="/home/me/me_node/websocket-cert.pem"
```
```bash
rpc-ws-ssl-key-file="/home/me/me_node/websocket-cert.pem"
```
Path to the PEM certificate file when enabling SSL/TLS for the WebSocket JSON-RPC service.
This file contains the private key that corresponds to the public certificate specified using
[`--rpc-ws-ssl-cert-file`](#rpc-ws-ssl-cert-file).
Required if [`--rpc-ws-ssl-keystore-type`](#rpc-ws-ssl-keystore-type) is `PEM`.
---
## `rpc-ws-ssl-keystore-file`
```bash
--rpc-ws-ssl-keystore-file=/home/me/me_node/keystore.jks
```
```bash
BESU_RPC_WS_SSL_KEYSTORE_FILE="/home/me/me_node/keystore.jks"
```
```bash
rpc-ws-ssl-keystore-file="/home/me/me_node/keystore.jks"
```
Path to the keystore file when enabling SSL/TLS for the WebSocket JSON-RPC service.
The keystore file is used to store the server's private key and public certificate in a single
file, typically in JKS or PKCS12 format. Use this option if you prefer to
manage your SSL/TLS certificates and keys in a keystore rather than separate PEM files.
Required if [`--rpc-ws-ssl-keystore-type`](#rpc-ws-ssl-keystore-type) is set to `JKS` or `PKCS12`.
Specify the keystore password using [`--rpc-ws-ssl-keystore-password`](#rpc-ws-ssl-keystore-password)
or [`--rpc-ws-ssl-keystore-password-file`](#rpc-ws-ssl-keystore-password-file).
---
## `rpc-ws-ssl-keystore-password`
```bash
--rpc-ws-ssl-keystore-password=keystore_password
```
```bash
BESU_RPC_WS_SSL_KEYSTORE_PASSWORD="keystore_password"
```
```bash
rpc-ws-ssl-keystore-password="keystore_password"
```
Password for the keystore specified in [`--rpc-ws-ssl-keystore-file`](#rpc-ws-ssl-keystore-file),
when enabling WebSocket SSL/TLS client authentication.
---
## `rpc-ws-ssl-keystore-password-file`
```bash
--rpc-ws-ssl-keystore-password-file=/home/me/me_node/keystore-password.txt
```
```bash
BESU_RPC_WS_SSL_KEYSTORE_PASSWORD_FILE="/home/me/me_node/keystore-password.txt"
```
```bash
rpc-ws-ssl-keystore-password-file="/home/me/me_node/keystore-password.txt"
```
Path to the file containing the password for the keystore specified in [`--rpc-ws-ssl-keystore-file`](#rpc-ws-ssl-keystore-file),
when enabling WebSocket SSL/TLS client authentication.
---
## `rpc-ws-ssl-keystore-type`
```bash
--rpc-ws-ssl-keystore-type=JKS
```
```bash
BESU_RPC_WS_SSL_KEYSTORE_TYPE="JKS"
```
```bash
rpc-ws-ssl-keystore-type="JKS"
```
Type of the keystore when enabling SSL/TLS for the WebSocket JSON-RPC service. Valid options are
`JKS`, `PKCS12`, and `PEM`.
Provide the appropriate file path for the keystore using either
[`--rpc-ws-ssl-keystore-file`](#rpc-ws-ssl-keystore-file) (for `JKS` or `PKCS12`), or
[`--rpc-ws-ssl-key-file`](#rpc-ws-ssl-key-file) and [`--rpc-ws-ssl-cert-file`](#rpc-ws-ssl-cert-file) (for `PEM`).
---
## `rpc-ws-ssl-trustcert-file`
```bash
--rpc-ws-ssl-trustcert-file=/home/me/me_node/trust-cert.pem
```
```bash
BESU_RPC_WS_SSL_TRUSTCERT_FILE="/home/me/me_node/trust-cert.pem"
```
```bash
rpc-ws-ssl-trustcert-file="/home/me/me_node/trust-cert.pem"
```
Path to the PEM trust certificate file when enabling client SSL/TLS authentication for the WebSocket JSON-RPC
service.
---
## `rpc-ws-ssl-truststore-file`
```bash
--rpc-ws-ssl-truststore-file=/home/me/me_node/websocket-truststore.jks
```
```bash
BESU_RPC_WS_SSL_TRUSTSTORE_FILE="/home/me/me_node/websocket-truststore.jks"
```
```bash
rpc-ws-ssl-truststore-file="/home/me/me_node/websocket-truststore.jks"
```
Path to the truststore file when enabling SSL/TLS client authentication for the WebSocket JSON-RPC
service.
Specify the truststore password using [`--rpc-ws-ssl-truststore-password`](#rpc-ws-ssl-truststore-password)
or [`--rpc-ws-ssl-truststore-password-file`](#rpc-ws-ssl-truststore-password-file).
---
## `rpc-ws-ssl-truststore-password`
```bash
--rpc-ws-ssl-truststore-password=truststore_password
```
```bash
BESU_RPC_WS_SSL_TRUSTSTORE_PASSWORD="truststore_password"
```
```bash
rpc-ws-ssl-truststore-password="truststore_password"
```
Password for the truststore specified using [`--rpc-ws-ssl-truststore-file`](#rpc-ws-ssl-truststore-file),
when enabling WebSocket SSL/TLS client authentication.
---
## `rpc-ws-ssl-truststore-password-file`
```bash
--rpc-ws-ssl-truststore-password-file=/home/me/me_node/truststore-password.txt
```
```bash
BESU_RPC_WS_SSL_TRUSTSTORE_PASSWORD_FILE="/home/me/me_node/truststore-password.txt"
```
```bash
rpc-ws-ssl-truststore-password-file="/home/me/me_node/truststore-password.txt"
```
Path to the file containing the password for the truststore specified in [`--rpc-ws-ssl-truststore-file`](#rpc-ws-ssl-truststore-file),
when enabling WebSocket SSL/TLS client authentication.
---
## `rpc-ws-ssl-truststore-type`
```bash
--rpc-ws-ssl-truststore-type=JKS
```
```bash
BESU_RPC_WS_SSL_TRUSTSTORE_TYPE="JKS"
```
```bash
rpc-ws-ssl-truststore-type="JKS"
```
Type of the truststore when enabling client SSL/TLS authentication for the WebSocket JSON-RPC service. Valid options are
`JKS`, `PKCS12`, and `PEM`.
Specify the required [`--rpc-ws-ssl-truststore-file`](#rpc-ws-ssl-truststore-file) for `JKS` and `PKCS12`, or
[`--rpc-ws-ssl-trustcert-file`](#rpc-ws-ssl-trustcert-file) for `PEM`.
---
## `security-module`
```bash
--security-module=hsm
```
```bash
BESU_SECURITY_MODULE=hsm
```
```bash
security-module="hsm"
```
Name of the security module plugin to use for [node key](../concepts/node-keys.md) storage.
For example, use a Hardware Security Module (HSM) or V3 filestore plugin, such as the
[Besu HSM plugin](https://github.com/besu-eth/besu-hsm-plugin).
The default is `localfile`.
If using a local private key file, specify its location using [`--node-private-key-file`](#node-private-key-file).
---
## `snapsync-server-enabled`
```bash
--snapsync-server-enabled=true
```
```bash
BESU_SNAPSYNC_SERVER_ENABLED=true
```
```bash
snapsync-server-enabled=true
```
Enables or disables serving [snap sync](../concepts/node-sync.md#snap-synchronization) data.
Set to `true` to allow other nodes to download data from this node using snap sync.
The default is `false`.
---
## `snapsync-synchronizer-pre-checkpoint-headers-only-enabled`
```bash
--snapsync-synchronizer-pre-checkpoint-headers-only-enabled=false
```
```bash
BESU_SNAPSYNC_SYNCHRONIZER_PRE_CHECKPOINT_HEADERS_ONLY_ENABLED=false
```
```bash
snapsync-synchronizer-pre-checkpoint-headers-only-enabled=false
```
If set to `false`, [snap sync](../concepts/node-sync.md#snap-synchronization) downloads full pre-merge Proof of Work (PoW) historical blocks
instead of headers only, allowing full historical data to be retained.
The default is `true`.
Setting this option to `false` increases sync time and disk space usage.
---
## `snapsync-synchronizer-transaction-indexing-enabled`
```bash
--snapsync-synchronizer-transaction-indexing-enabled=true
```
```bash
BESU_SNAPSYNC_SYNCHRONIZER_TRANSACTION_INDEXING_ENABLED=true
```
```bash
snapsync-synchronizer-transaction-indexing-enabled=true
```
Enables or disables transaction indexing during initial [snap sync](../concepts/node-sync.md#snap-synchronization).
The default is `false`.
:::note Notes
- Enable this option to query historical transactions by hash.
- Setting this option to `true` increases sync time and disk space usage.
:::
---
## `static-nodes-file`
```bash
--static-nodes-file=/path/to/besudata/static-nodes.json
```
```bash
BESU_STATIC_NODES_FILE=/path/to/besudata/static-nodes.json
```
```bash
static-nodes-file="/path/to/besudata/static-nodes.json"
```
Static nodes JSON file containing the [static nodes](../how-to/connect/static-nodes.md) for this node to connect to. The default is `datapath/static-nodes.json`.
---
## `strict-tx-replay-protection-enabled`
```bash
--strict-tx-replay-protection-enabled=false
```
```bash
BESU_STRICT_TX_REPLAY_PROTECTION_ENABLED=false
```
```bash
strict-tx-replay-protection-enabled=false
```
Enables or disables replay protection, in accordance with [EIP-155](https://eips.ethereum.org/EIPS/eip-155), on transactions submitted using JSON-RPC.
The default is `false`.
---
## `sync-min-peers`
```bash
--sync-min-peers=8
```
```bash
BESU_SYNC_MIN_PEERS=8
```
```bash
sync-min-peers=8
```
The minimum number of peers required before starting [sync](../concepts/node-sync.md). The default is `5`. Set to `1` to enable static peers to contribute to the initial sync.
:::info
This option does not apply to Proof of Stake networks.
:::
---
## `sync-mode`
```bash
--sync-mode=SNAP
```
```bash
BESU_SYNC_MODE=SNAP
```
```bash
sync-mode="SNAP"
```
The synchronization mode. Use `SNAP` for [snap sync](../concepts/node-sync.md#snap-synchronization) and `FULL` for [full sync](../concepts/node-sync.md#full-synchronization).
- The default is `FULL` when connecting to a private network by not using the [`--network`](#network) option and specifying the [`--genesis-file`](#genesis-file) option.
- The default is `SNAP` when using the [`--network`](#network) option with named networks, except for the `dev` development network. `SNAP` is also the default if running Besu on the default network (Ethereum Mainnet) by specifying neither [network](#network) nor [genesis file](#genesis-file).
:::warning Checkpoint sync
Checkpoint sync is deprecated.
If you specify `CHECKPOINT`, Besu performs snap sync instead.
:::
---
## `target-gas-limit`
```bash
--target-gas-limit=8000000
```
```bash
BESU_TARGET_GAS_LIMIT=8000000
```
```bash
target-gas-limit="8000000"
```
The gas limit toward which Besu will gradually move on an existing network, if enough miners are in agreement. To change the block gas limit set in the genesis file without creating a new network, use `target-gas-limit`. The gas limit between blocks can change only 1/1024th, so the target tells the block creator how to set the gas limit in its block. If the values are the same or within 1/1024th, Besu sets the limit to the specified value. Otherwise, the limit moves as far as it can within that constraint.
If a value for `target-gas-limit` is not specified, the block gas limit remains at the value specified in the [genesis file](genesis-items.md#genesis-block-parameters).
Use the [`miner_changeTargetGasLimit`](api/miner.md#miner_changetargetgaslimit) API to update the `target-gas-limit` while Besu is running. Alternatively restart Besu with an updated `target-gas-limit` value.
---
## `tx-pool`
```bash
--tx-pool=sequenced
```
```bash
BESU_TX_POOL=sequenced
```
```bash
tx-pool="sequenced"
```
Type of [transaction pool](../concepts/transactions/pool.md) to use.
Set to `layered` to use the [layered transaction pool](../concepts/transactions/pool.md#layered-transaction-pool) implementation.
The default is `layered`.
Set to `sequenced` to use the [sequenced transaction pool](../concepts/transactions/pool.md#sequenced-transaction-pool).
The default is `sequenced` for the [enterprise/private profile](../how-to/configure-besu/profile.md#enterpriseprivate-profile).
---
## `tx-pool-blob-price-bump`
```bash
--tx-pool-blob-price-bump=25
```
```bash
BESU_TX_POOL_BLOB_PRICE_BUMP=25
```
```bash
tx-pool-blob-price-bump="25"
```
Sets the price bump policy for re-issued blob transactions as a percentage increase in price.
A blob transaction can only replace, or be replaced by, another blob transaction.
The default is `100`.
---
## `tx-pool-enable-balance-check`
```bash
--tx-pool-enable-balance-check=true
```
```bash
BESU_TX_POOL_ENABLE_BALANCE_CHECK=true
```
```bash
tx-pool-enable-balance-check=true
```
Enables or disables balance checks for pending transactions in the [transaction pool](../concepts/transactions/pool.md).
When enabled, the check prevents pending transactions, whose sender doesn't have enough balance to pay their fee, from being included in the prioritized layer. This prevents such transactions from occupying space and potentially being selected for block production.
The default is `true`.
---
## `tx-pool-enable-save-restore`
```bash
--tx-pool-enable-save-restore=true
```
```bash
BESU_TX_POOL_ENABLE_SAVE_RESTORE=true
```
```bash
tx-pool-enable-save-restore=true
```
Enables or disables saving the [transaction pool](../concepts/transactions/pool.md) contents to a
file on shutdown and reloading it at startup.
The default is `false`.
You can define a custom path to the transaction pool file using the [`--tx-pool-save-file`](#tx-pool-save-file) option.
---
## `tx-pool-layer-max-capacity`
```bash
--tx-pool-layer-max-capacity=20000000
```
```bash
BESU_TX_POOL_LAYER_MAX_CAPACITY=20000000
```
```bash
tx-pool-layer-max-capacity="20000000"
```
Maximum amount of memory (in bytes) that any layer within the [layered transaction pool](../concepts/transactions/pool.md#layered-transaction-pool) can occupy.
The default is `12500000`, or 12.5 MB.
The transaction pool includes two memory-limited layers, resulting in an expected memory consumption
that is twice the value specified by this option, or 25 MB by default.
Increase this value if you have spare RAM and the eviction rate is high for your network.
---
## `tx-pool-limit-by-account-percentage`
```bash
--tx-pool-limit-by-account-percentage=0.1
```
```bash
BESU_TX_POOL_LIMIT_BY_ACCOUNT_PERCENTAGE=0.1
```
```bash
tx-pool-limit-by-account-percentage=0.4
```
The maximum percentage of transactions from a single sender kept in the [transaction pool](../concepts/transactions/pool.md).
Accepted values are in the range `(0–1]`.
The default is `.001`, or 0.1% of transactions from a single sender to be kept in the pool.
:::caution
- With the [layered transaction pool](../concepts/transactions/pool.md#layered-transaction-pool)
implementation, this option is not applicable.
Replace this option with [`--tx-pool-max-future-by-sender`](#tx-pool-max-future-by-sender) to
specify the maximum number of sequential transactions from a single sender kept in the pool.
- The default value is often unsuitable for [private networks](../../private-networks/index.md).
This feature mitigates future-nonce transactions from filling the pool without ever being
executable by Besu.
This is important for Mainnet, but may cause issues on private networks.
Please update this value or set to `1` if you know the nodes gossiping transactions in your network.
:::
---
## `tx-pool-max-future-by-sender`
```bash
--tx-pool-max-future-by-sender=250
```
```bash
BESU_TX_POOL_MAX_FUTURE_BY_SENDER=250
```
```bash
tx-pool-max-future-by-sender="250"
```
The maximum number of sequential transactions from a single sender kept in the
[layered transaction pool](../concepts/transactions/pool.md#layered-transaction-pool).
The default is `200`.
Increase this value to allow a single sender to fit more transactions in a single block.
For private networks, you can set this in the hundreds or thousands if you want to ensure
transactions with large nonce gaps remain in the transaction pool.
---
## `tx-pool-max-prioritized`
```bash
--tx-pool-max-prioritized=1500
```
```bash
BESU_TX_POOL_MAX_PRIORITIZED=1500
```
```bash
tx-pool-max-prioritized="1500"
```
The maximum number of transactions that are prioritized in the
[layered transaction pool](../concepts/transactions/pool.md#layered-transaction-pool).
The default is `2000`.
For private networks, we recommend setting this value to the maximum number of transactions that fit
in a block in your network.
---
## `tx-pool-max-prioritized-by-type`
```bash
--tx-pool-max-prioritized-by-type=["BLOB=6","FRONTIER=200"]
```
```bash
BESU_TX_POOL_MAX_PRIORITIZED_BY_TYPE=["BLOB=6","FRONTIER=200"]
```
```bash
tx-pool-max-prioritized-by-type=["BLOB=6","FRONTIER=200"]
```
The maximum number of transactions of a specific [transaction type](../concepts/transactions/types.md) that are prioritized in the [layered transaction pool](../concepts/transactions/pool.md#layered-transaction-pool).
This option is mostly useful for tuning the amount of prioritized [blob transactions](../concepts/transactions/types.md#blob-transactions) in the transaction pool.
Keeping the prioritized layer sorted is costly, and only a few blob transactions can fit in a block (currently a maximum of six).
Tuning the maximum number of prioritized transactions by type can help maintain the efficiency and performance of the transaction pool.
The default is `BLOB=6`.
---
## `tx-pool-max-size`
```bash
--tx-pool-max-size=2000
```
```bash
BESU_TX_POOL_MAX_SIZE=2000
```
```bash
tx-pool-max-size="2000"
```
The maximum number of transactions kept in the [transaction pool](../concepts/transactions/pool.md).
The default is `4096`.
:::caution
With the [layered transaction pool](../concepts/transactions/pool.md#layered-transaction-pool)
implementation, this option is not applicable because the layered pool is limited by memory size
instead of the number of transactions.
To configure the maximum memory capacity, use [`--tx-pool-layer-max-capacity`](#tx-pool-layer-max-capacity).
:::
---
## `tx-pool-min-gas-price`
```bash
--tx-pool-min-gas-price=2000
```
```bash
BESU_TX_POOL_MIN_GAS_PRICE=2000
```
```bash
tx-pool-min-gas-price="2000"
```
The minimum gas price, in wei, required for a transaction to be accepted into the [transaction pool](../concepts/transactions/pool.md).
---
## `tx-pool-min-score`
```bash
--tx-pool-min-score=-100
```
```bash
BESU_TX_POOL_MIN_SCORE=-100
```
```bash
tx-pool-min-score="-100"
```
Remove a pending transaction from the [layered transaction pool](../concepts/transactions/pool.md#penalize-transient-invalid-pending-transactions)
if its score is lower than this value. Accepts a value between `-128` and `127`.
The default is `-128`.
The lowest score a pending transaction can have is `-128`. The default value of `-128` means that pending
transactions will not be removed and will remain in the pool with the lowest score, being selected after
all other pending transactions.
---
## `tx-pool-no-local-priority`
```bash
--tx-pool-no-local-priority=true
```
```bash
BESU_TX_POOL_NO_LOCAL_PRIORITY=true
```
```bash
tx-pool-no-local-priority=true
```
If this option is set to `true`, senders of transactions submitted via RPC are *not* prioritized over
remote transactions in the [transaction pool](../concepts/transactions/pool.md).
The default is `false`.
---
## `tx-pool-price-bump`
```bash
--tx-pool-price-bump=25
```
```bash
BESU_TX_POOL_PRICE_BUMP=25
```
```bash
tx-pool-price-bump=25
```
The price bump percentage to
[replace an existing transaction in the transaction pool](../concepts/transactions/pool.md#replace-transactions-with-the-same-sender-and-nonce).
For networks with a [base fee and priced gas](../concepts/transactions/pool.md#in-networks-with-a-base-fee-and-priced-gas), the default is `10`, or 10%.
For networks with [zero base fee, or free gas](../concepts/transactions/pool.md#in-networks-with-zero-base-base-or-free-gas), the default is `0`.
---
## `tx-pool-priority-senders`
```bash
--tx-pool-priority-senders=0x13003d886a7be927d9451c27eb3bc8d3616e26e9
```
```bash
BESU_TX_POOL_PRIORITY_SENDERS=0x13003d886a7be927d9451c27eb3bc8d3616e26e9
```
```bash
tx-pool-priority-senders="0x13003d886a7be927d9451c27eb3bc8d3616e26e9"
```
A comma-separated list of sender addresses to prioritize in the [transaction pool](../concepts/transactions/pool.md).
Transactions sent from these addresses, from any source, are prioritized and only evicted after all others.
If not specified, only senders submitting transactions via RPC have priority (unless
[`--tx-pool-no-local-priority`](#tx-pool-no-local-priority) is set to `true`).
---
## `tx-pool-retention-hours`
```bash
--tx-pool-retention-hours=5
```
```bash
BESU_TX_POOL_RETENTION_HOURS=5
```
```bash
tx-pool-retention-hours=5
```
The maximum period (in hours) to hold pending transactions in the [transaction pool](../concepts/transactions/pool.md).
The default is `13`.
:::caution
With the [layered transaction pool](../concepts/transactions/pool.md#layered-transaction-pool)
implementation, this option is not applicable because old transactions will expire when the memory
cache is full.
:::
---
## `tx-pool-save-file`
```bash
--tx-pool-save-file=/home/me/me_node/node_txpool.dump
```
```bash
BESU_TX_POOL_SAVE_FILE=/home/me/me_node/node_txpool.dump
```
```bash
tx-pool-save-file="/home/me/me_node/node_txpool.dump"
```
The path to the file that stores the [transaction pool's](../concepts/transactions/pool.md)
content if the save and restore functionality is enabled using
[`--tx-pool-enable-save-restore`](#tx-pool-enable-save-restore).
The file is created on shutdown and reloaded during startup.
The default file name is `txpool.dump` in the [data directory](#data-path).
---
## `tx-sender-nonce-index-enabled`
```bash
--tx-sender-nonce-index-enabled=false
```
```bash
BESU_TX_SENDER_NONCE_INDEX_ENABLED=false
```
```bash
tx-sender-nonce-index-enabled=false
```
Enables or disables the sender and nonce index, which maps each sender address and nonce to a transaction hash.
This index is required for
[`eth_getTransactionBySenderAndNonce`](api/eth/transaction.md#eth_gettransactionbysenderandnonce)
to return transactions included in blocks.
The default is `true`.
:::note Storage impact
The index adds approximately 60 bytes per transaction.
If you upgrade Besu to enable this index without resyncing, the index is only populated for blocks processed after the upgrade.
Resyncing will index the full available transaction history.
Disabling this option for [archive nodes](../concepts/node-sync.md#archive-nodes) avoids the extra
storage cost in the case of a resync.
:::
---
## `version`
```bash
-V, --version
```
Prints version information and exits.
---
## `version-compatibility-protection`
```bash
--version-compatibility-protection=true
```
```bash
BESU_VERSION_COMPATIBILITY_PROTECTION=true
```
```bash
version-compatibility-protection=true
```
Enables or disables performing version compatibility checks when starting Besu.
If set to `true`, it checks that the version of Besu being started is the same
or later than the version of Besu that previously started with the same data directory.
The default is `false` for named networks, such as Mainnet or Sepolia, and `true`
for non-named networks.
---
## `Xhelp`
```bash
-X, --Xhelp
```
Displays the early access options and their descriptions, and exits.
:::caution
The displayed options are unstable and may change between releases.
:::
[push gateway integration]: ../how-to/monitor/metrics.md#run-prometheus-with-besu-in-push-mode
[JWT provider's public key file]: ../how-to/use-besu-api/authenticate.md#jwt-public-key-authentication
---
## Projects using Besu
This page highlights a selection of projects and organizations using Besu.
## Block explorers
The following block explorers are compatible with Besu:
- [Blockscout](https://github.com/blockscout/blockscout#readme) - Blockscout is an open-source block explorer
that supports networks running Besu.
See the [project documentation](https://docs.blockscout.com/) for setup instructions.
- [Chainlens Blockchain Explorer](https://www.web3labs.com/chainlens) - Chainlens is a block explorer and analytics
platform for public and private EVM networks.
You can include Chainlens when generating a Besu network using the Developer Quickstart.
See [how to use Chainlens](/private-networks/how-to/monitor/chainlens).
## Blockchains
The following EVM blockchains use Besu:
- [Hedera](https://hedera.com/) - Hedera nodes use the Besu EVM client library as an execution layer.
This was adopted in [HIP-26](https://hips.hedera.com/hip/hip-26).
See [Hyperledger Besu EVM on Hedera](https://docs.hedera.com/hedera/core-concepts/smart-contracts/deploying-smart-contracts#hyperledger-besu-evm-on-hedera)
for more information.
- [Linea](https://linea.build/) - Linea, a zkEVM Layer 2 network, uses Linea Besu, a Besu distribution with
Linea-specific plugins, as its execution client.
See the [Linea Besu node guide](https://docs.linea.build/network/how-to/run-a-node/linea-besu) for setup
instructions.
## Financial infrastructure
The following financial institutions and networks use Besu:
- [Swift](https://www.swift.com/) - Swift's blockchain-based shared ledger for 24/7 cross-border payments uses an
EVM-compatible architecture based on Besu.
See the
[Swift announcement](https://www.swift.com/news-events/news/swifts-blockchain-based-shared-ledger-progresses-mvp-implementation)
for more information.
- [Citi](https://www.citigroup.com/global/insights/citi-token-services-for-cash) - Citi uses Besu for its
Integrated Digital Assets Platform and Citi Token Services for Cash.
See the
[Citi case study](https://www.lfdecentralizedtrust.org/case-studies/citi-transforms-transaction-banking-services-with-besu)
from LF Decentralized Trust for more information.
- [DTCC](https://www.dtcc.com/) - DTCC's digital collateral management platform is built on Besu.
See the
[DTCC announcement](https://www.dtcc.com/news/2025/april/02/dtcc-announces-new-platform-for-tokenized-real-time-collateral-management)
for more information.
## Public-sector networks
The following government and public-sector blockchain networks use Besu:
- [EBSI (European Blockchain Services Infrastructure)](https://hub.ebsi.eu/) - The European Union's cross-border
infrastructure for public services is built using Besu.
See the
[EBSI case study](https://www.lfdecentralizedtrust.org/case-studies/establishing-a-new-foundation-for-trust-how-besu-helps-governments-meet-citizen-needs-while-rebuilding-credibility)
from LF Decentralized Trust for more information.
- [LACChain](https://www.lacchain.net/) - This permissioned public blockchain ecosystem for Latin America and the
Caribbean is built using Besu.
See the [LACChain case study](https://www.lfdecentralizedtrust.org/case-studies/lacchain-case-study) from LF
Decentralized Trust for more information.
- [Rede Blockchain Brasil (RBB)](https://redeblockchainbrasil.org/) - This national transparency initiative for
Brazil's public sector is built using Besu.
See the
[RBB case study](https://www.lfdecentralizedtrust.org/case-studies/establishing-a-new-foundation-for-trust-how-besu-helps-governments-meet-citizen-needs-while-rebuilding-credibility)
from LF Decentralized Trust for more information.
---
## Subcommands
This reference describes the syntax of the Besu subcommands.
Subcommands are part of the command line interface (CLI); run `besu --help` to display all subcommands and [options](options.md).
:::warning Important
This reference contains subcommands that apply to both public and private networks. For private-network-specific subcommands, see the [private network subcommands reference](../../private-networks/reference/subcommands.md).
:::
To start a Besu node using subcommands, run:
```bash
besu [OPTIONS] [SUBCOMMAND] [SUBCOMMAND OPTIONS]
```
If using Bash or Z shell, you can view subcommand suggestions by pressing the Tab key twice.
```bash
besu Tab+Tab
```
---
## `blocks`
Provides blocks related actions.
### `import`
```bash
besu blocks import [--skip-pow-validation-enabled] [--start-block=] [--end-block=] --from=
```
```bash
besu blocks import --skip-pow-validation-enabled --start-block=100 --end-block=300 --from=/home/me/me_project/mainnet-export1.blocks --from=/home/me/me_project/mainnet-export2.blocks
```
Imports a block or range of blocks from the specified file into the blockchain database.
You can specify the starting index of the block range to import with `--start-block`. If omitted, the default start block is 0 (the beginning of the chain).
You can specify the ending index (exclusive) of the block range to import with `--end-block`. If omitted, all blocks after the start block are imported.
You can specify multiple `--from` arguments. This can be useful when blocks have been exported over time to multiple files. If multiple files are provided they are read in the order specified in the command.
Including `--skip-pow-validation-enabled` skips validation of the `mixHash` when importing blocks.
:::note
Use `--skip-pow-validation-enabled` when performing [Ethereum Foundation hive testing](https://github.com/ethereum/hive).
:::
### `export`
```bash
besu blocks export [--start-block=] [--end-block=] --to=
```
```bash
besu --network=sepolia --data-path=/home/data/ blocks export --start-block=100 --end-block=300 --to=/home/exportblock.bin
```
Exports a block or range of blocks from storage to a file in RLP format.
If you omit `--start-block`, the default start block is 0 (the beginning of the chain), and if you omit `--end-block`, the default end block is the current chain head.
If you are not running the command against the default network (Mainnet), specify the `--network` or `--genesis-file` parameter.
---
## `operator`
Provides operator actions.
### `generate-log-bloom-cache`
```bash
besu operator generate-log-bloom-cache [--start-block=] [--end-block=]
```
```bash
besu --network=sepolia --data-path=/project/sepolia operator generate-log-bloom-cache --start-block=0 --end-block=100000
```
:::tip
Manually executing `generate-log-bloom-cache` is not required unless you set the [`--auto-log-bloom-caching-enabled`](options.md#auto-log-bloom-caching-enabled) command line option to false.
:::
Generates cached log bloom indexes for blocks. APIs use the cached indexes for improved log query performance.
:::note
Each index file contains 100000 blocks. The last fragment of blocks less that 100000 are not indexed.
:::
To generate cached log bloom indexes while the node is running, use the [`admin_generateLogBloomCache`](api/admin.md#admin_generatelogbloomcache) API.
---
## `password`
Provides password related actions.
### `hash`
```bash
besu password hash --password=
```
```bash
besu password hash --password=myPassword123
```
Generates the hash of a given password. Include the hash in the [credentials file](../how-to/use-besu-api/authenticate.md#1-create-the-credentials-file) for JSON-RPC API [authentication](../how-to/use-besu-api/authenticate.md).
---
## `public-key`
Provides node public key related actions.
:::caution
To get the public key or address of a node, ensure you use the [`--data-path`](options.md#data-path) or [`--node-private-key-file`](options.md#node-private-key-file) option with the `public-key` command. Otherwise, a new [node key](../concepts/node-keys.md) is silently generated when starting Besu.
:::
### `export`
```bash
besu public-key export [--node-private-key-file=] [--to=] [--ec-curve=]
```
```bash
besu --data-path= public-key export --node-private-key-file=/home/me/me_node/myPrivateKey --ec-curve=secp256k1
```
```bash
besu --data-path= public-key export --node-private-key-file=/home/me/me_node/myPrivateKey --to=/home/me/me_project/not_precious_pub_key --ec-curve=secp256k1
```
Outputs the node public key to standard output or to the file specified by `--to=`. You can output the public key associated with a specific private key file using the [`--node-private-key-file`](options.md#node-private-key-file) option. The default elliptic curve used for the key is `secp256k1`. Use the `--ec-curve` option to choose between `secp256k1` or `secp256r1`.
### `export-address`
```bash
besu public-key export-address [--node-private-key-file=] [--to=] [--ec-curve=]
```
```bash
besu --data-path= public-key export-address --node-private-key-file=/home/me/me_node/myPrivateKey --ec-curve=secp256k1
```
```bash
besu --data-path= public-key export-address --node-private-key-file=/home/me/me_node/myPrivateKey --to=/home/me/me_project/me_node_address --ec-curve=secp256k1
```
Outputs the node address to standard output or to the file specified by `--to=`. You can output the address associated with a specific private key file using the [`--node-private-key-file`](options.md#node-private-key-file) option. The default elliptic curve used for the key is `secp256k1`. Use the `--ec-curve` option to choose between `secp256k1` or `secp256r1`.
---
## `retesteth`
```bash
besu retesteth [--data-path=] [--rpc-http-host=] [--rpc-http-port=] [-l=] [--host-allowlist=[,…]… or * or all]
```
```bash
besu retesteth --data-path=/home/me/me_node --rpc-http-port=8590 --host-allowlist=*
```
Runs a Retesteth-compatible server. [Retesteth](https://github.com/ethereum/retesteth/wiki) is a developer tool that can generate and run consensus tests against any Ethereum client running such a server.
The command accepts the following command line options:
- [`--data-path`](options.md#data-path)
- [`--host-allowlist`](options.md#host-allowlist)
- [`--rpc-http-host`](options.md#rpc-http-host)
- [`--rpc-http-port`](options.md#rpc-http-port)
- [`--logging`](options.md#logging)
---
## `storage`
Provides storage related actions.
### `prune-pre-merge-blocks`
```bash
besu --data-path=/path/to/your/database storage prune-pre-merge-blocks [--prune-range-size=] [--threads=]
```
```bash
besu --data-path=/path/to/your/database storage prune-pre-merge-blocks --prune-range-size=5000 --threads=4
```
[Prunes all pre-merge Proof of Work blocks](../how-to/pre-merge-history-expiry.md#offline-pruning) and associated
transaction receipts, leaving only headers and genesis block.
Specify the size of the block ranges to prune with the `--prune-range-size` option. The default range is `10000`.
Specify the number of concurrent threads to use while pruning with the `--threads` option. The default is 1 less than
the total CPU count.
### `revert-metadata`
```bash
besu storage revert-metadata v2-to-v1
```
Reverts the modifications made by the [database metadata refactor](https://github.com/besu-eth/besu/pull/6555).
If you need to downgrade Besu, run this subcommand before installing the previous binaries.
### `revert-variables`
```bash
besu --config-file storage revert-variables
```
```bash
besu --config-file config.toml storage revert-variables
```
Reverts the modifications made by the [variables storage feature](https://github.com/besu-eth/besu/pull/5471).
If you need to downgrade Besu, first run this subcommand specifying the path to
the [configuration file](../how-to/configure-besu/index.md) normally used to
start Besu.
### `rocksdb usage`
```bash
besu --config-file storage rocksdb usage
```
```bash
besu --config-file config.toml storage rocksdb usage
```
```bash
|--------------------------------|-----------------|-------------|-----------------|------------------|
| Column Family | Keys | Total Size | SST Files Size | Blob Files Size |
|--------------------------------|-----------------|-------------|-----------------|------------------|
| BLOCKCHAIN | 2355141414 | 933 GiB | 166 GiB | 767 GiB |
| VARIABLES | 26 | 240 KiB | 240 KiB | 0 B |
| ACCOUNT_INFO_STATE | 9634454 | 496 MiB | 496 MiB | 0 B |
| ACCOUNT_STORAGE_STORAGE | 24041432 | 1 GiB | 1 GiB | 0 B |
| CODE_STORAGE | 37703864 | 12 GiB | 12 GiB | 0 B |
| TRIE_BRANCH_STORAGE | 1885032116 | 138 GiB | 138 GiB | 0 B |
| TRIE_LOG_STORAGE | 267301 | 17 GiB | 17 GiB | 0 B |
|--------------------------------|-----------------|-------------|-----------------|------------------|
| ESTIMATED TOTAL | 4311820607 | 1104 GiB | 337 GiB | 767 GiB |
|--------------------------------|-----------------|-------------|-----------------|------------------|
```
Displays the disk space used by the RocksDB key-value database, categorized into column families.
### `trie-log`
Provides actions related to managing, recording, and logging changes for the Bonsai Trie data.
#### `count`
```bash
besu --config-file storage trie-log count
```
```bash
besu --config-file config.toml storage trie-log count
```
```bash
trieLog count: 742311
- canonical count: 681039
- fork count: 217
- orphaned count: 61055
```
Displays the number of trie logs in the database.
This is the number of keys for the `TRIE_LOG_STORAGE` [column family in RocksDB](#rocksdb-usage).
The following are specified in the `trieLog count`:
- `canonical count` represents the finalized blockchain.
- `fork count` represents non-finalized branches of the blockchain.
- `orphaned count` represents trie logs not in the blockchain, which can occur during block creation.
#### `prune`
```bash
besu --config-file storage trie-log prune
```
```bash
besu --config-file config.toml storage trie-log prune
```
```bash
besu --config-file config.toml --bonsai-historical-block-limit=1024 storage trie-log prune
```
Removes all trie log layers below the specified retention limit, including orphaned trie logs.
You can configure the retention limit using [`--bonsai-historical-block-limit`](options.md#bonsai-historical-block-limit).
The retention limit should match the configuration used with [`--bonsai-limit-trie-logs-enabled`](options.md#bonsai-limit-trie-logs-enabled).
The default limit is `512`.
#### `export`
```bash
besu --config-file storage trie-log export [--trie-log-block-hash=] [--trie-log-file-path=]
```
```bash
besu --config-file config.toml storage trie-log export --trie-log-block-hash=0x0dcfa528de7d12df63673d0ebbd103dbf3a9464fae7eeb89e0934678cd05d64b
```
:::note
This example exports the trie log corresponding to a particular block hash into a file in the default location, `/trie-logs.bin`.
:::
```bash
besu --config-file config.toml storage trie-log export --trie-log-file-path=/tmp/list_of_trielogs.bin --trie-log-block-hash=0x0dcfa528de7d12df63673d0ebbd103dbf3a9464fae7eeb89e0934678cd05d64b,0xe8c3e77a6eaf6c87552aee07b86ecf4aacba43650b1d6aac32a44fa3ca97780d,0x86df7008b32fee67baac103846931c58454fc1b391e7d826c4886ba8580ba169
```
:::note
This example exports trie logs corresponding to a list of block hashes into a specific file location.
:::
Exports the trie logs of blocks specified by hash to a binary file.
By default, Bonsai trie logs are regularly pruned, so the trie log for a given block might not be present if it has been pruned.
If you need to manually import or export trie logs, we recommend temporarily disabling trie log pruning by setting
[`--bonsai-limit-trie-logs-enabled`](options.md#bonsai-limit-trie-logs-enabled) to `false`.
#### `import`
```bash
besu --config-file storage trie-log import [--trie-log-file-path=]
```
```bash
besu --config-file config.toml storage trie-log import --trie-log-file-path=/tmp/list_of_trielogs.bin
```
Imports trie logs from a binary trie log export file.
By default, Bonsai trie logs are regularly pruned.
If pruning is enabled, Besu might subsequently prune the imported trie logs.
If you need to manually import or export trie logs, we recommend temporarily disabling trie log pruning by setting
[`--bonsai-limit-trie-logs-enabled`](options.md#bonsai-limit-trie-logs-enabled) to `false`.
---
## `validate-config`
```bash
besu validate-config --config-file
```
```bash
besu validate-config --config-file config.toml
```
Performs basic syntax validation of the specified [configuration file](../how-to/configure-besu/index.md). Checks TOML syntax (for example, valid format and unmatched quotes) and flags unknown options. Doesn't check data types, and doesn't check dependencies between options (this is done at Besu startup).
---
## Deploy AWS Node Runners
[AWS Blockchain Node Runners](https://aws-samples.github.io/aws-blockchain-node-runners/docs/intro)
is an open-source initiative aimed at simplifying the deployment of self-managed blockchain nodes
on AWS using vetted deployment blueprints and infrastructure configurations.
AWS Node Runners solves common challenges in architecting and deploying blockchain nodes on AWS,
helping users identify optimal configurations for specific protocol clients.
This page walks you through the AWS Node Runners [architecture](#architecture), and how to
[deploy Besu and Teku on AWS](#deploy-besu-and-teku-on-aws).
## Architecture
AWS Blockchain Node Runners supports several Ethereum client combinations and offers two
configuration options: a single node setup for development environments, and a highly available
multi-node setup for production environments.
The following diagrams illustrate the high level architecture of these setups.
### Single RPC node setup

This single node setup is for small-scale development environments.
It deploys a single EC2 instance with both consensus and execution clients.
The RPC port is exposed only to the internal IP range of the VPC, while P2P ports allow external access to keep the clients synced.
### Highly available setup

In this highly available, multiple node setup:
1. The sync node synchronizes data continuously with the Ethereum network.
1. The sync node copies node state data to an Amazon S3 bucket.
1. New RPC nodes copy state data from the Amazon S3 bucket to accelerate their initial sync.
1. The Application Load Balancer routes application and smart contract development tool requests to available RPC nodes.
### Architecture checklist
The following is a checklist for an implementation of the AWS Blockchain Node Runners.
This checklist takes into account questions from the [AWS Well-Architected framework](https://aws.amazon.com/architecture/well-architected/)
that are relevant to this workload.
You can add more checks from the framework if required for your workload.
Pillar
Control
Question/Check
Notes
Security
Network protection
Are there unnecessary open ports in security groups?
The Erigon snap sync port (`42069`) remains open for non-Erigon clients.
Traffic inspection
AWS WAF can be implemented for traffic inspection. Additional charges will apply.
Compute protection
Reduce attack surface
This solution uses Amazon Linux 2 AMI. You can run hardening scripts on it.
Enable users to perform actions at a distance
This solution uses AWS Systems Manager for terminal sessions, not SSH ports.
Data protection at rest
Use encrypted Amazon Elastic Block Store (Amazon EBS) volumes
This solution uses encrypted Amazon EBS volumes.
Use encrypted Amazon Simple Storage Service (Amazon S3) buckets
This solution uses Amazon S3 managed keys (SSE-S3) encryption.
Data protection in transit
Use TLS
The AWS Application Load Balancer currently uses an HTTP listener. To use TLS, create an HTTPS listener with a self-signed certificate.
Authorization and access control
Use instance profile with Amazon Elastic Compute Cloud (Amazon EC2) instances
This solution uses AWS Identity and Access Management (AWS IAM) role instead of IAM user.
Follow the principle of least privilege access
In the sync node, the root user is not used (it uses the special user `ethereum` instead).
Application security
Security-focused development practices
cdk-nag is used with appropriate suppressions.
Cost optimization
Use cost-effective resources
AWS Graviton-based Amazon EC2 instances are used, which are cost-effective compared to Intel/AMD instances.
Estimate costs
One sync node with m7g.2xlarge for geth-Lighthouse configuration (2048 GB SSD) will cost around $430 per month in the US East region. Additional charges apply if you deploy RPC nodes with a load balancer.
Reliability
Withstand component failures
This solution uses AWS Application Load Balancer with RPC nodes for high availability. If the sync node fails, Amazon S3 backup can be used to reinstate the nodes.
How is data backed up?
Data is backed up to Amazon S3 using the s5cmd tool.
How are workload resources monitored?
Resources are monitored using Amazon CloudWatch dashboards. Amazon CloudWatch custom metrics are pushed through CloudWatch Agent.
Performance efficiency
How is the compute solution selected?
The solution is selected based on best price-performance, that is, AWS Graviton-based Amazon EC2 instances.
How is the storage solution selected?
The solution is selected based on best price-performance, that is, gp3 Amazon EBS volumes with optimal IOPS and throughput.
How is the architecture selected?
The s5cmd tool is used for Amazon S3 uploads/downloads because it gives better price-performance compared to Amazon EBS snapshots.
Operational excellence
How is health of the workload determined?
Workload health is determined via AWS Application Load Balancer Target Group Health Checks, on port `8545`.
Sustainability
Select the most efficient hardware for your workload
This solution uses AWS Graviton-based Amazon EC2 instances, which offer the best performance per watt of energy use in Amazon EC2.
## Deploy Besu and Teku on AWS
:::note
In this guide, you'll set all major configuration through environment variables, but you can also
modify parameters in the `config/config.ts` file.
:::
### 1. Configure the AWS CloudShell
#### 1.1. Log into AWS
Log in to your [AWS account](https://aws.amazon.com/) with permissions to create and modify
resources in IAM, EC2, EBS, VPC, S3, KMS, and Secrets Manager.
From the AWS Management Console, open the [AWS CloudShell](https://docs.aws.amazon.com/cloudshell/latest/userguide/welcome.html),
a web-based shell environment.
For more information, see [this demo](https://youtu.be/fz4rbjRaiQM) on
[CloudShell with VPC environment](https://docs.aws.amazon.com/cloudshell/latest/userguide/creating-vpc-environment.html),
which you'll use to test APIs from an internal IP address space.
#### 1.2. Install dependencies
To deploy and test blueprints in the CloudShell, clone the following repository and install dependencies:
```bash
git clone https://github.com/aws-samples/aws-blockchain-node-runners.git
cd aws-blockchain-node-runners
npm install
```
### 2. Prepare to deploy nodes
In the root directory of your project:
1. If you have deleted or don't have the default VPC, create a default VPC:
```bash
aws ec2 create-default-vpc
```
:::note
You might see the following error if the default VPC already exists:
```bash
An error occurred (DefaultVpcAlreadyExists) when calling the CreateDefaultVpc operation: A Default VPC already exists for this account in this region.
```
This means that the default VPC must have at least two public subnets in different availability
zones, and public subnet must set `Auto-assign public IPv4 address` to `YES`.
:::
1. Configure your Node Runners Ethereum blueprint deployment.
To specify the Ethereum client combination you want to deploy, create your own copy of the `.env`
file and edit it using your preferred text editor.
The following example uses a sample configuration from the repository for a Besu and Teku node deployment:
```bash
# Ensure you're in aws-blockchain-node-runners/lib/ethereum
cd lib/ethereum
pwd
cp ./sample-configs/.env-besu-teku .env
nano .env
```
:::note
You can find more examples for other Ethereum client combinations in the `sample-configs` directory.
:::
1. Deploy common components, such as IAM role and Amazon S3 bucket to store data snapshots:
```bash
pwd
# Ensure you're in aws-blockchain-node-runners/lib/ethereum
npx cdk deploy eth-common
```
### 3. Deploy nodes
Deploy your node or nodes, depending on your setup:
- [Single RPC node](#31-option-1-single-rpc-node)
- [Highly available RPC nodes](#32-option-2-highly-available-rpc-nodes)
#### 3.1. (Option 1) Single RPC node
In a single RPC node setup:
1. Deploy the node:
```bash
pwd
# Ensure you're in aws-blockchain-node-runners/lib/ethereum
npx cdk deploy eth-single-node --json --outputs-file single-node-deploy.json
```
:::note
The default VPC must have at least two public subnets in different Availability Zones, and the
public subnets must set `Auto-assign public IPv4 address` to `YES`.
:::
1. After starting the node, wait for the initial synchronization process to finish.
It can take half a day to approximately 6-10 days, depending on the client combination and
the network state.
You can use Amazon CloudWatch to track the progress, which publishes metrics every five minutes.
Watch `sync distance` for the consensus client, and `blocks behind` for the execution client.
When the node is fully synced, those two metrics should be `0`.
To see them:
- Navigate to [CloudWatch service](https://console.aws.amazon.com/cloudwatch/) (ensure you're
in the region you specified for `AWS_REGION`).
- Open `Dashboards` and select `eth-sync-node-` from the list of dashboards.
1. Once the initial synchronization is done, you can access the RPC API of that node from within the
same VPC.
The RPC port is not exposed to the Internet.
Run the following query against the private IP of the single RPC node you deployed:
```bash
INSTANCE_ID=$(cat single-node-deploy.json | jq -r '..|.node-instance-id? | select(. != null)')
NODE_INTERNAL_IP=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID --query 'Reservations[*].Instances[*].PrivateIpAddress' --output text)
echo "NODE_INTERNAL_IP=$NODE_INTERNAL_IP"
```
Copy the output from the last `echo` command with `NODE_INTERNAL_IP=` and open
[CloudShell tab with VPC environment](https://docs.aws.amazon.com/cloudshell/latest/userguide/creating-vpc-environment.html)
to access the internal IP address space.
Paste `NODE_INTERNAL_IP=` into the new CloudShell tab.
Then, query the API:
``` bash
# IMPORTANT: Run from CloudShell VPC environment tab
# This queries the token balance of a Beacon deposit contract: https://etherscan.io/address/0x00000000219ab540356cbb839cbe05303d7705fa
curl http://$NODE_INTERNAL_IP:8545 -X POST -H "Content-Type: application/json" \
--data '{"method":"eth_getBalance","params":["0x00000000219ab540356cBB839Cbe05303d7705Fa", "latest"],"id":1,"jsonrpc":"2.0"}'
```
The result should look like the following (the actual balance might change):
```javascript
{"jsonrpc":"2.0","id":1,"result":"0xe791d050f91d9949d344d"}
```
#### 3.2. (Option 2) Highly available RPC nodes
In a highly available multi-node setup:
1. Deploy the sync node:
```bash
pwd
# Ensure you're in aws-blockchain-node-runners/lib/ethereum
npx cdk deploy eth-sync-node --json --outputs-file sync-node-deploy.json
```
:::note
The default VPC must have at least two public subnets in different Availability Zones, and the
public subnets must set `Auto-assign public IPv4 address` to `YES`.
:::
1. After starting the node, wait for the initial synchronization process to finish.
It can take from half a day to approximately 6-10 days, depending on the client combination and
the network state.
You can use Amazon CloudWatch to track the progress, which publishes metrics every five minutes.
Watch `sync distance` for the consensus client, and `blocks behind` for the execution client.
When the node is fully synced, those two metrics should be `0`.
To see them:
- Navigate to [CloudWatch service](https://console.aws.amazon.com/cloudwatch/) (make sure you are
in the region you have specified for `AWS_REGION`).
- Open `Dashboards` and select `eth-sync-node-` from the list of dashboards.
Once the synchronization process is over, the script automatically stops both clients and copies
all the contents of the `/data` directory to your snapshot S3 bucket.
That can take from 30 minutes to approximately 2 hours.
During the process, you will see lower CPU and RAM usage, but high data disc throughput and
outbound network traffic.
The script automatically starts the clients after the process is done.
:::note
The snapshot backup process automatically runs every day at midnight of the time zone were the
sync node runs.
To change the schedule, modify `crontab` of the root user on the node's EC2 instance.
:::
1. Configure and deploy two RPC nodes:
```bash
pwd
# Ensure you're in aws-blockchain-node-runners/lib/ethereum
npx cdk deploy eth-rpc-nodes --json --outputs-file rpc-node-deploy.json
```
1. Give the new RPC nodes approximately 30 minutes to initialize, then run the following query
against the load balancer behind the RPC node created:
```bash
export ETH_RPC_ABL_URL=$(cat rpc-node-deploy.json | jq -r '..|.alburl? | select(. != null)')
echo ETH_RPC_ABL_URL=$ETH_RPC_ABL_URL
```
```bash
# IMPORTANT: Run from CloudShell VPC environment tab
# We query token balance of Beacon deposit contract: https://etherscan.io/address/0x00000000219ab540356cbb839cbe05303d7705fa
curl http://$ETH_RPC_ABL_URL:8545 -X POST -H "Content-Type: application/json" \
--data '{"method":"eth_getBalance","params":["0x00000000219ab540356cBB839Cbe05303d7705Fa", "latest"],"id":1,"jsonrpc":"2.0"}'
```
The result should look like the following (the actual balance might change):
```javascript
{"jsonrpc":"2.0","id":1,"result":"0xe791d050f91d9949d344d"}
```
If the nodes are still starting and catching up with the chain, you will see the following response:
```HTML
503 Service Temporarily Unavailable
503 Service Temporarily Unavailable
```
:::note
By default and for security reasons, the load balancer is available only from within the default
VPC in the region where it is deployed.
It is not available from the Internet and is not open for external connections.
Before opening it up, protect your RPC APIs.
:::
### 4. Clear and undeploy nodes
To clear and undeploy the RPC nodes, sync nodes, and common components, use the following commands:
```bash
# Set the AWS account ID and region in case the local .env file is lost.
export AWS_ACCOUNT_ID=
export AWS_REGION=
pwd
# Ensure you're in aws-blockchain-node-runners/lib/ethereum.
# Destroy the single RPC node.
cdk destroy eth-single-node
# Destroy multiple RPC nodes.
cdk destroy eth-rpc-nodes
# Destroy the sync node.
cdk destroy eth-sync-node
# You need to manually delete an s3 bucket with a name similar to 'eth-snapshots-$accountid-eth-nodes-common'
# on the console:
# 1. Empty the bucket
# 2. Delete the bucket
# 3. Execute and delete all common components like IAM role and Security Group
cdk destroy eth-common
```
---
## Run Besu and Teku on Mainnet
Run Besu as an [execution client](../concepts/node-clients.md#execution-clients) and [Teku](https://docs.teku.consensys.net/) as a [consensus client](../concepts/node-clients.md#consensus-clients) on Ethereum Mainnet.
## 1. Install Besu and Teku
Install [Besu](../get-started/install/binary-distribution.md) and [Teku](https://docs.teku.consensys.net/HowTo/Get-Started/Installation-Options/Install-Binaries/).
Ensure you meet the prerequisites for the installation option you use. For example, you must have Java 25+ if using the Besu and Teku binary distributions.
Ensure you meet the [system requirements for Besu on public networks](../get-started/system-requirements.md).
## 2. Generate the shared secret
Run the following command:
```bash
openssl rand -hex 32 | tr -d "\n" > jwtsecret.hex
```
You will specify `jwtsecret.hex` when starting Besu and Teku. This is a shared JWT secret the clients use to authenticate each other when using the [Engine API](../how-to/use-engine-api.md).
## 3. Generate validator keys
If you're running Teku as a beacon node only, skip to the [next step](#4-start-besu).
If you're also running Teku as a validator client, have a funded Ethereum address ready (32 ETH and gas fees for each validator).
Generate validator keys and stake your ETH for one or more validators using the [Staking Launchpad](https://launchpad.ethereum.org/en/).
:::info
Save the password you use to generate each key pair in a `.txt` file.
You should also have a `.json` file for each validator key pair.
:::
## 4. Start Besu
Run the following command or specify the options in a [configuration file](../how-to/configure-besu/index.md):
```bash
besu \
--sync-mode=SNAP \
--data-storage-format=BONSAI \
--rpc-http-enabled=true \
--p2p-host= \
--host-allowlist=,127.0.0.1,localhost \
--engine-host-allowlist=,127.0.0.1,localhost \
--engine-rpc-enabled \
--engine-jwt-secret=
```
Specify:
- The path to the `jwtsecret.hex` file generated in [step 2](#2-generate-the-shared-secret) using the [`--engine-jwt-secret`](../reference/options.md#engine-jwt-secret) option.
- The public IP address of your Besu node using the [`--host-allowlist`](../reference/options.md#host-allowlist) and [`--engine-host-allowlist`](../reference/options.md#engine-host-allowlist) options.
Also, in the command:
- [`--sync-mode`](../reference/options.md#sync-mode) specifies using [snap sync](../concepts/node-sync.md#snap-synchronization).
- [`--data-storage-format`](../reference/options.md#data-storage-format) specifies using [Bonsai Tries](../concepts/data-storage-formats.md#bonsai-tries).
- [`--rpc-http-enabled`](../reference/options.md#rpc-http-enabled) enables the HTTP JSON-RPC service.
- [`--engine-rpc-enabled`](../reference/options.md#engine-rpc-enabled) enables the [Engine API](../reference/engine-api.md).
You can modify the option values and add other [command line options](../reference/options.md) as needed.
## 5. Start Teku
Open a new terminal window.
### Beacon node only
To run Teku as a beacon node only (without validator duties), run the following command or specify the options in the [Teku configuration file]:
```bash
teku \
--ee-endpoint=http://localhost:8551 \
--ee-jwt-secret-file= \
--metrics-enabled=true \
--rest-api-enabled=true \
--p2p-advertised-ip= \
--checkpoint-sync-url=
```
Specify:
- The path to the `jwtsecret.hex` file generated in [step 2](#2-generate-the-shared-secret) using the
[`--ee-jwt-secret-file`](https://docs.teku.consensys.io/reference/cli#ee-jwt-secret-file) option.
- The public IP address of your Teku node using the
[`--p2p-advertised-ip`](https://docs.teku.consensys.io/reference/cli#p2p-advertised-ip) option.
- The URL of a checkpoint sync endpoint using the
[`--checkpoint-sync-url`](https://docs.teku.consensys.io/reference/cli#checkpoint-sync-url) option.
Also, in the command:
- [`--ee-endpoint`](https://docs.teku.consensys.io/reference/cli#ee-endpoint) is set to the default URL of Besu's Engine API.
- [`--metrics-enabled`](https://docs.teku.consensys.io/reference/cli#metrics-enabled) enables Teku's metrics exporter.
- [`--rest-api-enabled`](https://docs.teku.consensys.io/reference/cli#rest-api-enabled) enables Teku's REST API service.
You can modify the option values and add other [Teku command line options] as needed.
### Beacon node and validator client
To run Teku as a beacon node and validator in a single process, run the following command or specify the options in the [Teku configuration file]:
```bash
teku \
--ee-endpoint http://localhost:8551 \
--ee-jwt-secret-file \
--metrics-enabled=true \
--rest-api-enabled=true \
--checkpoint-sync-url= \
--validators-proposer-default-fee-recipient= \
--validator-keys=:[,:,...]
```
Specify:
- The path to the `jwtsecret.hex` file generated in [step 2](#2-generate-the-shared-secret) using the
[`--ee-jwt-secret-file`](https://docs.teku.consensys.io/reference/cli#ee-jwt-secret-file) option.
- The URL of a checkpoint sync endpoint using the
[`--checkpoint-sync-url`](https://docs.teku.consensys.io/reference/cli#checkpoint-sync-url) option.
- An Ethereum address you own as the default fee recipient using the
[`--validators-proposer-default-fee-recipient`](https://docs.teku.consensys.io/reference/cli#validators-proposer-default-fee-recipient)
option.
- The paths to the keystore `.json` file and password `.txt` file created in
[step 3](#3-generate-validator-keys) for each validator using the
[`--validator-keys`](https://docs.teku.consensys.io/reference/cli#validator-keys) option.
Separate the `.json` and `.txt` files with a colon, and separate entries for multiple validators with commas.
Also, in the command:
- [`--ee-endpoint`](https://docs.teku.consensys.io/reference/cli#ee-endpoint) is set to the default URL of Besu's Engine API.
- [`--metrics-enabled`](https://docs.teku.consensys.io/reference/cli#metrics-enabled) enables Teku's metrics exporter.
- [`--rest-api-enabled`](https://docs.teku.consensys.io/reference/cli#rest-api-enabled) enables Teku's REST API service.
You can modify the option values and add other [Teku command line options] as needed.
## 6. Wait for Besu and Teku to sync
After starting Besu and Teku, your node starts syncing and connecting to peers.
```json
{"@timestamp":"2023-02-03T04:43:49,555","level":"INFO","thread":"main","class":"DefaultSynchronizer","message":"Starting synchronizer.","throwable":""}
{"@timestamp":"2023-02-03T04:43:49,556","level":"INFO","thread":"main","class":"FastSyncDownloader","message":"Starting sync","throwable":""}
{"@timestamp":"2023-02-03T04:43:49,559","level":"INFO","thread":"main","class":"Runner","message":"Ethereum main loop is up.","throwable":""}
{"@timestamp":"2023-02-03T04:43:53,106","level":"INFO","thread":"Timer-0","class":"DNSResolver","message":"Resolved 2409 nodes","throwable":""}
{"@timestamp":"2023-02-03T04:45:04,803","level":"INFO","thread":"nioEventLoopGroup-3-10","class":"SnapWorldStateDownloader","message":"Downloading world state from peers for pivot block 16545859 (0x616ae3c4cf85f95a9bce2814a7282d75dc2eac36
cb9f0fcc6f16386df70da3c5). State root 0xa7114541f42c62a72c8b6bb9901c2ccf4b424cd7f76570a67b82a183b02f25dc pending requests 0","throwable":""}
{"@timestamp":"2023-02-03T04:46:04,834","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.08%, Peer count: 8","throwable":""}
{"@timestamp":"2023-02-03T04:48:01,840","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.23%, Peer count: 8","throwable":""}
{"@timestamp":"2023-02-03T04:49:09,931","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.41%, Peer count: 11","throwable":""}
{"@timestamp":"2023-02-03T04:50:12,466","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.61%, Peer count: 10","throwable":""}
{"@timestamp":"2023-02-03T04:51:20,977","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.75%, Peer count: 10","throwable":""}
{"@timestamp":"2023-02-03T04:51:28,985","level":"INFO","thread":"EthScheduler-Services-29 (importBlock)","class":"FastImportBlocksStep","message":"Block import progress: 180400 of 16545859 (1%)","throwable":""}
```
```bash
2022-03-21 20:43:24.355 INFO - Syncing *** Target slot: 76092, Head slot: 2680, Remaining slots: 73412, Connected peers: 8
2022-03-21 20:43:36.363 INFO - Syncing *** Target slot: 76093, Head slot: 2879, Remaining slots: 73214, Connected peers: 10
2022-03-21 20:43:48.327 INFO - Syncing *** Target slot: 76094, Head slot: 3080, Remaining slots: 73014, Connected peers: 8
2022-03-21 20:44:00.339 INFO - Syncing *** Target slot: 76095, Head slot: 3317, Remaining slots: 72778, Connected peers: 6
2022-03-21 20:44:12.353 INFO - Syncing *** Target slot: 76096, Head slot: 3519, Remaining slots: 72577, Connected peers: 9
```
If you're running Teku as a beacon node only, you're all set. If you're also running Teku as a validator client, ensure Besu and Teku are fully synced before submitting your staking deposit in the next step. Syncing Besu can take several days.
## 7. Stake ETH
Stake your ETH for one or more validators using the [Staking Launchpad](https://launchpad.ethereum.org/en/).
You can check your validator status by searching your Ethereum address on the [Beacon Chain explorer](https://beaconcha.in/). It may take up to multiple days for your validator to be activated and start proposing blocks.
[Teku configuration file]: https://docs.teku.consensys.net/HowTo/Configure/Use-Configuration-File/
[Teku command line options]: https://docs.teku.consensys.net/Reference/CLI/CLI-Syntax/
---
## Run Besu and Teku on a testnet
Run Besu as an [execution client](../concepts/node-clients.md#execution-clients) and [Teku](https://docs.teku.consensys.net/) as a [consensus client](../concepts/node-clients.md#consensus-clients) on the [Hoodi](https://github.com/eth-clients/hoodi), [Ephemery](https://github.com/ephemery-testnet/ephemery-resources), and [Sepolia](https://github.com/eth-clients/sepolia) Ethereum testnets.
:::note
Sepolia is a permissioned network and you can't run a validator client on it without [requesting to become a validator](https://notes.ethereum.org/zvkfSmYnT0-uxwwEegbCqg) first. You can connect your consensus client using the beacon node only, without any validator duties.
:::
## 1. Install Besu and Teku
Install [Besu](../get-started/install/binary-distribution.md) and [Teku](https://docs.teku.consensys.net/HowTo/Get-Started/Installation-Options/Install-Binaries/).
Ensure you meet the prerequisites for the installation option you use. For example, you must have Java 25+ if using the Besu and Teku binary distributions.
Ensure you meet the [system requirements for Besu on public networks](../get-started/system-requirements.md).
## 2. Generate the shared secret
Run the following command:
```bash
openssl rand -hex 32 | tr -d "\n" > jwtsecret.hex
```
You will specify `jwtsecret.hex` when starting Besu and Teku. This is a shared JWT secret the clients use to authenticate each other when using the [Engine API](../how-to/use-engine-api.md).
## 3. Generate validator keys
If you're running Teku as a beacon node only, skip to the [next step](#4-start-besu).
If you're also running Teku as a validator client, create a test Ethereum address (you can do this in [MetaMask](https://support.metamask.io/configure/accounts/how-to-add-accounts-in-your-wallet/)). Fund this address with testnet ETH (32 ETH and gas fees for each validator) using a faucet. See the faucets for the relevant testnet:
- [Hoodi](https://github.com/eth-clients/hoodi)
- [Sepolia](https://github.com/eth-clients/sepolia)
- [Ephemery](https://ephemery-faucet.pk910.de/)
:::note
If you can't get ETH using the faucet, you can ask for help on the [EthStaker Discord](https://discord.com/invite/ethstaker).
:::
Generate validator keys for one or more validators using the [Hoodi Staking Launchpad](https://hoodi.launchpad.ethereum.org/), [Ephemery Staking Launchpad](https://launchpad.ephemery.dev/)
(or [request to become validator on Sepolia](https://notes.ethereum.org/zvkfSmYnT0-uxwwEegbCqg)).
:::info
Save the password you use to generate each key pair in a `.txt` file. You should also have a `.json` file for each validator key pair.
:::
## 4. Start Besu
Run the following command or specify the options in a [configuration file](../how-to/configure-besu/index.md):
```bash
besu \
--network=hoodi \
--rpc-http-enabled=true \
--rpc-http-cors-origins="*" \
--rpc-ws-enabled=true \
--p2p-host= \
--host-allowlist="*" \
--engine-host-allowlist="*" \
--engine-rpc-enabled \
--engine-jwt-secret=
```
```bash
besu \
--network=sepolia \
--rpc-http-enabled=true \
--rpc-http-cors-origins="*" \
--rpc-ws-enabled=true \
--p2p-host= \
--host-allowlist="*" \
--engine-host-allowlist="*" \
--engine-rpc-enabled \
--engine-jwt-secret=
```
```bash
besu \
--network=ephemery \
--rpc-http-enabled=true \
--rpc-http-cors-origins="*" \
--rpc-ws-enabled=true \
--p2p-host= \
--host-allowlist="*" \
--engine-host-allowlist="*" \
--engine-rpc-enabled \
--engine-jwt-secret=
```
Specify the path to the `jwtsecret.hex` file generated in [step 2](#2-generate-the-shared-secret) using the [`--engine-jwt-secret`](../reference/options.md#engine-jwt-secret) option.
You can modify the option values and add other [command line options](../reference/options.md) as needed.
## 5. Start Teku
Open a new terminal window.
### Beacon node only
To run Teku as a beacon node only (without validator duties), run the following command or specify the options in the [Teku configuration file]:
```bash
teku \
--network=hoodi \
--ee-endpoint=http://localhost:8551 \
--ee-jwt-secret-file= \
--metrics-enabled=true \
--rest-api-enabled=true \
--p2p-advertised-ip= \
--checkpoint-sync-url=
```
```bash
teku \
--network=sepolia \
--ee-endpoint=http://localhost:8551 \
--ee-jwt-secret-file= \
--metrics-enabled=true \
--rest-api-enabled=true \
--p2p-advertised-ip= \
--checkpoint-sync-url=
```
```bash
teku \
--network=ephemery \
--ee-endpoint=http://localhost:8551 \
--ee-jwt-secret-file= \
--metrics-enabled=true \
--rest-api-enabled=true \
--p2p-advertised-ip= \
--checkpoint-sync-url=
```
Specify:
- The path to the `jwtsecret.hex` file generated in [step 2](#2-generate-the-shared-secret) using the
[`--ee-jwt-secret-file`](https://docs.teku.consensys.io/reference/cli#ee-jwt-secret-file) option.
- The public IP address of your Teku node using the
[`--p2p-advertised-ip`](https://docs.teku.consensys.io/reference/cli#p2p-advertised-ip) option.
- The URL of a checkpoint sync endpoint using the
[`--checkpoint-sync-url`](https://docs.teku.consensys.io/reference/cli#checkpoint-sync-url) option.
You can modify the option values and add other [Teku command line options] as needed.
### Beacon node and validator client
To run Teku as a beacon node and validator in a single process, run the following command or specify the options in the [Teku configuration file]:
```bash
teku \
--network=hoodi \
--ee-endpoint=http://localhost:8551 \
--ee-jwt-secret-file= \
--metrics-enabled=true \
--rest-api-enabled=true \
--p2p-advertised-ip= \
--checkpoint-sync-url= \
--validators-proposer-default-fee-recipient= \
--validator-keys=:[,:,...]
```
Sepolia is a permissioned network and you can't run a validator client on it without [requesting to become a validator](https://notes.ethereum.org/zvkfSmYnT0-uxwwEegbCqg) first.
Specify:
- The path to the `jwtsecret.hex` file generated in [step 2](#2-generate-the-shared-secret) using the
[`--ee-jwt-secret-file`](https://docs.teku.consensys.io/reference/cli#ee-jwt-secret-file) option.
- The public IP address of your Teku node using the
[`--p2p-advertised-ip`](https://docs.teku.consensys.io/reference/cli#p2p-advertised-ip) option.
- The URL of a checkpoint sync endpoint using the
[`--checkpoint-sync-url`](https://docs.teku.consensys.io/reference/cli#checkpoint-sync-url) option.
- The test Ethereum address created in [step 3](#3-generate-validator-keys) as the default fee
recipient using the
[`--validators-proposer-default-fee-recipient`](https://docs.teku.consensys.io/reference/cli#validators-proposer-default-fee-recipient)
option.
- The paths to the keystore `.json` file and password `.txt` file created in
[step 3](#3-generate-validator-keys) for each validator using the
[`--validator-keys`](https://docs.teku.consensys.io/reference/cli#validator-keys) option.
Separate the `.json` and `.txt` files with a colon, and separate entries for multiple validators with commas.
You can modify the option values and add other [Teku command line options] as needed.
## 6. Wait for Besu and Teku to sync
After starting Besu and Teku, your node starts syncing and connecting to peers.
```json
{"@timestamp":"2023-02-03T04:43:49,555","level":"INFO","thread":"main","class":"DefaultSynchronizer","message":"Starting synchronizer.","throwable":""}
{"@timestamp":"2023-02-03T04:43:49,556","level":"INFO","thread":"main","class":"FastSyncDownloader","message":"Starting sync","throwable":""}
{"@timestamp":"2023-02-03T04:43:49,559","level":"INFO","thread":"main","class":"Runner","message":"Ethereum main loop is up.","throwable":""}
{"@timestamp":"2023-02-03T04:43:53,106","level":"INFO","thread":"Timer-0","class":"DNSResolver","message":"Resolved 2409 nodes","throwable":""}
{"@timestamp":"2023-02-03T04:45:04,803","level":"INFO","thread":"nioEventLoopGroup-3-10","class":"SnapWorldStateDownloader","message":"Downloading world state from peers for pivot block 16545859 (0x616ae3c4cf85f95a9bce2814a7282d75dc2eac36
cb9f0fcc6f16386df70da3c5). State root 0xa7114541f42c62a72c8b6bb9901c2ccf4b424cd7f76570a67b82a183b02f25dc pending requests 0","throwable":""}
{"@timestamp":"2023-02-03T04:46:04,834","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.08%, Peer count: 8","throwable":""}
{"@timestamp":"2023-02-03T04:48:01,840","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.23%, Peer count: 8","throwable":""}
{"@timestamp":"2023-02-03T04:49:09,931","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.41%, Peer count: 11","throwable":""}
{"@timestamp":"2023-02-03T04:50:12,466","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.61%, Peer count: 10","throwable":""}
{"@timestamp":"2023-02-03T04:51:20,977","level":"INFO","thread":"EthScheduler-Services-3 (batchPersistAccountData)","class":"SnapsyncMetricsManager","message":"Worldstate download progress: 0.75%, Peer count: 10","throwable":""}
{"@timestamp":"2023-02-03T04:51:28,985","level":"INFO","thread":"EthScheduler-Services-29 (importBlock)","class":"FastImportBlocksStep","message":"Block import progress: 180400 of 16545859 (1%)","throwable":""}
```
```bash
2022-03-21 20:43:24.355 INFO - Syncing *** Target slot: 76092, Head slot: 2680, Remaining slots: 73412, Connected peers: 8
2022-03-21 20:43:36.363 INFO - Syncing *** Target slot: 76093, Head slot: 2879, Remaining slots: 73214, Connected peers: 10
2022-03-21 20:43:48.327 INFO - Syncing *** Target slot: 76094, Head slot: 3080, Remaining slots: 73014, Connected peers: 8
2022-03-21 20:44:00.339 INFO - Syncing *** Target slot: 76095, Head slot: 3317, Remaining slots: 72778, Connected peers: 6
2022-03-21 20:44:12.353 INFO - Syncing *** Target slot: 76096, Head slot: 3519, Remaining slots: 72577, Connected peers: 9
```
If you're running Teku as a beacon node only, you're all set. If you're also running Teku as a validator client, ensure Besu and Teku are fully synced before submitting your staking deposit in the next step. Syncing Besu can take several days.
## 7. Stake ETH
Stake your testnet ETH for one or more validators using the
[Hoodi Staking Launchpad](https://hoodi.launchpad.ethereum.org/) or
[Ephemery Staking Launchpad](https://launchpad.ephemery.dev/).
You can check your validator status by searching your Ethereum address on the
[Hoodi explorer](https://hoodi.etherscan.io/) or
[Ephemery explorer](https://explorer.ephemery.dev/). It may take up to multiple days
for your validator to be activated and start proposing blocks.
[Teku configuration file]: https://docs.teku.consensys.net/HowTo/Configure/Use-Configuration-File/
[Teku command line options]: https://docs.teku.consensys.net/Reference/CLI/CLI-Syntax/
---
## Deploy Besu using Kubernetes
# Deploy a Besu public node using Kubernetes
You can use a cloud provider such as [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/)
or [Azure Kubernetes Service (AKS)](https://azure.microsoft.com/en-au/products/kubernetes-service) to deploy
a Besu public node
This tutorial walks you through adding an extra node group to your Besu pod.
## AWS EKS
### Prerequisites
Set up a Kubernetes cluster using a managed Kubernetes service such as
[Amazon EKS](https://aws.amazon.com/eks/).
### Steps
#### 1. Create a security group for discovery
Create a security group in your VPC that allows traffic from anywhere on ports `30303` and `9000`
(or equivalent ports that you are using for discovery).
##### Outbound rules
| Type | Protocol | Port range | Destination |
|-------------|----------|------------|-------------|
| All traffic | All | All | `0.0.0.0/0` |
| All traffic | All | All | `::/0` |
#### Inbound rules
| Type | Protocol | Port range | Destination | Description |
|------------|----------|------------|-------------|-------------|
| Custom UDP | UDP | `9000` | `0.0.0.0/0` | CL client |
| Custom TCP | TCP | `9000` | `0.0.0.0/0` | CL client |
| Custom UDP | UDP | `30303` | `0.0.0.0/0` | EL client |
| Custom TCP | TCP | `30303` | `0.0.0.0/0` | EL client |
:::warning important
The key here is to allow traffic on both TCP and UDP for the consensus layer client and the
execution layer client.
:::
#### 2. Add a node group to your cluster
In your VPC settings, enable **Auto-assign public IPv4 address** on the public subnets on which you
spin up your nodes.
This allows you to isolate your Besu node on a public subnet and separate it from the other apps and
node groups you might have running.
If you are using [EKSCTL](https://eksctl.io/), add the following snippet to your setup:
```yaml
managedNodeGroups:
- name: ng-ethereum
instanceType: m6a.xlarge
desiredCapacity: 1 # Increase this capacity if you need more nodes.
subnets:
- public-subnet-id1
- public-subnet-id2
- public-subnet-id3
labels: { "ng": "ethereum" }
securityGroups:
attachIDs: ["sg-1234..."] # The ID of the security group from the previous step.
iam:
withAddonPolicies:
ebs: true
# efs: true
taints:
- key: ethereum
value: "true"
effect: NoSchedule
- key: ethereum
value: "true"
effect: NoExecute
```
If you are using [Terraform](https://www.terraform.io/), use something like the following for your
new node pool:
```yaml
ng-ethereum = {
desired_size = 1
subnet_ids = module.vpc.public_subnets # Only public subnets here.
vpc_security_group_ids = [ sg-1234 ] # The ID of the security group from the previous step.
instance_types = ["m6a.xlarge"]
iam_role_name = "${local.name}-eks-ng-ethereum-role"
taints = [
{
key = "ethereum"
value = "true"
effect = "NO_SCHEDULE"
},
{
key = "ethereum"
value = "true"
effect = "NO_EXECUTE"
}
]
labels = {
workloadType = "ethereum"
}
...
```
#### 3. Install the EBS or EFS drivers
We recommend using EBS or NvME storage for your chain data.
For most cases, the [EBS drivers](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html) or
[EFS drivers](https://docs.aws.amazon.com/eks/latest/userguide/efs-csi.html) are sufficient.
However, if you are using instance stores, use the
[Local Storage Static Provisioner](https://aws.amazon.com/blogs/containers/eks-persistent-volumes-for-instance-store/)
instead.
#### 4. Set up the pod
Now that the infrastructure is set up, use `hostNetworking` to bind your pod to the host and use the
host node's public IP for your Besu node.
First, add the following snippet to your StatefulSet:
```yaml
template:
metadata:
labels:
...
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
affinity: ...
```
Next, add an init container and a shared volume to store the public IP.
The init container `init` runs and gets the public IP of the host using the AWS metadata service and
saves it to a local shared volume `besu-pip` (between the init container and the Besu pod).
```yaml
template:
metadata:
labels:
...
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
affinity: ...
initContainers:
- name: init
image: alpine/curl:8.5.0
volumeMounts:
- name: pip
mountPath: /pip
- name: shared-jwt
mountPath: /jwt
- name: besu-data
mountPath: /data
securityContext:
runAsUser: 0
command:
- /bin/bash
- -xec
- |
# Get the existing public IP to associate with.
PUBLIC_IP_TO_ASSOCIATE=$(curl http://ifconfig.me/ip)
# Store the public IP in a local file to be used by the container.
echo -ne "$PUBLIC_IP_TO_ASSOCIATE" > /pip/ip
# Create the JWT key.
openssl rand -hex 32 | tr -d "\n" > /jwt/jwtSecret.hex
# Update permissions on the data volume (if needed).
chown -R 1000:1000 /data
containers:
...
volumes:
- name: pip
emptyDir: {}
- name: jwt
emptyDir: {}
- name: besu-data
persistentVolumeClaim:
claimName: besu-pvc
- name: teku-data
persistentVolumeClaim:
claimName: teku-pvc
```
When you start Besu up in the pod, use the text file in `pip` as your `p2p-host`, which allows
traffic in and out as normal.
```yaml
template:
metadata:
labels:
...
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
affinity: ...
initContainers:
- name: init
image: alpine/curl:8.5.0
volumeMounts:
- name: pip
mountPath: /pip
- name: shared-jwt
mountPath: /jwt
- name: besu-data
mountPath: /data
securityContext:
runAsUser: 0
command:
- /bin/bash
- -xec
- |
# Get the existing public IP to associate with.
PUBLIC_IP_TO_ASSOCIATE=$(curl http://ifconfig.me/ip)
# Store the public IP in a local file to be used by the container.
echo -ne "$PUBLIC_IP_TO_ASSOCIATE" > /pip/ip
# Create the JWT key.
openssl rand -hex 32 | tr -d "\n" > /jwt/jwtSecret.hex
# Update permissions on the data volume (if needed).
chown -R 1000:1000 /data
containers:
- name: besu
image: hyperledger/besu:latest
volumeMounts:
- name: pip
mountPath: /pip
readOnly: true
- name: shared-jwt
mountPath: /jwt
- name: besu-data
mountPath: {{ .Values.settings.dataPath }}
ports:
- name: elc-rpc
containerPort: 8545
protocol: TCP
- name: elc-ws
containerPort: 8546
protocol: TCP
- name: elc-rlpx
containerPort: 30303
protocol: TCP
- name: elc-discovery
containerPort: 30303
protocol: UDP
- name: elc-metrics
containerPort: 8545
protocol: TCP
- name: elc-engine
containerPort: 8551
protocol: TCP
command:
- /bin/sh
- -c
args:
- |
pip=$(cat /pip/ip)
/opt/besu/bin/besu \
--p2p-host=${pip} \
...
- name: teku
image: consensys/teku:develop
...
volumes:
- name: pip
emptyDir: {}
- name: jwt
emptyDir: {}
- name: besu-data
persistentVolumeClaim:
claimName: besu-pvc
- name: teku-data
persistentVolumeClaim:
claimName: teku-pvc
```
## Azure AKS
The process for Azure is much the same as that of AWS with a couple of differences.
#### 1. Create a Network Security Group (NSG)
Create a NSG with ports `30303` and `9000` (or equivalent) open for TCP and UDP.
Bind this NSG with the subnet you've designated for your Ethereum nodes to ensure that nodes initiated within this subnet will automatically inherit these security rules.
#### 2. Add a node pool to your cluster
In Azure all machines get allocated a public IP by default but you need to turn this on for your
new node pool.
If you are using [Terraform](https://www.terraform.io/), use something like the following for your
new node pool:
```yaml
node_pools = {
...
ethereum = {
name = "ethereum"
vm_size = "Standard_D8as_v5"
vnet_subnet_id = lookup(module.vnet.vnet_subnets_name_id, "subnet-....") # The ID of the security group from the previous step.
os_disk_size_gb = 100
min_count = 1
max_count = 10
enable_auto_scaling = true
enable_node_public_ip = true # This flag lets every node keep its public ip
enable_host_encryption = true
node_taints = ["ethereum=true:NoSchedule", "ethereum=true:NoExecute"]
node_labels = {
"workloadType" = "ethereum"
}
}
...
}
```
#### 3. Use Azure StorageClasses to suit your needs
We recommend using either Azure Disk or Azure Files to store your chain data
using the [CSI storage drivers](https://learn.microsoft.com/en-us/azure/aks/csi-storage-drivers).
If you are using a Terraform to provision your cluster e.g.
[terraform-azurerm-aks](https://registry.terraform.io/modules/Azure/aks/azurerm/latest)
the CSI drivers are provisioned automatically for you.
---
## Concepts
This section provides background information and context about private network features.
The following features are shared with [public networks](../../public-networks/index.md) and the content can be found in the public networks section:
- Transactions:
- [Transaction types](../../public-networks/concepts/transactions/types.md)
- [Transaction pool](../../public-networks/concepts/transactions/pool.md)
- [Transaction validation](../../public-networks/concepts/transactions/validation.md)
- [Network ID and chain ID](../../public-networks/concepts/network-and-chain-id.md)
- [Events and logs](../../public-networks/concepts/events-and-logs.md)
- [Genesis file](../../public-networks/concepts/genesis-file.md)
- [Node keys](../../public-networks/concepts/node-keys.md)
---
## Node synchronization for private networks
For private, permissioned blockchain networks, Besu uses the same [synchronization
modes as public networks](../../public-networks/concepts/node-sync.md), but with specific configurations
for private network needs.
To sync Besu on a private network:
- Ensure all nodes use compatible sync modes and configurations.
- Configure the network with a custom genesis file.
- Set the network ID and bootnodes specific to your private network.
- Implement permissioning features to control network access.
The following is an overview of the private network sync modes.
Select the sync mode based on your network's requirements and node purposes.
| Sync mode | Private network use | Description |
|--------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|
| [Full](../../public-networks/concepts/node-sync.md#full-synchronization) | Default for private networks. Use full sync for the initial network and when peers cannot serve snap data. | Downloads and verifies the blockchain from genesis. Enable using [`--sync-mode=FULL`](../../public-networks/reference/options.md#sync-mode). |
| [Snap](../../public-networks/concepts/node-sync.md#snap-synchronization) | Optional for nodes joining or catching up to an existing private network. | Downloads as many leaves of the trie as possible and reconstructs the trie locally. Requires existing Bonsai nodes to serve snap sync data using [`--snapsync-server-enabled=true`](../../public-networks/reference/options.md#snapsync-server-enabled). Enable using [`--sync-mode=SNAP`](../../public-networks/reference/options.md#sync-mode). |
:::warning Checkpoint sync
Checkpoint sync is deprecated and will be removed in a future release. When you select checkpoint sync, Besu performs snap sync instead.
:::
---
## Permissioning
A permissioned network enables node permissioning and account permissioning, allowing only specified nodes and accounts to access the network.
:::caution Permissioning in peer-to-peer networks: challenges and enforcement
In peer-to-peer networks, permissioning enforces rules on nodes you control.
Permissioning requires a distributed network of trust across the network where participants agree to follow the rules. One bad actor can decide not to follow the rules. Nodes can take action to prevent the bad actor from adding to the chain but they cannot prevent the bad actor from allowing access to the chain.
:::
## Node permissioning
Use node permissioning to restrict access to known participants only.

Node-level permissions are a useful system of governance to control connections to an individual node.
## Account permissioning
Use account permissioning to:
- Enforce onboarding or identity requirements.
- Suspend accounts.
- Restrict the actions an account can perform.

## Specify local permissioning
[Local permissioning](../how-to/use-local-permissioning.md) works at the node level. Each node in the network has a [permissions configuration file], which can be used to configure node and/or account permissioning rules.
Local permissioning affects your node but not the rest of the network. Use local permissioning to restrict use of your node (that is, the resources under your control). For example, customers are able to access your node.
Local permissioning does not require coordination with the rest of the network and you can act immediately to protect your node. Your rules are not enforced in blocks produced by other nodes.
To implement more complex permissioning rules, you can [write your own plugin](../../plugins/index.md).
[permissions configuration file]: ../how-to/use-local-permissioning.md#permissions-configuration-file
---
## Proof of authority consensus
Besu implements the QBFT and IBFT 2.0 proof of authority (PoA) [consensus protocols](../how-to/configure/consensus/index.md). PoA consensus protocols work when participants know each other and there is a level of trust between them. For example, in a permissioned consortium network.
:::warning Important
Besu no longer supports the Clique consensus protocol.
:::
PoA consensus protocols have faster block times and much greater transaction throughput than the proof of stake consensus used on Ethereum Mainnet.
In QBFT or IBFT 2.0, a group of nodes in the network act as validators. The existing nodes in the validator pool vote to add nodes to or remove nodes from the pool.
Consider the following properties when using QBFT or IBFT 2.0:
## Immediate finality
QBFT and IBFT 2.0 have immediate finality; there are no forks and all valid blocks get included in the main chain.
## Minimum number of validators
To be Byzantine fault tolerant, QBFT and IBFT 2.0 require a minimum of four validators.
:::tip
Byzantine fault tolerant is the ability to function correctly and reach consensus despite nodes failing or propagating incorrect information to peers.
:::
## Liveness
QBFT and IBFT 2.0 networks require greater than or equal to two-thirds of validators to be operating to create blocks. For example, an QBFT and IBFT 2.0 network of:
- Four to five validators tolerates one unresponsive validator.
- Six to eight validators tolerates two unresponsive validators.
Networks with three or less validators can produce blocks but do not guarantee finality when operating in adversarial environments.
:::caution
We recommend using QBFT or IBFT 2.0 networks with at least four nodes in production environments.
:::
## Speed
For QBFT and IBFT 2.0, the time to add new blocks increases as the number of validators increases.
---
## Privacy with Paladin
[Paladin](https://lfdt-paladin.github.io/paladin/head/architecture/overview/) is an open-source
privacy layer developed by the Linux Foundation Decentralized Trust (LFDT), separate from Besu.
It runs alongside each Besu node in a permissioned network, managing private state in each node's
encrypted local database and anchoring cryptographic commitments on the public chain.
This allows participants to share confidential business logic, private tokens, or regulated assets
without exposing that data to the rest of the network.
[Permissioning](./permissioning.md) controls which nodes and accounts can access the network.
Paladin controls what those permitted participants can see once they are on the network.
The two mechanisms are independent and can be used together.
Use Paladin when full on-chain visibility is unacceptable for your use case, for example when
sharing contract state between a subset of consortium members, issuing regulated tokens that
require auditor oversight, or settling assets with no trusted intermediary.
Paladin supports three privacy domains, each with a different trust model and privacy mechanism.
Choosing the right domain depends on what you need to keep private and how much you trust the
other parties involved.
## Privacy domains
In Paladin, a _domain_ is a pluggable runtime module that implements a specific privacy protocol.
Each domain has its own smart contracts, key management, and transaction lifecycle.
Paladin ships three built-in domains: Pente, Noto, and Zeto.
### Pente
Pente is a privacy group domain where a subset of nodes share an encrypted EVM environment.
Members can deploy and call Solidity contracts whose state is invisible to non-members.
Transactions are submitted by any group member and executed privately; only an encrypted state
root lands on the public chain.
No trusted third party is required; the group collectively holds the state, and other members
endorse each EVM execution.
Use Pente for private business logic: confidential contracts, private DeFi, and multi-party
workflows that need shared compute rather than just value transfer.
### Noto
Noto is a private token domain backed by a designated notary.
Every transfer must be co-signed by the notary, who has full visibility into all balances and
transfers; each participant sees only their own transactions.
The notary co-signs automatically in `notaryMode: basic`, which means you are trusting the notary
to act honestly and not front-run transfers.
Use Noto when an issuer or custodian must maintain full auditability over a token: regulated
assets such as CBDCs, tokenised securities, or supply-chain tokens with compliance requirements.
### Zeto
Zeto is a private token domain that uses zero-knowledge succinct non-interactive arguments of
knowledge (ZK-SNARKs).
Each transfer is accompanied by a cryptographic proof that the sender owned the funds and the
amounts are consistent, without revealing what those amounts are.
No trusted third party is required; validity is guaranteed by the proof, not by a co-signer.
:::note Proof generation: bundled library vs. production
The Paladin Docker image bundles a shared library (`libzeto.so`) containing WASM-compiled
Groth16 circuits for proof generation.
This is the setup used in the Developer Quickstart and requires no ZK tooling on your machine,
but WASM warm-up adds 3 to 5 minutes of latency on the first transaction in each session,
particularly noticeable in Docker or WSL2 environments.
In production, most deployments replace the bundled WASM circuits with natively compiled
binaries and a dedicated prover such as
[rapidsnark](https://github.com/iden3/rapidsnark), reducing proof generation to under 30
seconds and eliminating the warm-up penalty.
Refer to the [Paladin documentation](https://lfdt-paladin.github.io/paladin/head/architecture/overview/)
for guidance on configuring a production prover.
:::
Use Zeto when you need the strongest privacy guarantees with no trusted intermediary: interbank
settlement, privacy-first payment rails, or any use case where even the notary model is
unacceptable.
### Domain comparison
| | Pente | Noto | Zeto |
| -------------------------------- | ----------------------------- | ------------------------------------------- | ------------------------------------------------------- |
| **Privacy mechanism** | Encrypted EVM state | UTXO hashes, notary co-signs | UTXO hashes and Groth16 ZK proof |
| **Who can see amounts** | Group members only | Notary sees all; participants see own txns | Sender and receiver only |
| **Who must sign** | Submitting node | Sender and notary (automatic in basic mode) | Sender only (proof substitutes co-signer) |
| **Trusted third party** | No | Yes (notary) | No |
| **Smart contract support** | Yes (private EVM) | No | No |
| **Token transfers** | No (compute, not value) | Yes | Yes |
| **Double-spend protection** | EVM state | Notary enforces UTXO rules | Nullifiers (`Zeto_AnonNullifier`) or none (`Zeto_Anon`) |
| **Proof of validity** | EVM re-execution by members | Notary signature | Cryptographic (Groth16 SNARK) |
| **Transaction latency** | Seconds | Seconds | Under 30s (native binaries); 3–5 min first-run warm-up with bundled `libzeto.so` (WASM) |
| **Best for** | Private business logic | Regulated tokens with oversight | Maximum privacy, no trusted party |
## Factory contracts
Paladin is a multi-node system, and the nodes need a shared on-chain coordination point for each
privacy domain.
That coordination point is a factory contract.
Paladin keeps private state off-chain, in each node's encrypted private database.
The public chain still needs to know something is happening; otherwise double-spends are possible,
state roots can't be anchored, and nodes have no way to discover that a new token or privacy group
exists.
When a node deploys a new token or forms a privacy group, it needs a known on-chain address to
publish to, and other nodes need to know where to look.
Each factory contract serves that purpose: it is a static address, hardcoded in each node's
configuration, that acts as a shared registry.
In Paladin configuration, that address is typically set as `registryAddress`.
Deploying a token or privacy group calls the factory contract, which emits an on-chain event that
all other Paladin nodes are watching.
This makes discovery automatic, with no out-of-band coordination required.
Each domain has its own factory contract, and all three must be deployed before any Paladin node
starts.
For details on factory contract deployment and configuration, see the
[Paladin architecture documentation](https://lfdt-paladin.github.io/paladin/head/architecture/overview/).
## Next steps
- Use the [Developer Quickstart with privacy](../tutorials/quickstart-with-privacy.md) to create a
local network with all three privacy domains.
- Learn how [permissioning](./permissioning.md) controls node and account access on your network.
---
## Install binary distribution(Install)
## MacOS with Homebrew
### Prerequisites
- [Homebrew](https://brew.sh/)
- Java JDK
:::caution
Besu supports:
- MacOS High Sierra 10.13 or later versions.
- Java 25+. You can install Java using `brew install openjdk@25`. Alternatively, you can manually
install the [Java JDK](https://www.oracle.com/java/technologies/downloads).
:::
### Install (or upgrade) using Homebrew
To install Besu using Homebrew:
```bash
brew tap besu-eth/besu
brew install besu-eth/besu/besu
```
To upgrade an existing Besu installation using Homebrew:
```bash
brew upgrade besu-eth/besu/besu
```
:::note
If you've upgraded your MacOS version between installing and upgrading Besu, when running `brew upgrade besu-eth/besu/besu` you may be prompted to reinstall command line tools with `xcode-select --install`.
:::
:::note
When upgrading Besu, you might be prompted to fix the remote branch names in Homebrew by using the command `brew tap --repair`.
:::
To display the Besu version and confirm installation:
```bash
besu --version
```
To display Besu command line help:
```bash
besu --help
```
## Linux / Unix
### Prerequisites
- [Java JDK 25+](https://www.oracle.com/java/technologies/downloads/)
:::note Linux open file limit
If synchronizing to Mainnet on Linux or other chains with large data requirements, increase the maximum number of open files allowed using `ulimit`. If the open files limit is not high enough, a `Too many open files` RocksDB exception occurs.
:::
:::tip
We recommend installing [jemalloc](https://jemalloc.net/) to reduce memory usage. If using Ubuntu, you can install it with the command: `apt install libjemalloc-dev`.
:::
### Install from packaged binaries
Download the Besu [packaged binaries](https://github.com/besu-eth/besu/releases).
Unpack the downloaded files and change into the `besu-` directory.
Display Besu command line help to confirm installation:
```bash
bin/besu --help
```
## Upgrade Besu
See the [Upgrade Besu](../../../public-networks/how-to/upgrade-node.md#upgrade-on-linux) guide for instructions on upgrading Besu on Linux.
---
## Installation options(Install)
Get started with the [Developer Quickstart](../../../private-networks/tutorials/quickstart.md). Use the quickstart to rapidly generate local blockchain networks.
You can also install the following:
- [Docker image](run-docker-image.md)
- [Binaries](binary-distribution.md)
## Build from source
If you want to use the latest development version of Besu or a specific commit, build from source. Otherwise, use the [binary] or [Docker image] for more stable versions.
View the [Wiki] for instructions to install Besu from source.
[Wiki]: https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22154264/Building+from+source
[binary]: binary-distribution.md
[Docker image]: run-docker-image.md
---
## Run Besu from Docker image(Install)
# Run Besu from a Docker image
Besu provides a Docker image to run a Besu node in a Docker container.
Use this Docker image to run a single Besu node without installing Besu.
## Prerequisites
- [Docker](https://docs.docker.com/install/)
- MacOS or Linux
:::caution
The Docker image does not run on Windows.
:::
## Expose ports
Expose ports for P2P discovery, GraphQL, metrics, and HTTP and WebSocket JSON-RPC. You need to expose the ports to use the default ports or the ports specified using [`--rpc-http-port`](../../../public-networks/reference/options.md#rpc-http-port), [`--p2p-port`](../../../public-networks/reference/options.md#p2p-port), [`--rpc-ws-port`](../../../public-networks/reference/options.md#rpc-ws-port), [`--metrics-port`](../../../public-networks/reference/options.md#metrics-port), [`--graphql-http-port`](../../../public-networks/reference/options.md#graphql-http-port), and [`--metrics-push-port`](../../../public-networks/reference/options.md#metrics-push-port) options.
To run Besu exposing local ports for access:
```bash
docker run -p :8545 -p :8546 -p :30303 hyperledger/besu:latest --rpc-http-enabled --rpc-ws-enabled
```
:::note
The examples on this page expose TCP ports only. To expose UDP ports, specify `/udp` at the end of the argument for the `-p` Docker subcommand option:
```bash
docker run -p :/udp
```
See the [`docker run -p` documentation](https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port--p---expose).
:::
To enable JSON-RPC HTTP calls to `127.0.0.1:8545` and P2P discovery on `127.0.0.1:13001`:
```bash
docker run -p 8545:8545 -p 13001:30303 hyperledger/besu:latest --rpc-http-enabled
```
## Start Besu
:::danger
Don't mount a volume at the default data path (`/opt/besu`). Mounting a volume at the default data path interferes with the operation of Besu and prevents Besu from safely launching.
To run a node that maintains the node state (key and database), [`--data-path`](../../../public-networks/reference/options.md#data-path) must be set to a location other than `/opt/besu` and a storage volume mounted at that location.
When running in a Docker container, [`--nat-method`](../../../public-networks/how-to/connect/specify-nat.md) must be set to `DOCKER` or `AUTO` (default). Don't set [`--nat-method`](../../../public-networks/how-to/connect/specify-nat.md) to `NONE` or `UPNP`.
:::
You can specify [Besu environment variables](../../../public-networks/reference/options.md#specify-options) with the Docker image instead of the command line options.
```bash
docker run -p 30303:30303 -p 8545:8545 -e BESU_RPC_HTTP_ENABLED=true -e BESU_NETWORK=sepolia hyperledger/besu:latest
```
```bash
docker run -p 30303:30303 -p 8545:8545 -e BESU_RPC_HTTP_ENABLED=true -e BESU_NETWORK=ephemery hyperledger/besu:latest
```
:::caution "Unsupported address type exception"
When running Besu from a Docker image, you might get the following exception:
```bash
Unsupported address type exception when connecting to peer {}, this is likely due to ipv6 not being enabled at runtime.
```
This happens when the IPv6 support in Docker is disabled while connecting to an IPv6 peer, preventing outbound communication. IPv6 is disabled by default in Docker.
[Enable IPv6 support in Docker](https://docs.docker.com/config/daemon/ipv6/) to allow outbound IPv6 traffic and allow connection with IPv6 peers.
:::
### Run a node for testing
To run a node for testing purposes with WebSocket enabled:
```bash
docker run -p 8546:8546 --mount type=bind,source=/,target=/var/lib/besu hyperledger/besu:latest --rpc-ws-enabled --network=dev --data-path=/var/lib/besu
```
## Stop Besu and clean up resources
When done running nodes, you can shut down the node container without deleting resources or you can delete the container after stopping it. Run `docker container ls` and `docker volume ls` to get the container and volume names.
To stop a container:
```bash
docker stop
```
To delete a container:
```bash
docker rm
```
## Upgrade Besu
See the [Upgrade Besu](../../../public-networks/how-to/upgrade-node.md#upgrade-on-docker) guide for instructions on upgrading Besu on Docker.
---
## Start Besu(Get-started)
Use the [`besu`](../reference/options.md) command with the required command line options to start a node.
## Prerequisites
[Besu installed](install/binary-distribution.md)
## Local block data
When connecting to a network other than the network previously connected to, you must either delete the local block data or use the [`--data-path`](../../public-networks/reference/options.md#data-path) option to specify a different data directory.
To delete the local block data, delete the `database` directory in the `besu/build/distribution/besu-` directory.
## Genesis configuration
To define a genesis configuration, create a [genesis file](../../public-networks/concepts/genesis-file.md) (for example, `genesis.json`) and specify the file using the [`--genesis-file`](../../public-networks/reference/options.md#genesis-file) option.
When you specify [`--network=dev`](../../public-networks/reference/options.md#network), Besu uses the development mode genesis configuration with a fixed low difficulty. A node started with [`--network=dev`](../../public-networks/reference/options.md#network) has an empty bootnodes list by default.
Predefined genesis configurations for named networks are in the [Besu source files](https://github.com/besu-eth/besu/tree/master/config/src/main/resources).
## Confirm node is running
If you started Besu with the [`--rpc-http-enabled`](../../public-networks/reference/options.md#rpc-http-enabled) option, use [cURL](https://curl.haxx.se/) to call [JSON-RPC API methods](../reference/api/index.md) to confirm the node is running.
- `eth_chainId` returns the chain ID of the network.
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' localhost:8545/ -H "Content-Type: application/json"
```
- `eth_syncing` returns the starting, current, and highest block.
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' localhost:8545/ -H "Content-Type: application/json"
```
For example, after connecting to Mainnet, `eth_syncing` will return something similar to:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"startingBlock": "0x0",
"currentBlock": "0x2d0",
"highestBlock": "0x66c0"
}
}
```
## Run a node for testing
To run a node for testing purposes:
```bash
besu --network=dev --rpc-http-cors-origins="all" --host-allowlist="*" --rpc-ws-enabled --rpc-http-enabled --data-path=/tmp/tmpDatdir
```
You can also use the following [configuration file](../../public-networks/how-to/configure-besu/index.md) on the command line to start a node with the same options as above:
```toml
network="dev"
rpc-http-cors-origins=["all"]
host-allowlist=["*"]
rpc-ws-enabled=true
rpc-http-enabled=true
data-path="/tmp/tmpdata-path"
```
:::caution
The following settings are a security risk in production environments:
- Enabling the HTTP JSON-RPC service ([`--rpc-http-enabled`](../../public-networks/reference/options.md#rpc-http-enabled)) and setting [`--rpc-http-host`](../../public-networks/reference/options.md#rpc-http-host) to 0.0.0.0 exposes the RPC connection on your node to any remote connection.
- Setting [`--host-allowlist`](../../public-networks/reference/options.md#host-allowlist) to `"*"` allows JSON-RPC API access from any host.
- Setting [`--rpc-http-cors-origins`](../../public-networks/reference/options.md#rpc-http-cors-origins) to `"all"` or `"*"` allows cross-origin resource sharing (CORS) access from any domain.
:::
## Run a node on a private network
To run a node on your private network specifying a genesis file and data directory:
```bash
besu --genesis-file=/genesis.json --data-path= --rpc-http-enabled --bootnodes=
```
Where `` is the path to the directory to save the chain data to. Ensure you configure a peer discovery method, such as [bootnodes](../how-to/configure/bootnodes.md).
:::note
You might need to set [`--tx-pool-limit-by-account-percentage`](../../public-networks/reference/options.md#tx-pool-limit-by-account-percentage) to 1. The default value is suitable for Mainnet, but may cause issues on private networks.
:::
:::info Sync nodes for BFT
If you're running a node on a [QBFT](../how-to/configure/consensus/qbft.md) or [IBFT 2.0](../how-to/configure/consensus/ibft.md) network,
Besu uses [full sync](../../public-networks/concepts/node-sync.md#full-synchronization) by default.
To use [snap sync](../../public-networks/concepts/node-sync.md#snap-synchronization) for a node joining or catching up to an existing QBFT or IBFT 2.0 network,
the existing nodes must serve snap sync data using
[`--snapsync-server-enabled=true`](../../public-networks/reference/options.md#snapsync-server-enabled),
and the joining node must set
[`--sync-mode=SNAP`](../../public-networks/reference/options.md#sync-mode).
:::
---
## System requirements(Get-started)
Private network system requirements depend on many factors, including:
- Size of the world state for the network.
- Number of transactions submitted to the network.
- [Block gas limit](../../public-networks/reference/genesis-items.md#genesis-block-parameters).
- Number and complexity of [JSON-RPC](../../public-networks/how-to/use-besu-api/json-rpc.md), [PubSub](../../public-networks/how-to/use-besu-api/rpc-pubsub.md), or [GraphQL](../../public-networks/how-to/use-besu-api/graphql.md) queries handled by the node.
Participation in private networks is typically restricted in some way, so the volume of traffic is much lower than on Mainnet, resulting in lower system requirements.
## Determining system requirements
To determine system requirements, check CPU and disk space requirements using [Prometheus](../../public-networks/how-to/monitor/metrics.md). Grafana provides a [sample dashboard](https://grafana.com/grafana/dashboards/10273) for Besu.
## Java Virtual Machine size
Depending on your environment and network setup, the minimum Java Virtual Machine (JVM) memory requirement for private networks is 4 GB.
JVM memory requirements are highest when syncing, but will reduce after the node is synchronized to the chain head. Monitor your system to determine your actual JVM memory needs.
## VM requirements
If you set up your own VM locally using a VM manager such as [VirtualBox](https://www.oracle.com/virtualization/virtualbox/):
- Ensure you enable Intel Virtualization Technology (VTx) and Virtualization Technology for Directed I/O (VT-d) in the BIOS settings.
- On Windows, you might need to disable Hyper-V in the Windows Feature list.
We recommend you create a VM with the following attributes:
- Memory size: Set to 6 GB (recommended)
- Create a virtual hard disk with at least 10 GB (20 GB recommended)
- Virtual hard disk file type: VDI (if you need to share it with other apps, use VHD)
- (Optional) You can create a shared directory to copy block files or genesis files from the host computer to the VM. For details on how to create a shared directory, see "Share Folders" in the [Oracle VirtualBox documentation].
## Disk type
Use [local SSD storage](https://cloud.google.com/compute/docs/disks) for high throughput nodes (validators and RPC nodes). Read-only nodes can use a lower performance setup.
You can use local SSDs through [SCSI interfaces](https://en.wikipedia.org/wiki/SCSI). For higher performance in production settings, we recommend upgrading to [NVMe interfaces](https://cloud.google.com/compute/docs/disks/local-ssd#performance).
[Oracle VirtualBox documentation]: https://docs.oracle.com/en/virtualization/virtualbox/6.1/user/
---
## Backup and restore
# Backup and restore Besu
In a decentralized blockchain, data replicates between nodes so it is not lost. But backing up configuration and data ensures a smoother recovery from corrupted data or other failures.
## Genesis file
The genesis file for a network must be accessible on every node. We recommend storing the genesis file under source control.
## Data backups
If installed locally, the default data location is the Besu installation directory.
We recommend mounting a [separate volume to store data](../get-started/install/run-docker-image.md). Use the [`--data-path`](../../public-networks/reference/options.md#data-path) command line option to pass the path to Besu.
The default data location is the Besu installation directory, or `/opt/besu/database` if using the [Besu Docker image](../get-started/install/run-docker-image.md).
Having some data reduces the time to synchronize a new node. You can perform periodic backups of the data directory and send the data to your preferred backup mechanism. For example, `cron` job and `rsync`, archives to the cloud such as s3, or `tar.gz` archives.
## Data restores
To restore data:
1. If the node is running, stop the node.
1. If required, move the data directory to another location for analysis.
1. Restore the data from your last known good backup to the same directory.
1. Ensure user permissions are valid so you can read from and write to the data directory.
1. Restart the node.
## Corrupted data
If log messages signify a corrupt database, the cleanest way to recover is:
1. Stop the node.
1. Restore the data from a [previous backup](#data-backups).
1. Restart the node.
## Prevent accidental downgrade
When restarting Besu, accidentally using an earlier version of Besu might risk corrupting your database.
To protect against incompatibility between versions, set the
[`--version-compatibility-protection`](../../public-networks/reference/options.md#version-compatibility-protection)
option to `true`.
## Find peers after restarting
The process for finding peers after restarting is the same as for [finding peers after upgrading and restarting].
[finding peers after upgrading and restarting]: ../../public-networks/how-to/upgrade-node.md#find-peers-on-restarting
---
## Bootnodes
# Configure bootnodes
You can use bootnodes to initially discover peers. Bootnodes are regular nodes used to discover other nodes.
In private networks for development or testing purposes, specify at least one bootnode.
In production networks, [configure two or more nodes as bootnodes](#configure-bootnodes-in-a-production-network).
:::tip
Bootnodes and static nodes are parallel methods for finding peers. Depending on your use case, you can use only bootnodes, only static nodes, or both bootnodes and static nodes.
When connecting to bootnodes, Besu attempts to connect to all bootnodes at once, at startup.
When connecting to static nodes, Besu attempts to reconnect periodically, if the connection fails or is lost.
To find peers, configure one or more bootnodes. To configure a specific set of peer connections, use [static nodes](../../../public-networks/how-to/connect/static-nodes.md).
:::
:::note Mainnet and public testnets
For Mainnet and the Sepolia and Ephemery testnets, Besu has an internal list of enode URLs and uses this list automatically when you specify the [`--network`](../../../public-networks/reference/options.md#network) option.
:::
## Specify a bootnode
To start a node, specify bootnode [enode URLs](../../../public-networks/concepts/node-keys.md#enode-url) or
[ENR URLs](../../../public-networks/concepts/node-keys.md#enr-url) for P2P
discovery using the [`--bootnodes`](../../../public-networks/reference/options.md#bootnodes) option.
```bash
besu --genesis-file=privateNetworkGenesis.json --data-path=nodeDataPath --bootnodes=enode://c35c3ec90a8a51fd5703594c6303382f3ae6b2ecb99bab2c04b3794f2bc3fc2631dabb0c08af795787a6c004d8f532230ae6e9925cbbefb0b28b79295d615f@127.0.0.1:30303
```
The `--bootnodes` option also accepts files or URLs:
- A local file path: `/path/to/bootnodes.txt`
- A file URI: `file:///path/to/bootnodes.txt`
- An HTTP(S) URL: `https://example.com/bootnodes.txt`
You can mix sources, comma-separated, together with direct enode or ENR URLs.
The list of sources must specify all enode URLs or all ENR URLs.
```bash
besu --bootnodes=/etc/besu/enodes.txt,https://example.com/enodes.txt,enode://c35c3...d615f@1.2.3.4:30303
```
:::tip Early access feature
To use ENR URLs and IPv6 addresses (discovery v5), set the early access option `--Xv5-discovery-enabled` to `true`.
:::
The default host and port advertised to other peers for P2P discovery is `127.0.0.1:30303`.
To specify a different host or port, use the
[`--p2p-host`](../../../public-networks/reference/options.md#p2p-host)
/ [`--p2p-host-ipv6`](../../../public-networks/reference/options.md#p2p-host) or
[`--p2p-port`](../../../public-networks/reference/options.md#p2p-port)
/ [`--p2p-port-ipv6`](../../../public-networks/reference/options.md#p2p-port) options.
By default, peer discovery listens on all available network interfaces. If the device Besu is running
on must bind to a specific network interface, specify the interface using the
[`--p2p-interface`](../../../public-networks/reference/options.md#p2p-interface) or
[`--p2p-interface-ipv6`](../../../public-networks/reference/options.md#p2p-interface-ipv6) option.
## Configure bootnodes in a production network
A network must have at least one operating bootnode. To allow for continuity in the event of failure, configure two or more bootnodes in a production network. If you don't configure any bootnodes, Besu uses Mainnet's default bootnodes.
We don't recommend putting bootnodes behind a load balancer because the [enode](../../../public-networks/concepts/node-keys.md#enode-url) relates to the node public key, IP address, and discovery ports. Any changes to a bootnode enode prevents other nodes from being able to establish a connection with the bootnode. This is why we recommend putting more bootnodes on the network itself.
To ensure a bootnode enode doesn't change when recovering from a complete bootnode failure:
1. Create the [node key pair](../../../public-networks/concepts/node-keys.md) (that is, the private and public key) before starting the bootnode.
1. When creating bootnodes in the cloud (for example, AWS and Azure), attempt to assign a static IP address to them. If your network is:
- Publicly accessible, assign an elastic IP.
- Internal only, specify a private IP address when you create the instance and record this IP address.
We recommend storing the bootnode configuration under source control.
To allow for failure, specify all bootnodes on the command line (even to the bootnodes themselves).
:::tip
Having each bootnode list the other bootnodes increases the speed of discovery. Nodes ignore their own enode in the bootnodes list so it isn't required to specify different bootnode lists to the bootnodes themselves.
:::
## Add and remove bootnodes
Adding new bootnodes is a similar process to creating bootnodes. After creating the bootnodes and adding them to the network, update the [`--bootnodes`](../../../public-networks/reference/options.md#bootnodes) command line option for each node to include the new bootnodes.
When adding bootnodes, you don't need to restart running nodes. By updating the [`--bootnodes`](../../../public-networks/reference/options.md#bootnodes) option, the next time you restart the nodes (for example, when [upgrading](../../../public-networks/how-to/upgrade-node.md)), the nodes connect to the new bootnodes.
---
## Add and remove validators without voting
[QBFT](qbft.md) or [IBFT 2.0](ibft.md) network conditions might not allow voting to change validators. For example, if a majority of the current validators are no longer participating in the network, a vote to add or remove validators won't be successful. You can bypass voting and specify new validators using a transition in the genesis file.
:::caution
- In most cases, add or remove validators [by voting or smart contract for QBFT](qbft.md#add-and-remove-validators); or [by voting for IBFT 2.0](ibft.md#add-and-remove-validators). Use transitions only when voting isn't possible. Using transitions requires coordinating a rolling update of all the nodes in order to pick up the configuration at the correct block height. Using transitions also leaves the validator overrides permanently in your genesis configuration.
- Transitions are a Besu-specific feature. If you run a mixed-client QBFT network, you can't use transitions to change the validators.
:::
To add or remove validators without voting:
1. In the genesis file, add the `transitions` configuration item where:
- `` is the upcoming block at which to change validators.
- ` ... ` are strings representing the account addresses of the validators after ``.
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
},
"transitions": {
"qbft": [
{
"block": ,
"validators": [
,
...
]
}
]
}
},
...
}
```
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
},
"transitions": {
"qbft": [
{
"block": 25,
"validators": [
"0x372a70ace72b02cc7f1757183f98c620254f9c8d",
"0x9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb"
]
}
]
}
},
...
}
```
```json
{
"config": {
...
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
},
"transitions": {
"ibft2": [
{
"block": ,
"validators": [
,
...
]
}
]
}
},
...
}
```
```json
{
"config": {
...
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
},
"transitions": {
"ibft2": [
{
"block": 25,
"validators": [
"0x372a70ace72b02cc7f1757183f98c620254f9c8d",
"0x9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb"
]
}
]
}
},
...
}
```
2. Restart all nodes in the network using the updated genesis file. You can make a rolling update of the nodes, as long as they're all up before the transition block is processed.
3. To verify the changes after the transition block, call [`qbft_getValidatorsByBlockNumber`](../../../reference/api/qbft.md#qbft_getvalidatorsbyblocknumber) or [`ibft_getValidatorsByBlockNumber`](../../../reference/api/ibft.md#ibft_getvalidatorsbyblocknumber), specifying `latest`.
:::caution
Don't specify a transition block in the past.
Specifying a transition block in the past can result in unexpected behavior, such as causing the network to fork.
:::
## Override smart contract validators
When using [QBFT contract validator selection](qbft.md#add-and-remove-validators-using-a-smart-contract), if network conditions require it, you can bypass the smart contract and specify new validators in the genesis file. For example, you lose quorum for your current list of contract validators, and you can't perform a transaction to vote more in.
This requires temporarily [switching to block header validator selection mode](qbft.md#swap-validator-management-methods).
To bypass the smart contract and specify new validators:
1. In the genesis file, add a `transitions` configuration item where:
- `` is the upcoming block at which to change validators.
- `` is the validator selection mode to switch to. In this case we'll switch to the `blockheader` mode temporarily.
- ` ... ` are strings representing the account addresses of the validators after ``. These validators only need to be sufficient to progress the chain and allow a new contract to be deployed.
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4,
"validatorcontractaddress": "0x0000000000000000000000000000000000007777"
},
"transitions": {
"qbft": [
{
"block": ,
"validatorselectionmode": ,
"validators": [
,
...
]
}
]
}
},
...
}
```
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4,
"validatorcontractaddress": "0x0000000000000000000000000000000000007777"
},
"transitions": {
"qbft": [
{
"block": 2555,
"validatorselectionmode": "blockheader",
"validators": [
"0x372a70ace72b02cc7f1757183f98c620254f9c8d",
"0x9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb"
]
}
]
}
},
...
}
```
2. Restart all nodes in the network using the updated genesis file. You can make a rolling update of the nodes, as long as they're all up before the transition block is processed.
3. Deploy a new contract to the blockchain containing the desired list of validators.
4. In the genesis file, add another `transitions` configuration item where:
- `` is the upcoming block at which to change validators.
- `` is the validator selection mode to switch to. In this case we'll switch to `contract` mode.
- `` is the address of the new smart contract.
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4,
“validatorcontractaddress”: “0x0000000000000000000000000000000000007777”
},
"transitions": {
"qbft": [
{
"block": 2555,
"validatorselectionmode": "blockheader",
"validators": [
"0x372a70ace72b02cc7f1757183f98c620254f9c8d",
"0x9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb"
]
},
{
"block": ,
"validatorselectionmode": ,
"validatorcontractaddress":
}
]
}
},
...
}
```
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4,
"validatorcontractaddress": "0x0000000000000000000000000000000000007777"
},
"transitions": {
"qbft": [
{
"block": 2555,
"validatorselectionmode": "blockheader",
"validators": [
"0x372a70ace72b02cc7f1757183f98c620254f9c8d",
"0x9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb"
]
},
{
"block": 2755,
"validatorselectionmode": "contract",
"validatorcontractaddress": "0x0000000000000000000000000000000000009999"
}
]
}
},
...
}
```
5. Restart all nodes in the network using the updated genesis file. You can make a rolling update of the nodes, as long as they're all up before the transition block is processed.
---
## IBFT 2.0
# Configure IBFT 2.0 consensus
Besu implements the IBFT 2.0 proof of authority (PoA) [consensus protocol](index.md). IBFT 2.0 is supported for existing private networks, but [QBFT](qbft.md) is the recommended enterprise-grade consensus protocol for private networks.
In IBFT 2.0 networks, approved accounts, known as validators, validate transactions and blocks. Validators take turns to create the next block. Before inserting the block onto the chain, a super-majority (greater than or equal to 2/3) of validators must first sign the block.
Existing validators propose and vote to [add or remove validators](#add-and-remove-validators).
You can [create a private network using IBFT](../../../tutorials/ibft/index.md).
:::caution
Configure your network to ensure you never lose more than 1/3 of your validators.
If more than 1/3 of validators stop participating, the network stops creating new blocks and stalls.
It might take significant time to recover after nodes are restarted.
:::
:::tip HSM-backed validator keys
For IBFT 2.0 validators, [node addresses](../../../../public-networks/concepts/node-keys.md) are validator addresses.
To store a validator's node key in a Hardware Security Module (HSM) instead of
on disk, use a security module plugin, such as the
[Besu HSM plugin](https://github.com/besu-eth/besu-hsm-plugin), with the
[`--security-module`](../../../../public-networks/reference/options.md#security-module)
option.
:::
## Genesis file
To use IBFT 2.0, Besu requires an IBFT 2.0 [genesis file](../../../../public-networks/concepts/genesis-file.md). The genesis file defines properties specific to IBFT 2.0.
```json title="Example IBFT 2.0 genesis file"
{
"config": {
"chainId": 1981,
"berlinBlock": 0,
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4,
"blockreward": "5000000000000000",
"miningbeneficiary": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"
}
},
"nonce": "0x0",
"timestamp": "0x58ee40ba",
"extraData": "0xf83ea00000000000000000000000000000000000000000000000000000000000000000d594c2ab482b506de561668e07f04547232a72897daf808400000000c0",
"gasLimit": "0x1fffffffffffff",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"alloc": {}
}
```
You can configure the following properties in the `ibft2` configuration object:
- `blockperiodseconds` - The minimum block time, in seconds.
The default is 1.
- `emptyblockperiodseconds` - The minimum time between empty blocks, in seconds.
Use this to reduce empty block production while still producing blocks more quickly when transactions are pending.
The default is 0, which disables the empty block delay.
- `epochlength` - The number of blocks after which to reset all votes.
The default is 30000.
- `requesttimeoutseconds` - The timeout for each consensus round before a round change, in seconds.
The default is 1.
- `blockreward` - Reward amount in Wei to reward the beneficiary.
Specify a hexadecimal value with a `0x` prefix or a decimal string value.
If set, all nodes on the network must use the identical value.
The default is 0.
- `miningbeneficiary` - Beneficiary of the `blockreward`.
If omitted, the validator that proposes the block receives the reward.
If set, all nodes on the network must use the same beneficiary.
:::caution
We don't recommend changing `epochlength` in a running network. Changing the `epochlength` after genesis can result in illegal blocks.
:::
Invalid block header error
When adding a new node, if a `TimeStampMoreRecentThanParent | Invalid block header` error occurs, the genesis file of the new node specifies a higher `blockperiodseconds` than the imported chain. The imported chain makes new blocks faster than the genesis file allows and Besu rejects them with this error. This error most often occurs when importing chains from older versions of Besu.
Decrease the `blockperiodseconds` in the new IBFT 2.0 genesis file to a lower value that satisfies the block header validation.
If the error reads `| TimestampMoreRecentThanParent | Invalid block header: timestamp 1619660141 is only 3 seconds newer than parent timestamp 1619660138. Minimum 4 seconds`, decrease the `blockperiodseconds` from 4 seconds to 3 seconds to match the imported chain.
After you update the new genesis file, if the imported chain has a `blockperiodseconds` value set lower than you prefer, you can adjust it by [configuring the block time on an existing IBFT 2.0 network](#configure-block-time-on-an-existing-network).
The properties with specific values in the IBFT 2.0 genesis files are:
- `nonce` - `0x0`
- `difficulty` - `0x1`
- `mixHash` - `0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365` for Istanbul block identification
To start a node on an IBFT 2.0 private network, use the [`--genesis-file`](../../../../public-networks/reference/options.md#genesis-file) option to specify the custom genesis file.
### Extra data
The `extraData` property is an RLP encoding of:
- 32 bytes of vanity data.
- A list of validator addresses.
- Any validator votes. No vote is included in the genesis block.
- The round the block was created on. The round in the genesis block is 0.
- A list of seals of the validators (signed block hashes). No seals are included in the genesis block.
In the genesis block, the important information in the extra data is the list of validators. All other details have empty values. Formally, `extraData` in the genesis block contains `RLP([32 bytes Vanity, List, No Vote, Round=Int(0), 0 Seals])`.
:::info
RLP encoding is a space-efficient object serialization scheme used in Ethereum.
:::
#### Generate extra data
To generate the `extraData` RLP string for inclusion in the genesis file, use the [`rlp encode`](../../../reference/subcommands.md#encode) Besu subcommand.
```bash title="Example"
besu rlp encode --from=toEncode.json
```
Where the `toEncode.json` file contains a list of the initial validators, in ascending order. To write the validator address and copy it to the `toEncode.json` file, use the [`public-key export-address`](../../../../public-networks/reference/subcommands.md#export-address) Besu subcommand. For example:
```json title="One initial validator in toEncode.json file"
["9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb"]
```
Copy the RLP encoded data to the `extraData` property in the genesis file.
### Block time
When the protocol receives a new chain head, the block time (`blockperiodseconds`) and round timeout (`requesttimeoutseconds`) timers start. When `blockperiodseconds` expires, the protocol proposes a new block.
If `requesttimeoutseconds` expires before adding the proposed block, a round change occurs, with the block time and timeout timers reset. The timeout period for the new round is two times `requesttimeoutseconds`. The timeout period continues to double each time a round fails to add a block.
Usually, the protocol adds the proposed block before reaching `requesttimeoutseconds`. A new round then starts, resetting the block time and round timeout timers. When `blockperiodseconds` expires, the protocol proposes the next new block.
:::danger
If more than 1/3 of validators stop participating, new blocks can no longer be created and `requesttimeoutseconds` doubles with each round change. The quickest method to resume block production is to restart all validators, which resets `requesttimeoutseconds` to its genesis value.
:::
Once `blockperiodseconds` is over, the time from proposing a block to adding the block is small (usually around one second) even in networks with geographically dispersed validators.
An internal network run by ConsenSys had four geographically dispersed validators in Sweden, Sydney, and two in North Virginia. With a `blockperiodseconds` of 5 and a `requesttimeoutseconds` of 10, the testnet consistently created blocks with a five second block time.
#### Tune block timeout
To tune the block timeout for your network deployment:
1. Set `blockperiodseconds` to your desired block time and `requesttimeoutseconds` to two times `blockperiodseconds`.
1. Reduce `requesttimeoutseconds` until you start to see round changes occurring.
1. Increase `requesttimeoutseconds` to the value where round changes are no longer occurring.
:::tip
View [`TRACE` logs](../../../../public-networks/reference/api/trace.md) to see round change log messages.
:::
Use a [transition](#transitions) to update the `blockperiodseconds` in an existing network.
### Advanced configuration options
The `ibft2` object also supports the following optional properties:
- `gossipedHistoryLimit` - Number of previous IBFT 2.0 messages to keep in history for gossip.
The default is 1000.
- `messageQueueLimit` - In large networks with limited resources, increasing the message queue limit might help with message activity surges. The default is 1000.
- `duplicateMessageLimit` - If the same node is retransmitting messages, increasing the duplicate message limit might reduce the number of retransmissions. A value of two to three times the number of validators is usually enough. The default is 100.
- `futureMessagesLimit` - The future messages buffer holds messages for a future chain height. For large networks, increasing the future messages limit might be useful. The default is 1000.
- `futureMessagesMaxDistance` - The maximum height from the current chain height for buffering messages in the future messages buffer. The default is 10.
### Post-Merge configuration
After [The Merge](https://ethereum.org/en/upgrades/merge/), the following block fields are modified or deprecated. Their fields **must** contain only the constant values from the following chart.
| Field | Constant value | Comment |
|------------------|----------------------------------------------------------------------|----------------------------|
| **`ommersHash`** | `0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347` | `= Keccak256(RLP([]))` |
| **`difficulty`** | `0` | Replaced with `prevrandao` |
| **`mixHash`** | `0x0000000000000000000000000000000000000000000000000000000000000000` | Replaced with `prevrandao` |
| **`nonce`** | `0x0000000000000000` | |
| **`ommers`** | `[]` | `RLP([]) = 0xc0` |
Additionally, [`extraData`](#extra-data) is limited to 32 bytes of vanity data after The Merge.
## Add and remove validators
Existing validators propose and vote to add or remove validators using the IBFT 2.0 JSON-RPC API methods. Enable the HTTP interface with [`--rpc-http-enabled`](../../../../public-networks/reference/options.md#rpc-http-enabled) or the WebSocket interface with [`--rpc-ws-enabled`](../../../../public-networks/reference/options.md#rpc-ws-enabled).
The IBFT 2.0 API methods are disabled by default. To enable them, specify the [`--rpc-http-api`](../../../../public-networks/reference/options.md#rpc-http-api) or [`--rpc-ws-api`](../../../../public-networks/reference/options.md#rpc-ws-api) option and include `IBFT`.
The methods to add or remove validators are:
- [`ibft_getPendingVotes`](../../../reference/api/ibft.md#ibft_getpendingvotes).
- [`ibft_proposeValidatorVote`](../../../reference/api/ibft.md#ibft_proposevalidatorvote).
- [`ibft_discardValidatorVote`](../../../reference/api/ibft.md#ibft_discardvalidatorvote).
To view validator metrics for a specified block range, use [`ibft_getSignerMetrics`](../../../reference/api/ibft.md#ibft_getsignermetrics).
:::note
If network conditions render it impossible to add and remove validators by voting, you can [add and remove validators without voting](add-validators-without-voting.md).
:::
### Add a validator
To propose adding a validator to an IBFT 2.0 network, call [`ibft_proposeValidatorVote`](../../../reference/api/ibft.md#ibft_proposevalidatorvote), specifying the address of the proposed validator and `true`. A majority of validators must execute the call.
```bash title="JSON-RPC ibft_proposeValidatorVote request example"
curl -X POST --data '{"jsonrpc":"2.0","method":"ibft_proposeValidatorVote","params":["0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73", true], "id":1}'
```
When the validator proposes the next block, the protocol inserts one proposal received from [`ibft_proposeValidatorVote`](../../../reference/api/ibft.md#ibft_proposevalidatorvote) into the block. If blocks include all proposals, subsequent blocks proposed by the validator will not contain a vote.
When more than 50% of the existing validators have published a matching proposal, the protocol adds the proposed validator to the validator pool and the validator can begin validating blocks.
To return a list of validators and confirm the addition of a proposed validator, use [`ibft_getValidatorsByBlockNumber`](../../../reference/api/ibft.md#ibft_getvalidatorsbyblocknumber).
```bash title="JSON-RPC ibft_getValidatorsByBlockNumber request example"
curl -X POST --data '{"jsonrpc":"2.0","method":"ibft_getValidatorsByBlockNumber","params":["latest"], "id":1}'
```
To discard your proposal after confirming the addition of a validator, call [`ibft_discardValidatorVote`](../../../reference/api/ibft.md#ibft_discardvalidatorvote), specifying the address of the proposed validator.
```bash title="JSON-RPC ibft_discardValidatorVote request example"
curl -X POST --data '{"jsonrpc":"2.0","method":"ibft_discardValidatorVote","params":["0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73"], "id":1}'
```
### Remove a validator
The process for removing a validator from an IBFT 2.0 network is the same as [adding a validator](#add-a-validator) except you specify `false` as the second parameter of [`ibft_proposeValidatorVote`](../../../reference/api/ibft.md#ibft_proposevalidatorvote).
### Epoch transition
At each epoch transition, IBFT 2.0 discards all pending votes collected from received blocks. Existing proposals remain in effect and validators re-add their vote the next time they create a block.
An epoch transition occurs every `epochLength` blocks. Define `epochlength` in the [IBFT 2.0 genesis file](#genesis-file).
### Minimum number of validators
IBFT 2.0 requires four validators to be Byzantine fault tolerant. Byzantine fault tolerance is the ability for a blockchain network to function correctly and reach consensus despite nodes failing or propagating incorrect information to peers.
### Maximum number of validators
As the number of validators increase, the message complexity increases, which can decrease performance. In [network tests](https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22155102/Maximum+Validator+count+for+an+IBFT2+Network), IBFT 2.0 handles up to 30 validators with no loss of performance.
Non-validator nodes don't affect performance and don't count towards the maximum limit.
## Transitions
The `transitions` genesis configuration item allows you to specify a future block number at which to
change the IBFT 2.0 network configuration in an existing network.
For example, you can update the [block time](#configure-block-time-on-an-existing-network),
[block reward](#configure-block-rewards-on-an-existing-network), or
[mining beneficiary](#configure-the-mining-beneficiary-on-an-existing-network).
:::caution
Do not specify a transition block in the past.
Specifying a transition block in the past can result in unexpected behavior, such as causing the
network to fork.
:::
### Configure block time on an existing network
To update an existing network with a new `blockperiodseconds`:
1. Stop all nodes in the network.
2. In the [genesis file](#genesis-file), add the `transitions` configuration item where:
- `` is the upcoming block at which to change `blockperiodseconds`.
- `` is the updated value for `blockperiodseconds`.
```json
{
"config": {
...
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
},
"transitions": {
"ibft2": [
{
"block": ,
"blockperiodseconds":
}
]
}
},
...
}
```
```json
{
"config": {
...
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
},
"transitions": {
"ibft2": [
{
"block": 1240,
"blockperiodseconds": 4
}
]
}
},
...
}
```
3. Restart all nodes in the network using the updated genesis file.
4. To verify the changes after the transition block, view the Besu logs and check that the time
difference between each block matches the updated block period.
### Configure block rewards on an existing network
To update an existing network with a new `blockreward`:
1. Stop all nodes in the network.
2. In the [genesis file](#genesis-file), add the `transitions` configuration item where:
- `` is the upcoming block at which to change `blockreward`.
- `` is the updated value for `blockreward`.
```json
{
"config": {
...
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
"blockreward": "5000000000000000"
},
"transitions": {
"ibft2": [
{
"block": ,
"blockreward":
},
{
"block": ,
"blockreward":
},
{
"block": ,
"blockreward":
}
]
}
},
...
}
```
```json
{
"config": {
...
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
"blockreward": "5000000000000000"
},
"transitions": {
"ibft2": [
{
"block": 10,
"blockreward": "6000000000000000"
},
{
"block": 15,
"blockreward": "75000000000000000"
},
{
"block": 20,
"blockreward": "0"
}
]
}
},
...
}
```
:::note
You can add multiple `blockreward` updates in one transition object by specifying multiple future blocks.
:::
3. Restart all nodes in the network using the updated genesis file.
### Configure the mining beneficiary on an existing network
To update an existing network with a new mining beneficiary:
1. Stop all nodes in the network.
2. In the [genesis file](#genesis-file), add the `transitions` configuration item where:
- `` is the upcoming block at which to change `miningbeneficiary`.
- `` is the updated 20-byte address for `miningbeneficiary`. Starting at ``, block rewards go to this address.
```json
{
"config": {
"chainId": 999,
"berlinBlock": 0,
"ibft2": {
"blockperiodseconds": 1,
"epochlength": 30000,
"requesttimeoutseconds": 5,
"blockreward": "5000000000000000000",
"miningbeneficiary": "0x0000000000000000000000000000000000000001"
},
"transitions": {
"ibft2": [
{
"block": ,
"miningbeneficiary":
},
{
"block": ,
"miningbeneficiary":
}
]
}
},
...
}
```
```json
{
"config": {
"chainId": 999,
"berlinBlock": 0,
"ibft2": {
"blockperiodseconds": 1,
"epochlength": 30000,
"requesttimeoutseconds": 5,
"blockreward": "5000000000000000000",
"miningbeneficiary": "0x0000000000000000000000000000000000000001"
},
"transitions": {
"ibft2": [
{
"block": 10000,
"miningbeneficiary": "",
},
{
"block": 20000,
"miningbeneficiary": "0x0000000000000000000000000000000000000002",
}
]
}
},
...
}
```
:::note
Setting the `miningbeneficiary` to an empty value clears out any override so that block rewards go to the block producer rather than a global override address.
:::
3. Restart all nodes in the network using the updated genesis file.
---
## Consensus protocols
Besu supports the following consensus protocols:
- [QBFT](qbft.md) (proof of authority) - The recommended enterprise-grade consensus protocol for private networks.
- [IBFT 2.0](ibft.md) (proof of authority) - Supported for existing private networks.
- [Proof of stake](../../../../public-networks/concepts/proof-of-stake/index.md) - Used on Ethereum Mainnet and public testnets.
:::warning Important
Besu no longer supports the Clique and Ethash consensus protocols.
:::
Learn more about the [proof of authority consensus protocols](../../../concepts/poa.md).
The `config` property in the genesis file specifies the consensus protocol for a chain.
```json
{
"config": {
...
"qbft": {
...
}
},
...
}
```
```json
{
"config": {
...
"ibft2": {
...
}
},
...
}
```
---
## Migrate from IBFT 2.0 to QBFT
You can migrate a live [IBFT 2.0](ibft.md) network to [QBFT](qbft.md) consensus by updating the
genesis file to include a QBFT configuration section with a future migration block.
## Prerequisites
- A running IBFT 2.0 private network.
## Steps
### 1. Choose a migration block
Choose a block number that gives you enough time to update and restart all nodes in the network.
The migration block must be greater than the current chain head when you restart each node.
Get the current chain head block number using [`eth_blockNumber`](../../../../public-networks/reference/api/index.md#eth_blocknumber):
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
http://:8545
```
### 2. Update the genesis file
Add a `qbft` section to the existing genesis file.
Keep the original `ibft2` section intact; Besu uses both sections to detect and configure the
migration.
```json title="Example migration genesis file"
{
"config": {
"chainId": 1337,
"berlinBlock": 0,
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
},
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4,
"startBlock":
}
},
"nonce": "0x0",
"timestamp": "0x58ee40ba",
"extraData": "",
"gasLimit": "0x1fffffffffffff",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"alloc": {}
}
```
Ensure these fields are set:
- `qbft.startBlock` - The migration block number you chose in step 1.
The value must be greater than 0 and greater than the current chain head when you restart each node.
- `extraData` - The `extraData` value from your existing genesis file.
This field encodes the initial validator set for the IBFT 2.0 genesis block and remains valid after
migration because Besu reads the validator set from block headers.
You can set different QBFT parameters (for example, a shorter `blockperiodseconds`) if you want
the network behavior to change after the migration block.
If you want to keep the same parameters, copy the values from the `ibft2` section.
### 3. Restart all nodes with the updated genesis
Before the network reaches the migration block, restart each node with the updated genesis file:
```bash
besu \
--genesis-file= \
--data-path= \
```
Nodes automatically register both the IBFT 2.0 and QBFT wire protocols so they can communicate
before and after the migration block.
:::tip
Restart validator nodes one at a time and confirm each node is peering correctly before restarting
the next one.
Because IBFT 2.0 requires a super-majority of validators to produce blocks, losing more than 1/3 of
validators during the restart window will stall the network.
:::
:::warning
If any node is still using the old genesis configuration at the migration block, that node will fork
from the network.
:::
### 4. Verify the migration
When the network reaches the migration block, Besu handles the cutover from IBFT 2.0 to QBFT
automatically.
Confirm that the network has switched to QBFT by checking the node logs for the migration block number.
From the migration block onwards, imported and produced block log lines are tagged `QbftBesuControllerBuilder`.
For example:
```bash
2026-07-29 09:15:12.071+00:00 | pool-8-thread-1 | INFO | QbftBesuControllerBuilder | Imported empty block #100 / 0 tx / 0 pending / 0 (0.0%) gas / (0x6fc47ada7146d75f6a46911d8d4038795b0c99970bbd4ce0c6d6aa60955f66fe)
2026-07-29 09:15:14.051+00:00 | pool-8-thread-1 | INFO | QbftBesuControllerBuilder | Imported empty block #101 / 0 tx / 0 pending / 0 (0.0%) gas / (0x3cb663880a65103266b11a8d8631beca5c482d515ac287125aa077b2e31b80b0)
```
---
## QBFT
# Configure QBFT consensus
Besu implements the QBFT proof of authority (PoA) [consensus protocol](index.md). QBFT is the recommended enterprise-grade consensus protocol for private networks.
In QBFT networks, approved accounts, known as validators, validate transactions and blocks. Validators take turns to create the next block. Before inserting the block onto the chain, a super-majority (greater than or equal to 2/3) of validators must first sign the block.
Existing validators propose and vote to [add or remove validators](#add-and-remove-validators).
You can [create a private network using QBFT](../../../tutorials/qbft.md).
:::caution
Configure your network to ensure you never lose more than 1/3 of your validators.
If more than 1/3 of validators stop participating, the network stops creating new blocks and stalls.
It might take significant time to recover after nodes are restarted.
:::
:::tip HSM-backed validator keys
For QBFT validators, [node addresses](../../../../public-networks/concepts/node-keys.md) are validator addresses.
To store a validator's node key in a Hardware Security Module (HSM) instead of
on disk, use a security module plugin, such as the
[Besu HSM plugin](https://github.com/besu-eth/besu-hsm-plugin), with the
[`--security-module`](../../../../public-networks/reference/options.md#security-module)
option.
:::
## Genesis file
To use QBFT, define a [genesis file](../../../../public-networks/concepts/genesis-file.md) that contains the QBFT properties.
The genesis file differs depending on the [validator management method](#add-and-remove-validators) you intend to use.
:::note
You can use a [transitions](#transitions) to change the `blockperiodseconds` or validator management method of the network at a later time.
:::
```json
{
"config": {
"chainid": 1337,
"berlinBlock": 0,
"qbft": {
"epochlength": 30000,
"blockperiodseconds": 5,
"requesttimeoutseconds": 10
}
},
"nonce": "0x0",
"timestamp": "0x5b3d92d7",
"extraData": "0xf87aa00000000000000000000000000000000000000000000000000000000000000000f8549464a702e6263b7297a96638cac6ae65e6541f4169943923390ad55e90c237593b3b0e401f3b08a0318594aefdb9a738c9f433e5b6b212a6d62f6370c2f69294c7eeb9a4e00ce683cf93039b212648e01c6c6b78c080c0",
"gasLimit": "0x29b92700",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"64d9be4177f418bcf4e56adad85f33e3a64efe22": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"9f66f8a0f0a6537e4a36aa1799673ea7ae97a166": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"a7f25969fb6f3d5ac09a88862c90b5ff664557a7": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"f4bbfd32c11c9d63e9b4c77bb225810f840342df": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
```
```json
{
"config": {
"chainid": 1337,
"berlinBlock": 0,
"qbft": {
"epochlength": 30000,
"blockperiodseconds": 5,
"requesttimeoutseconds": 10,
"validatorcontractaddress": "0x0000000000000000000000000000000000007777"
}
},
"nonce": "0x0",
"timestamp": "0x5b3d92d7",
"extraData": "0xe5a00000000000000000000000000000000000000000000000000000000000000000c0c080c0",
"gasLimit": "0x29b92700",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"64d9be4177f418bcf4e56adad85f33e3a64efe22": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"9f66f8a0f0a6537e4a36aa1799673ea7ae97a166": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"a7f25969fb6f3d5ac09a88862c90b5ff664557a7": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"f4bbfd32c11c9d63e9b4c77bb225810f840342df": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"0x0000000000000000000000000000000000007777": {
"comment": "validator smart contract",
"balance": "0",
"code": "0x608060405234801561001057600080fd5b50600436106100a5576000357c0100000000000000000000000000000000000000000000000000000000900480639692ea25116100785780639692ea2514610113578063b4ec9ac114610126578063b7ab4db514610139578063c76f24371461014e57600080fd5b80631c5a9d9c146100aa578063508adcfc146100bf57806351b42b00146100db5780635dc43899146100e3575b600080fd5b6100bd6100b8366004611399565b610161565b005b6100c860035481565b6040519081526020015b60405180910390f35b6100bd6104aa565b6100f66100f1366004611399565b61074e565b6040805193845260208401929092521515908201526060016100d2565b6100bd610121366004611399565b610bbd565b6100bd610134366004611399565b610deb565b6101416110a3565b6040516100d291906113c9565b6100bd61015c366004611399565b611105565b3360009081526001602052604090205460ff1661019c5760405160e560020a62461bcd02815260040161019390611416565b60405180910390fd5b600160a060020a03811661021b5760405160e560020a62461bcd02815260206004820152602860248201527f63616e6e6f742061637469766174652076616c696461746f722077697468206160448201527f64647265737320300000000000000000000000000000000000000000000000006064820152608401610193565b60005b6000548110156102b7576000818154811061023b5761023b611505565b600091825260209091200154600160a060020a03838116911614156102a55760405160e560020a62461bcd02815260206004820152601b60248201527f76616c696461746f7220697320616c72656164792061637469766500000000006044820152606401610193565b806102af816114b8565b91505061021e565b33600090815260016020526040902054610100900460ff16156103345733600090815260016020526040812054815484929162010000900460ff1690811061030157610301611505565b9060005260206000200160006101000a815481600160a060020a030219169083600160a060020a03160217905550610432565b600054610100116103b05760405160e560020a62461bcd02815260206004820152602e60248201527f6e756d626572206f662076616c696461746f72732063616e6e6f74206265206c60448201527f6172676572207468616e203235360000000000000000000000000000000000006064820152608401610193565b3360009081526001602081905260408220805461ff001981166101009081178355845460ff16620100000262ffff001990921691909117179055815490810182559080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563018054600160a060020a038416600160a060020a03199091161790555b600160a060020a0382166000818152600260205260408082208054600160a060020a03191633908117909155915490519192917fbdea108da876d927928b65816d521f940fd6dc068dc0e02ba434e0ed0f2d915f9161049e916001909182521515602082015260400190565b60405180910390a35050565b3360009081526001602052604090205460ff166104dc5760405160e560020a62461bcd02815260040161019390611416565b6000546001106105315760405160e560020a62461bcd02815260206004820181905260248201527f63616e6e6f742064656163746976617465206c6173742076616c696461746f726044820152606401610193565b33600090815260016020526040902054610100900460ff166105be5760405160e560020a62461bcd02815260206004820152602860248201527f73656e64657220646f6573206e6f74206861766520616e20616374697665207660448201527f616c696461746f720000000000000000000000000000000000000000000000006064820152608401610193565b336000908152600160205260408120805461ff0019169081905581546201000090910460ff1691908190839081106105f8576105f8611505565b60009182526020822001548154600160a060020a03909116925081906106209060019061148a565b8154811061063057610630611505565b60009182526020822001548154600160a060020a03909116925082919060ff861690811061066057610660611505565b60009182526020808320919091018054600160a060020a031916600160a060020a03948516179055838316825260028152604080832054909316825260019052908120805462ff000019166201000060ff8716021790558054806106c6576106c66114ec565b6000828152602080822060001990840181018054600160a060020a03199081169091559301909355600160a060020a03851680825260028452604080832080549094169093558154835190815293840191909152339290917fbdea108da876d927928b65816d521f940fd6dc068dc0e02ba434e0ed0f2d915f910160405180910390a3505050565b336000908152600160205260408120548190819060ff166107845760405160e560020a62461bcd02815260040161019390611416565b60005b600160a060020a03851660009081526004602052604090205481101561082357600160a060020a038516600090815260046020526040812080546001929190849081106107d6576107d6611505565b6000918252602080832090910154600160a060020a0316835282019290925260400190205460ff1615610811578361080d816114b8565b9450505b8061081b816114b8565b915050610787565b5060026003546108339190611465565b831115610b8657600160a060020a038416600090815260046020526040812061085b9161135f565b600160a060020a03841660009081526001602052604090205460ff1615610ab0576003805490600061088c836114a1565b9091555050600160a060020a038416600090815260016020526040902054610100900460ff1615610a89576000546001106109325760405160e560020a62461bcd02815260206004820152603860248201527f63616e6e6f742072656d6f766520616c6c6f776564206163636f756e7420776960448201527f7468206c617374206163746976652076616c696461746f7200000000000000006064820152608401610193565b600160a060020a03841660009081526001602052604081205481546201000090910460ff169160029181908490811061096d5761096d611505565b6000918252602080832090910154600160a060020a0316835282019290925260400181208054600160a060020a0319169055805481906109af9060019061148a565b815481106109bf576109bf611505565b60009182526020822001548154600160a060020a03909116925082919060ff85169081106109ef576109ef611505565b600091825260208220018054600160a060020a031916600160a060020a039390931692909217909155805480610a2757610a276114ec565b6000828152602080822083016000199081018054600160a060020a0319169055909201909255600160a060020a0392831682526002815260408083205490931682526001905220805460ff909216620100000262ff0000199092169190911790555b600160a060020a0384166000908152600160205260409020805462ffffff19169055610b32565b60038054906000610ac0836114b8565b909155505060408051606081018252600180825260006020808401828152848601838152600160a060020a038b16845293909152939020915182549351915160ff16620100000262ff0000199215156101000261ff00199215159290921661ffff199095169490941717169190911790555b600160a060020a03841660008181526001602090815260409182902054915160ff909216151582527f94154efdb7741591680558a88682943a481f1a468cb81f46fe7f8cead2e40519910160405180910390a25b826002600354610b969190611465565b610ba190600161144d565b6002600354610bb09190611465565b9196909550931192915050565b3360009081526001602052604090205460ff16610bef5760405160e560020a62461bcd02815260040161019390611416565b60005b600160a060020a038216600090815260046020526040902054811015610d4b57600160a060020a0382166000908152600460205260409020805433919083908110610c3f57610c3f611505565b600091825260209091200154600160a060020a03161415610d3957600160a060020a03821660009081526004602052604090208054610c809060019061148a565b81548110610c9057610c90611505565b6000918252602080832090910154600160a060020a03858116845260049092526040909220805491909216919083908110610ccd57610ccd611505565b60009182526020808320919091018054600160a060020a031916600160a060020a039485161790559184168152600490915260409020805480610d1257610d126114ec565b60008281526020902081016000199081018054600160a060020a0319169055019055610d4b565b80610d43816114b8565b915050610bf2565b50600160a060020a0381166000818152600460205260409020546003543392917f91ad81c76cda7c0ccc324838ae74757eab38b250da52daab154daf408cb3bcba91610d9990600290611465565b610da490600161144d565b600160a060020a0386166000908152600160208181526040928390205483519586529085019390935260ff909216159083015260608201526080015b60405180910390a350565b3360009081526001602052604090205460ff16610e1d5760405160e560020a62461bcd02815260040161019390611416565b600160a060020a038116610e765760405160e560020a62461bcd02815260206004820152601f60248201527f6163636f756e7420746f2062652061646465642063616e6e6f742062652030006044820152606401610193565b600160a060020a03811660009081526001602081905260409091205460ff16151514610f0d5760405160e560020a62461bcd02815260206004820152602a60248201527f6163636f756e7420746f2072656d6f7665206973206e6f74206f6e207468652060448201527f616c6c6f77206c697374000000000000000000000000000000000000000000006064820152608401610193565b60005b600160a060020a038216600090815260046020526040902054811015610ffb57600160a060020a0382166000908152600460205260409020805433919083908110610f5d57610f5d611505565b600091825260209091200154600160a060020a03161415610fe95760405160e560020a62461bcd02815260206004820152602a60248201527f73656e6465722068617320616c726561647920766f74656420746f2072656d6f60448201527f7665206163636f756e74000000000000000000000000000000000000000000006064820152608401610193565b80610ff3816114b8565b915050610f10565b50600160a060020a0381166000818152600460209081526040822080546001810182558184529183209091018054600160a060020a0319163390811790915591839052546003549192917f91ad81c76cda7c0ccc324838ae74757eab38b250da52daab154daf408cb3bcba919061107490600290611465565b61107f90600161144d565b60408051928352602083019190915260009082018190526060820152608001610de0565b606060008054806020026020016040519081016040528092919081815260200182805480156110fb57602002820191906000526020600020905b8154600160a060020a031681526001909101906020018083116110dd575b5050505050905090565b3360009081526001602052604090205460ff166111375760405160e560020a62461bcd02815260040161019390611416565b600160a060020a03811660009081526001602052604090205460ff16156111c95760405160e560020a62461bcd02815260206004820152602b60248201527f6163636f756e7420746f2061646420697320616c7265616479206f6e2074686560448201527f20616c6c6f77206c6973740000000000000000000000000000000000000000006064820152608401610193565b60005b600160a060020a0382166000908152600460205260409020548110156112b757600160a060020a038216600090815260046020526040902080543391908390811061121957611219611505565b600091825260209091200154600160a060020a031614156112a55760405160e560020a62461bcd02815260206004820152602760248201527f73656e6465722068617320616c726561647920766f74656420746f206164642060448201527f6163636f756e74000000000000000000000000000000000000000000000000006064820152608401610193565b806112af816114b8565b9150506111cc565b50600160a060020a0381166000818152600460209081526040822080546001810182558184529183209091018054600160a060020a0319163390811790915591839052546003549192917f91ad81c76cda7c0ccc324838ae74757eab38b250da52daab154daf408cb3bcba919061133090600290611465565b61133b90600161144d565b60408051928352602083019190915260019082015260006060820152608001610de0565b508054600082559060005260206000209081019061137d9190611380565b50565b5b808211156113955760008155600101611381565b5090565b6000602082840312156113ab57600080fd5b8135600160a060020a03811681146113c257600080fd5b9392505050565b6020808252825182820181905260009190848201906040850190845b8181101561140a578351600160a060020a0316835292840192918401916001016113e5565b50909695505050505050565b6020808252601f908201527f73656e646572206973206e6f74206f6e2074686520616c6c6f77206c69737400604082015260600190565b60008219821115611460576114606114d3565b500190565b6000826114855760e060020a634e487b7102600052601260045260246000fd5b500490565b60008282101561149c5761149c6114d3565b500390565b6000816114b0576114b06114d3565b506000190190565b60006000198214156114cc576114cc6114d3565b5060010190565b60e060020a634e487b7102600052601160045260246000fd5b60e060020a634e487b7102600052603160045260246000fd5b60e060020a634e487b7102600052603260045260246000fdfea26469706673582212200c3e9c07521b155532c0de1605aae52f4ae953670f0afb0f30d320580b93213d64736f6c63430008070033",
"storage": {
"0000000000000000000000000000000000000000000000000000000000000000": "0000000000000000000000000000000000000000000000000000000000000002",
"290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563": "0000000000000000000000009a6d82ef3912d5ab60473124bccd2f2a640769d7",
"290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564": "00000000000000000000000065463bf6268e5cc409b6501ec846487b935a1446",
"aedead2c33b41c31b4afd2246c6bf5131c209d4b0ca6c2247778ac7be7443a00": "0000000000000000000000000000000000000000000000000000000000000101",
"33784757d5da236467d27a7c5b0cc5aa9026ca3b79e29106a67a5e93c292a523": "0000000000000000000000000000000000000000000000000000000000010101",
"35aba1eb0bbe741ac01e5b6ce584bc042b1a0b7d115eb8f7dd02a1a1de2fd14d": "000000000000000000000000fe3b557e8fb62b89f4916b721be55ceb828dbd73",
"0d9217f0a1f7c602fd67052d20171ff73b156d1b87ea258cb6a5d94f71298158": "000000000000000000000000627306090abab3a6e1400e9345bc60c78a8bef57",
"0000000000000000000000000000000000000000000000000000000000000003": "0000000000000000000000000000000000000000000000000000000000000002"
},
"version": "0x01"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
```
You can configure the following properties in the `qbft` configuration object:
- `blockperiodseconds` - The minimum block time, in seconds.
The default is 1.
- `emptyblockperiodseconds` - The minimum time between empty blocks, in seconds.
Use this to reduce empty block production while still producing blocks more quickly when transactions are pending.
The default is 0, which disables the empty block delay.
- `epochlength` - The number of blocks after which to reset all votes.
The default is 30000.
- `requesttimeoutseconds` - The timeout for each consensus round before a round change, in seconds.
The default is 1.
- `blockreward` - Reward amount in Wei to reward the beneficiary.
The default is 0.
Specify a hexadecimal value with a `0x` prefix or a decimal string value.
If set, all nodes on the network must use the identical value.
- `validatorcontractaddress` - Address of the validator smart contract. Required only if using a contract validator selection. The address must be identical to the address in the `alloc` section. This option can also be used in the [transitions](#transitions) configuration item if swapping [validator management methods](#add-and-remove-validators) in an existing network.
- `startblock` - Block number at which QBFT starts.
Use this when [migrating from IBFT 2.0 to QBFT](migrate-from-ibft-to-qbft.md).
- `miningbeneficiary` - Beneficiary of the `blockreward`.
If omitted, the validator that proposes the block receives the reward.
If set, all nodes on the network must use the same beneficiary.
:::caution
We don't recommend changing `epochlength` in a running network. Changing the `epochlength` after genesis can result in illegal blocks.
:::
Invalid block header error
When adding a new node, if a `TimeStampMoreRecentThanParent | Invalid block header` error occurs, the genesis file of the new node specifies a higher `blockperiodseconds` than the imported chain. The imported chain makes new blocks faster than the genesis file allows and Besu rejects them with this error. This error most often occurs when importing chains from older versions of Besu.
Decrease the `blockperiodseconds` in the new QBFT genesis file to a lower value that satisfies the block header validation.
If the error reads `| TimestampMoreRecentThanParent | Invalid block header: timestamp 1619660141 is only 3 seconds newer than parent timestamp 1619660138. Minimum 4 seconds`, decrease the `blockperiodseconds` from 4 seconds to 3 seconds to match the imported chain.
After you update the new genesis file, if the imported chain has a `blockperiodseconds` value set lower than you prefer, you can adjust it by [configuring the block time on an existing QBFT network](#configure-block-time-on-an-existing-network).
The properties with specific values in the QBFT genesis files are:
- `difficulty` - `0x1`
- `mixHash` - `0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365` for Istanbul block identification
To start a node on a QBFT private network, use the [`--genesis-file`](../../../../public-networks/reference/options.md#genesis-file) option to specify the custom genesis file.
### Extra data
The `extraData` property is an RLP encoding of:
- 32 bytes of vanity data.
- If using:
- [Block header validator selection](#add-and-remove-validators-using-block-headers), a list of validator addresses.
- [Contract validator selection](#add-and-remove-validators-using-a-smart-contract), no validators.
- Any validator votes. No vote is included in the genesis block.
- The round the block was created on. The round in the genesis block is 0.
- A list of seals of the validators (signed block hashes). No seals are included in the genesis block.
When using block header validator selection, the important information in the genesis block extra data is the list of validators. All other details have empty values in the genesis block.
:::info
When using contract validator selection to manage validators, the list of validators is configured
in the `alloc` property's `storage` section.
View the [example smart contract](https://github.com/ConsenSys/validator-smart-contracts) for more
information on how to generate the `storage` section.
:::
Formally, `extraData` in the genesis block contains:
- If using block header validator selection: `RLP([32 bytes Vanity, List, No Vote, Round=Int(0), 0 Seals])`.
- If using contract validator selection: `RLP([32 bytes Vanity, 0 Validators, No Vote, Round=Int(0), 0 Seals])`.
:::info
RLP encoding is a space-efficient object serialization scheme used in Ethereum.
:::
#### Generate extra data
To generate the `extraData` RLP string for inclusion in the genesis file, use the [`rlp encode`](../../../reference/subcommands.md#encode) Besu subcommand.
```bash title="Example"
besu rlp encode --from=toEncode.json --type=QBFT_EXTRA_DATA
```
Where the `toEncode.json` file contains a list of the initial validators, in ascending order. To write the validator address and copy it to the `toEncode.json` file, use the [`public-key export-address`](../../../../public-networks/reference/subcommands.md#export-address) Besu subcommand. For example:
```json title="Initial validators in toEncode.json file"
[
"0x4592c8e45706cc08b8f44b11e43cba0cfc5892cb",
"0x06e23768a0f59cf365e18c2e0c89e151bcdedc70",
"0xc5327f96ee02d7bcbc1bf1236b8c15148971e1de",
"0xab5e7f4061c605820d3744227eed91ff8e2c8908"
]
```
Copy the RLP encoded data to the `extraData` property in the genesis file.
```bash title="RLP encoded data"
0xf87aa00000000000000000000000000000000000000000000000000000000000000000f854944592c8e45706cc08b8f44b11e43cba0cfc5892cb9406e23768a0f59cf365e18c2e0c89e151bcdedc7094c5327f96ee02d7bcbc1bf1236b8c15148971e1de94ab5e7f4061c605820d3744227eed91ff8e2c8908c080c0
```
When you start the network, the four nodes previously specified in `toEncode.json` are the validators for the network.
### Block time
When the protocol receives a new chain head, the block time (`blockperiodseconds`) timer starts. When `blockperiodseconds` expires, the round timeout (`requesttimeoutseconds`) timer starts and the protocol proposes a new block.
If `requesttimeoutseconds` expires before adding the proposed block, a round change occurs, with the block time and timeout timers reset. The timeout period for the new round is two times `requesttimeoutseconds`. The timeout period continues to double each time a round fails to add a block.
Usually, the protocol adds the proposed block before reaching `requesttimeoutseconds`. A new round then starts, resetting the block time and round timeout timers. When `blockperiodseconds` expires, the protocol proposes the next new block.
:::danger
If more than 1/3 of validators stop participating, new blocks can no longer be created and `requesttimeoutseconds` doubles with each round change. The quickest method to resume block production is to restart all validators, which resets `requesttimeoutseconds` to its genesis value.
:::
Once `blockperiodseconds` is over, the time from proposing a block to adding the block is small (usually around one second) even in networks with geographically dispersed validators.
#### Tune block timeout
To tune the block timeout for your network deployment:
1. Set `blockperiodseconds` to your desired block time and `requesttimeoutseconds` to two times `blockperiodseconds`.
1. Reduce `requesttimeoutseconds` until you start to see round changes occurring.
1. Increase `requesttimeoutseconds` to the value where round changes are no longer occurring.
:::tip
View [`TRACE` logs](../../../../public-networks/reference/api/admin.md#admin_changeloglevel) to see round change log messages.
:::
Use a [transition](#transitions) to update the `blockperiodseconds` in an existing network.
### Advanced configuration options
The `qbft` object also supports the following optional properties:
- `gossipedHistoryLimit` - Number of previous QBFT messages to keep in history for gossip.
The default is 1000.
- `messageQueueLimit` - In large networks with limited resources, increasing the message queue limit might help with message activity surges. The default is 1000.
- `duplicateMessageLimit` - If the same node is retransmitting messages, increasing the duplicate message limit might reduce the number of retransmissions. A value of two to three times the number of validators is usually enough. The default is 100.
- `futureMessagesLimit` - The future messages buffer holds messages for a future chain height. For large networks, increasing the future messages limit might be useful. The default is 1000.
- `futureMessagesMaxDistance` - The maximum height from the current chain height for buffering messages in the future messages buffer. The default is 10.
### Post-Merge configuration
After [The Merge](https://ethereum.org/en/upgrades/merge/), the following block fields are modified or deprecated. Their fields **must** contain only the constant values from the following chart.
| Field | Constant value | Comment |
|------------------|----------------------------------------------------------------------|----------------------------|
| **`ommersHash`** | `0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347` | `= Keccak256(RLP([]))` |
| **`difficulty`** | `0` | Replaced with `prevrandao` |
| **`mixHash`** | `0x0000000000000000000000000000000000000000000000000000000000000000` | Replaced with `prevrandao` |
| **`nonce`** | `0x0000000000000000` | |
| **`ommers`** | `[]` | `RLP([]) = 0xc0` |
Additionally, [`extraData`](#extra-data) is limited to the 32 bytes of vanity data after The Merge.
## Add and remove validators
QBFT provides two methods to manage validators:
- [Block header validator selection](#add-and-remove-validators-using-block-headers) - Existing validators propose and vote to add or remove validators using the QBFT JSON-RPC API methods.
- [Contract validator selection](#add-and-remove-validators-using-a-smart-contract) - Use a smart contract to specify the validators used to propose and validate blocks.
You can use [transitions](#transitions) to swap between block header validator selection and contract validator selection in an existing network.
For block header validator selection, initial validators are configured in the genesis file's [`extraData`](#extra-data) property, whereas the initial validators when using the contract validator selection method are configured in the genesis file's `storage` section.
### Add and remove validators using block headers
Enable the HTTP interface with [`--rpc-http-enabled`](../../../../public-networks/reference/options.md#rpc-http-enabled) or the WebSockets interface with [`--rpc-ws-enabled`](../../../../public-networks/reference/options.md#rpc-ws-enabled).
The QBFT API methods are disabled by default. To enable them, specify the [`--rpc-http-api`](../../../../public-networks/reference/options.md#rpc-http-api) or [`--rpc-ws-api`](../../../../public-networks/reference/options.md#rpc-ws-api) option and include `QBFT`.
The methods to add or remove validators are:
- [`qbft_getPendingVotes`](../../../reference/api/qbft.md#qbft_getpendingvotes).
- [`qbft_proposeValidatorVote`](../../../reference/api/qbft.md#qbft_proposevalidatorvote).
- [`qbft_discardValidatorVote`](../../../reference/api/qbft.md#qbft_discardvalidatorvote).
To view validator metrics for a specified block range, use [`qbft_getSignerMetrics`](../../../reference/api/qbft.md#qbft_getsignermetrics).
:::note
If network conditions render it impossible to add and remove validators by voting, you can [add and remove validators without voting](add-validators-without-voting.md).
:::
#### Add a validator
To propose adding a validator, call [`qbft_proposeValidatorVote`](../../../reference/api/qbft.md#qbft_proposevalidatorvote), specifying the address of the proposed validator and `true`. A majority of validators must execute the call.
```bash title="JSON-RPC qbft_proposeValidatorVote request example"
curl -X POST --data '{"jsonrpc":"2.0","method":"qbft_proposeValidatorVote","params":["0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73", true], "id":1}'
```
When the validator proposes the next block, the protocol inserts one proposal received from [`qbft_proposeValidatorVote`](../../../reference/api/qbft.md#qbft_proposevalidatorvote) into the block. If blocks include all proposals, subsequent blocks proposed by the validator will not contain a vote.
When more than 50% of the existing validators have published a matching proposal, the protocol adds the proposed validator to the validator pool and the validator can begin validating blocks.
To return a list of validators and confirm the addition of a proposed validator, use [`qbft_getValidatorsByBlockNumber`](../../../reference/api/qbft.md#qbft_getvalidatorsbyblocknumber).
```bash title="JSON-RPC qbft_getValidatorsByBlockNumber request example"
curl -X POST --data '{"jsonrpc":"2.0","method":"qbft_getValidatorsByBlockNumber","params":["latest"], "id":1}'
```
To discard your proposal after confirming the addition of a validator, call [`qbft_discardValidatorVote`](../../../reference/api/qbft.md#qbft_discardvalidatorvote), specifying the address of the proposed validator.
```bash title="JSON-RPC qbft_discardValidatorVote request example"
curl -X POST --data '{"jsonrpc":"2.0","method":"qbft_discardValidatorVote","params":["0xFE3B557E8Fb62b89F4916B721be55cEb828dBd73"], "id":1}'
```
#### Remove a validator
The process for removing a validator is the same as adding a validator except you specify `false` as the second parameter of [`qbft_proposeValidatorVote`](../../../reference/api/qbft.md#qbft_proposevalidatorvote).
#### Epoch transition
At each epoch transition, QBFT discards all pending votes collected from received blocks. Existing proposals remain in effect and validators re-add their vote the next time they create a block.
An epoch transition occurs every `epochLength` blocks. Define `epochlength` in the QBFT genesis file.
### Add and remove validators using a smart contract
Users can create their own smart contracts to add or remove validators based on their organizational requirements. View the [example smart contract](https://github.com/ConsenSys/validator-smart-contracts) for more information on how to create and deploy the smart contract.
You can pre-deploy the validator smart contract in a new QBFT network by specifying the contract details in the [genesis file](qbft.md#genesis-file). For existing QBFT networks you need to compile and deploy the contract using a transaction, then obtain the contract address from the receipt and use that in a [transition](#swap-validator-management-methods).
:::info
You can't use the JSON-RPC methods to add or remove validators when using a smart contract to manage nodes.
You must interact with the contract functions using transactions.
:::
:::note
If network conditions render it impossible to add and remove validators using a smart contract, you can [override smart contract validators](add-validators-without-voting.md#override-smart-contract-validators).
:::
### Minimum number of validators
QBFT requires four validators to be Byzantine fault tolerant. Byzantine fault tolerance is the ability for a blockchain network to function correctly and reach consensus despite nodes failing or propagating incorrect information to peers.
## Transitions
The `transitions` genesis configuration item allows you to specify a future block number at which to
change the QBFT network configuration in an existing network.
For example, you can update the [block time](#configure-block-time-on-an-existing-network),
[block reward](#configure-block-rewards-on-an-existing-network),
[validator management method](#swap-validator-management-methods), or
[mining beneficiary](#configure-the-mining-beneficiary-on-an-existing-network).
:::caution
Do not specify a transition block in the past.
Specifying a transition block in the past can result in unexpected behavior, such as causing the
network to fork.
:::
### Configure block time on an existing network
To update an existing network with a new `blockperiodseconds`:
1. Stop all nodes in the network.
2. In the [genesis file](#genesis-file), add the `transitions` configuration item where:
- `` is the upcoming block at which to change `blockperiodseconds`.
- `` is the updated value for `blockperiodseconds`.
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
},
"transitions": {
"qbft": [
{
"block": ,
"blockperiodseconds":
}
]
}
},
...
}
```
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
},
"transitions": {
"qbft": [
{
"block": 1240,
"blockperiodseconds": 4
}
]
}
},
...
}
```
3. Restart all nodes in the network using the updated genesis file.
4. To verify the changes after the transition block, view the Besu logs and check that the time
difference between each block matches the updated block period.
### Configure block rewards on an existing network
To update an existing network with a new `blockreward`:
1. Stop all nodes in the network.
2. In the [genesis file](#genesis-file), add the `transitions` configuration item where:
- `` is the upcoming block at which to change `blockreward`.
- `` is the updated value for `blockreward`.
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
"blockreward": "5000000000000000"
},
"transitions": {
"qbft": [
{
"block": ,
"blockreward":
},
{
"block": ,
"blockreward":
},
{
"block": ,
"blockreward":
}
]
}
},
...
}
```
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
"blockreward": "5000000000000000"
},
"transitions": {
"qbft": [
{
"block": 10,
"blockreward": "6000000000000000"
},
{
"block": 15,
"blockreward": "75000000000000000"
},
{
"block": 20,
"blockreward": "0"
}
]
}
},
...
}
```
:::note
You can add multiple `blockreward` updates in one transition object by specifying multiple future blocks.
:::
3. Restart all nodes in the network using the updated genesis file.
### Swap validator management methods
To swap between block header validator selection and contract validator selection methods in an existing network:
1. Stop all nodes in the network.
2. In the [genesis file](#genesis-file), add the `transitions` configuration item where:
- `` is the upcoming block at which to change the validator selection method.
- `` is the validator selection mode to switch to. Valid options are `contract` and `blockheader`.
- `` is the smart contract address, if switching to the contract validator selection method.
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 5,
"epochlength": 30000,
"requesttimeoutseconds": 10
},
"transitions": {
"qbft": [
{
"block": ,
"validatorselectionmode": ,
"validatorcontractaddress":
}
]
}
},
...
}
```
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 5,
"epochlength": 30000,
"requesttimeoutseconds": 10
},
"transitions": {
"qbft": [
{
"block": 102885,
"validatorselectionmode": "contract",
"validatorcontractaddress": "0x0000000000000000000000000000000000007777"
}
]
}
},
...
}
```
3. Restart all nodes in the network using the updated genesis file.
### Configure the mining beneficiary on an existing network
To update an existing network with a new mining beneficiary:
1. Stop all nodes in the network.
2. In the [genesis file](#genesis-file), add the `transitions` configuration item where:
- `` is the upcoming block at which to change `miningbeneficiary`.
- `` is the updated 20-byte address for `miningbeneficiary`. Starting at ``, block rewards go to this address.
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 5,
"epochlength": 30000,
"requesttimeoutseconds": 10
},
"transitions": {
"qbft": [
{
"block": ,
"miningbeneficiary":
},
{
"block": ,
"miningbeneficiary":
}
]
}
},
...
}
```
```json
{
"config": {
...
"qbft": {
"blockperiodseconds": 5,
"epochlength": 30000,
"requesttimeoutseconds": 10
},
"transitions": {
"qbft": [
{
"block": 10000,
"miningbeneficiary": "0x0000000000000000000000000000000000000002",
},
{
"block": 20000,
"miningbeneficiary": "",
}
]
}
},
...
}
```
:::note
Setting the `miningbeneficiary` to an empty value clears out any override so that block rewards go to the block producer rather than a global override address.
:::
3. Restart all nodes in the network using the updated genesis file.
---
## Pre-deploy a contract
# Pre-deploy contracts in the genesis file
To pre-deploy contracts when starting Besu, specify the contract code in the [genesis file](../../../public-networks/concepts/genesis-file.md).
```json title="Contract code in the genesis file"
{
...
"alloc": {
"0x0ffd23af8eebc60b3cfdeed6f814988757237314": {
"balance": "0x100000000000000000000000000000000000000000000000000",
"code": "0x6080604052600436106043576000357c010000000000000000000000000000000000000000000000000000000090048063010fc84214604857806355241077146070575b600080fd5b348015605357600080fd5b50605a60a7565b6040518082815260200191505060405180910390f35b348015607b57600080fd5b5060a560048036036020811015609057600080fd5b810190808035906020019092919050505060ad565b005b60005481565b80600081905550807f04474795f5b996ff80cb47c148d4c5ccdbe09ef27551820caa9c2f8ed149cce360405160405180910390a25056fea165627a7a7230582038cb7ea327af8f73feabcfbff64498f1e74831e67f7c75286760d3845c6747c70029",
"storage": {
"7aa07e0c924147697605046b7c2c32645b7bbfb41e0ac5d0a84ac93cbb759798": "0000000000000000000000000000000000000000000000000000000000000001",
"cea2b0602db61f92b76ec4402875cc38eedc9fc425cb1b697fc2265d50fc20fb": "0000000000000000000000000000000000000000000000000000000000000001",
}
}
},
...
}
```
The contract code in the genesis file defines the:
- Address.
- Balance.
- Bytecode.
- Key value pairs for contract storage.
---
## Alternative elliptic curves
# Configure alternative elliptic curves
:::caution
Configuring alternative elliptic curves is an early access feature.
:::
By default, Besu uses the Ethereum standard `secp256k1` elliptic curve (EC). However, when running nodes in a private network, it is possible to configure an alternative elliptic curve.
The configuration for what elliptic curve Besu will use is done in the network configuration section of genesis file, using the [`ecCurve`](../../../public-networks/reference/genesis-items.md#configuration-items) key:
```bash
{
"genesis": {
"config": {
"ecCurve": "secp256k1",
[...]
},
[...]
}
```
:::danger Important
All nodes in the network **MUST** use the same elliptic curve. Nodes with different EC configuration from the network won't be able to send messages to other nodes or verify transactions and blocks.
:::
Besu supports the following elliptic curves:
- `secp256k1` (Ethereum default)
- `secp256r1`
---
## Free gas network
# Configure free gas networks
Transactions use computational resources so have an associated cost. Gas is the cost unit and the gas price is the price per gas unit. The transaction cost is the gas used \* gas price.
In public networks, the account submitting the transaction pays the transaction cost, in Ether. The miner (or validator in PoA networks) that includes the transaction in a block receives transaction cost.
In many private networks, network participants run the validators and do not require gas as an incentive. Networks that don't require gas as an incentive usually configure the gas price to be zero (that is, free gas). Some private networks might allocate Ether and use a non-zero gas price to limit resource use.
:::tip
We use the term _free gas network_ to refer to a network with a gas price of zero. A network with a gas price of zero is also known as a _zero gas network_ or _no gas network_.
:::
:::note
Some pre-crafted transactions require the deployment account to have gas available. For example, the transaction that creates the smart contract in [EIP-1820](https://eips.ethereum.org/EIPS/eip-1820).
:::
In a free gas network, transactions still use gas but the gas price is zero, meaning the transaction cost is zero. Transaction cost = gas used \* 0 (the gas price).
## Configure free gas in Besu
When gas is free, limiting block and contract sizes is less important. In free gas networks, we increase the block size limit and set the contract size limit to the maximum value.
### 1. Set the block size
If you want to remove gas from consideration and don't mind blocks potentially taking longer to create, in the genesis file set the block size limit (measured in gas) to the maximum accepted by Hardhat (`0x1fffffffffffff`). In the genesis file, specify `gasLimit` following the `config` key.
```json
{
"config": {
....
},
...
"gasLimit": "0x1fffffffffffff",
....
}
```
If you are more concerned about blocks arriving on time and don't have expensive individual transactions, set `gasLimit` to a value closer to the amount of gas your validators can process in the configured block time.
### 2. Set the contract size
In the `config` section of the genesis file, set the contract size limit to the maximum supported size (in bytes).
```json
(
"config": {
...
"contractSizeLimit": 2147483647,
...
}
...
}
```
### 3. Set a minimum gas price of zero
When starting nodes, set the [minimum gas price](../../../public-networks/reference/options.md#min-gas-price) to zero.
```bash
--min-gas-price=0
```
```bash
min-gas-price=0
```
:::danger Important
In a free gas network, ensure the [minimum gas price](../../../public-networks/reference/options.md#min-gas-price) is set to zero for every node. Any node with a minimum gas price set higher than zero will silently drop transactions with a zero gas price. You can query a node's gas configuration using [`eth_gasPrice`](../../../public-networks/reference/api/eth/fee.md#eth_gasprice).
:::
### 4. Disable the transaction pool balance check
Senders in a free gas network can have a zero balance and still submit valid transactions.
[`--tx-pool-enable-balance-check`](../../../public-networks/reference/options.md#tx-pool-enable-balance-check)
defaults to `true`, which prevents pending transactions from senders with insufficient balance from
being included in the prioritized layer of the [transaction pool](../../../public-networks/concepts/transactions/pool.md).
Set this option to `false` so the balance check doesn't block transactions from zero-balance senders.
```bash
--tx-pool-enable-balance-check=false
```
```bash
tx-pool-enable-balance-check=false
```
### 5. Enable zero base fee if using London fork or later
If your network is configured to use the `londonBlock` or a later hard fork, then you must also enable the `zeroBaseFee` configuration. You must set this on all your nodes. Once it is set, future blocks produced by that node will set a `baseFee` of 0. This is required because the London hard fork (EIP-1559) introduced a non-zero `baseFee` into the block which normally means transactions require gas.
```json
{
"config": {
"londonBlock": 0,
"zeroBaseFee": true,
...
},
...
}
```
If zero base fee is enabled, you cannot specify a value for [`--tx-pool-price-bump`](../../../public-networks/reference/options.md#tx-pool-price-bump).
## Configure free gas in Hardhat
If using Hardhat to develop your free gas network, you also need to configure free gas in Hardhat.
Like setting block and contract size limits to their maximum values for Besu, set the transaction gas limit in Hardhat to the maximum possible.
:::info
Besu does not support private key management. To use Besu with Hardhat, you must configure a [Hardhat wallet](../../../public-networks/how-to/develop/hardhat.md).
:::
### Update `hardhat.config.js`
Update the `hardhat.config.js` file:
1. Set the gas price to zero.
```js
gasPrice: 0;
```
1. Set the gas limit for a transaction (that is, contract creation) to be the block gas limit - 1.
```js
gas: "0x1ffffffffffffe";
```
Setting `gasPrice` to `0` should cover transaction costs for most deployments.
1. Specify `evmVersion` when using the latest Solidity version.
```js
solidity: {
version: "0.8.20",
settings: {
evmVersion: "london", // required for Besu
optimizer: {...},
},
},
```
---
## Client and server TLS
# Configure client TLS
Besu supports TLS for client communication. For example, you can configure TLS for communication between [Web3Signer](https://docs.web3signer.consensys.net/concepts/tls) and Besu.
```mermaid
flowchart TD
dapp["Dapp"]
web3signer["Web3Signer(TLS enabled)"]
besu["Besu(TLS enabled)"]
dapp -->|"eth_sendTransaction🔒TLS"| web3signer
web3signer <-->|"eth_sendRawTransaction🔒TLS"| besu
```
The following instructions allow you to configure client authentication to secure HTTP JSON-RPC
calls.
:::info Secure Websocket JSON-RPC calls
You can configure SSL/TLS authentication for WebSocket calls by enabling
[`--rpc-ws-ssl-enabled`](../../../public-networks/reference/options.md#rpc-ws-ssl-enabled) for
server authentication, and
[`--rpc-ws-ssl-client-auth-enabled`](../../../public-networks/reference/options.md#rpc-ws-ssl-client-auth-enabled) for client authentication.
:::
## Prerequisites
- Besu's password-protected PKCS12 keystore
- File containing the keystore password
## Configure client TLS
Allow clients (for example a dapp, curl, or Web3Signer) to send and receive secure HTTP JSON-RPCs.
**Client prerequisites**:
- [Configure the client for TLS]
- Client's PKCS12 keystore information
### Create the known clients file
The known clients file allows clients with self-signed certificates or non-public certificates to connect to Besu.
Create a file (in this example, `knownClients`) that lists one or more trusted clients. Use the format`` where:
- `` is the Common Name specified in the client certificate.
- `` is the SHA-256 fingerprint of the client certificate.
```bash title="Example"
web3signer 8E:E0:85:9F:FC:2E:2F:21:31:46:0B:82:4C:A6:88:AB:30:34:9A:C6:EA:4F:04:31:ED:0F:69:A7:B5:C2:2F:A7
curl FC:18:BF:39:45:45:9A:15:46:76:A6:E7:C3:94:64:B8:34:84:A3:8E:B8:EA:67:DC:61:C0:29:E6:38:B8:B7:99
```
You can use [`openssl`](https://www.openssl.org/) or [`keytool`](https://docs.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html) to display the SHA256 fingerprint.
```
keytool -list -v -keystore -storetype PKCS12 -storepass `.
```
### Start Besu
```bash
besu --rpc-http-enabled --rpc-http-tls-enabled --rpc-http-tls-client-auth-enabled --rpc-http-tls-keystore-file=/Users/me/my_node/keystore.pfx --rpc-http-tls-keystore-password-file=/Users/me/my_node/keystorePassword --rpc-http-tls-known-clients-file=/Users/me/my_node/knownClients --rpc-http-tls-cipher-suite=TLS_AES_256_GCM_SHA384 --rpc-http-tls-protocol=TLSv1.3,TLSv1.2
```
The command line:
- Enables the HTTP JSON-RPC service using the [`--rpc-http-enabled`](../../../public-networks/reference/options.md#rpc-http-enabled) option.
- Enables TLS for the HTTP JSON-RPC service using the [`--rpc-http-tls-enabled`](../../../public-networks/reference/options.md#rpc-http-tls-enabled) option.
- Enables TLS client authentication using the [`--rpc-http-tls-client-auth-enabled`](../../../public-networks/reference/options.md#rpc-http-tls-client-auth-enabled) option.
- Specifies the keystore using the [`--rpc-http-tls-keystore-file`](../../../public-networks/reference/options.md#rpc-http-tls-keystore-file) option.
- Specifies the file that contains the password to decrypt the keystore using the [`--rpc-http-tls-keystore-password-file`](../../../public-networks/reference/options.md#rpc-http-tls-keystore-password-file) option.
- [Specifies the clients](#create-the-known-clients-file) allowed to connect to Besu using the [`--rpc-http-tls-known-clients-file`](../../../public-networks/reference/options.md#rpc-http-tls-known-clients-file) option.
- specifies the Java cipher suites using the [`--rpc-http-tls-cipher-suite`](../../../public-networks/reference/options.md#rpc-http-tls-cipher-suite) option.
- specifies the TLS protocol version using the [`--rpc-http-tls-protocol`](../../../public-networks/reference/options.md#rpc-http-tls-protocol) option.
:::note
Set [`--rpc-http-tls-ca-clients-enabled`](../../../public-networks/reference/options.md#rpc-http-tls-ca-clients-enabled) to `true` to allow access to clients with signed and trusted root CAs.
:::
[Configure the client for TLS]: https://docs.web3signer.consensys.net/how-to/configure-tls
---
## Validators
# Configure validators in a production network
As when [configuring bootnodes](bootnodes.md):
1. Create the [node key pair](../../../public-networks/concepts/node-keys.md) (that is, the private and public key) before starting the validator.
:::tip HSM-backed validator keys
For validators backed by a Hardware Security Module (HSM), create or import the
node key in the HSM before starting Besu.
Configure Besu with a security module plugin, such as the
[Besu HSM plugin](https://github.com/besu-eth/besu-hsm-plugin), using the
[`--security-module`](../../../public-networks/reference/options.md#security-module)
option.
:::
1. When creating validators in the cloud (for example, AWS or Azure), attempt to assign static IP addresses to them. If your network is:
- Publicly accessible, assign an elastic IP address.
- Internal only, specify a private IP address when you create the instance and record this IP address.
We recommend storing validator configuration under source control.
## Number of validators required
Ensure you configure enough validators to allow for redundancy. IBFT 2.0 tolerates `f = (n-1)/3` faulty validators, where:
- `f` is the number of faulty validators
- `n` is the number of validators.
## Adding and removing validators
You can [vote validators in or out of the validator pool].
## Validators as bootnodes
Validators can also be bootnodes. Other than the [usual configuration for bootnodes](bootnodes.md), you do not need to specify any extra configuration when a validator is also a bootnode.
If you remove a validator that is also a bootnode, ensure there are enough remaining bootnodes on the network.
[vote validators in or out of the validator pool]: consensus/ibft.md#add-and-remove-validators
---
## Use Ansible
# Deploy Besu with Ansible
To deploy Besu using Ansible, use the [Besu role](https://galaxy.ansible.com/consensys/hyperledger_besu) published on Galaxy.
For more information, select **Documentation** on the [Ansible Galaxy Besu page](https://galaxy.ansible.com/consensys/hyperledger_besu).
:::tip
We strongly recommend automating network creation. Automating makes updates easier and ensures your configuration is synchronized across the network.
:::
---
## Deploy to the cloud
# Deploy Besu to the cloud
When deploying Besu to the cloud:
- Ensure you have enough spread across Availability Zones (AZs) and Regions, especially for bootnodes and validators.
- If your network is a multi-region network, consider using VPC Peering to reduce latency.
- Where required, use VPNs to connect to your on premise systems, or single private chains.
- If deploying to Kubernetes, please refer to the [tutorial](../../tutorials/kubernetes/index.md).
---
## Use Ethstats network monitor
# Connect to Ethstats network monitor
Connect to [Ethstats](https://ethstats.dev) to display real time and historical [statistics](#statistics) about the network and nodes. You can connect to the Ethstats dashboard by [connecting to a client and server](#connect-through-a-client-and-server) or by [connecting through the command line](#connect-through-the-command-line).
## Components
Ethstats consists of:
- A [server](https://github.com/goerli/ethstats-server), which consumes node data received from the client.
- A [client](https://github.com/goerli/ethstats-client), which extracts data from the node and sends it to the server.
- A [dashboard](https://github.com/goerli/ethstats-client#available-dashboards), which displays statistics.
## Statistics
Statistics displayed by Ethstats include:
- Nodes in the network. Metrics for nodes include:
- Information about the last received block such as block number, block hash, transaction count, uncle count, block time, and propagation time.
- Connected peers, whether the node is mining, hash rate, latency, and uptime.
- Charts for block time, block difficulty, block gas limit, block uncles, block transactions, block gas used, block propagation histogram, and top miners.
- IP-based geolocation overview.
- Node logs, which display the data sent by a node.
- Block history, which provides the ability to go back in time and playback the block propagation through the nodes.
## Connect through a client and server
Refer to the external [Ethstats client](https://github.com/goerli/ethstats-client) and [Ethstats server](https://github.com/goerli/ethstats-server) documentation for installing those components and connecting to a dashboard.
## Connect through the command line
You can use command line options to connect a node directly to a [dashboard](https://github.com/goerli/ethstats-client#available-dashboards), without using a client.
Start a node using the [`--ethstats`](../../../public-networks/reference/options.md#ethstats) option to specify the Ethstats server URL. You can specify a contact email to send to the server using [`--ethstats-contact`](../../../public-networks/reference/options.md#ethstats-contact).
```bash
besu --ethstats=Dev-Node-1:secret@127.0.0.1:3001 --ethstats-contact=contact@mail.com
```
:::note
A server must be specified by `--ethstats` in order to use `--ethstats-contact`.
:::
Open the selected dashboard website. Find your node under the list of nodes to see the statistics for the node and the network.

---
## Use Kubernetes
# Deploy Besu with Kubernetes
Use the [reference implementations](https://github.com/ConsenSys/quorum-kubernetes) to install private networks using Kubernetes (K8s). The repository has full support for cloud providers like AWS, Azure, GCP, and IBM, and has production setups that use of identities and cloud-native secret storage services like Azure KeyVault and AWS Secrets Manager.
Refer to the [tutorial](../../tutorials/kubernetes/index.md) and familiarize yourself with the reference implementations, and customize them to your requirements.
---
## How to
This section provides instructional content for private network features.
The following features are shared with [public networks](../../public-networks/index.md) and the content can be found in the public networks section:
- Configure and manage:
- [Use a configuration file](../../public-networks/how-to/configure-besu/index.md)
- [Configure high availability](../../public-networks/how-to/configure-ha/index.md)
- [Use the Besu API](../../public-networks/how-to/use-besu-api/index.md):
- [Use JSON-RPC over HTTP, WS, and IPC](../../public-networks/how-to/use-besu-api/json-rpc.md)
- [Use RPC Pub/Sub over WS](../../public-networks/how-to/use-besu-api/rpc-pubsub.md)
- [Use GraphQL over HTTP](../../public-networks/how-to/use-besu-api/graphql.md)
- [Authenticate JSON-RPC requests](../../public-networks/how-to/use-besu-api/authenticate.md)
- [Access logs using JSON-RPC API](../../public-networks/how-to/use-besu-api/access-logs.md)
- Find and connect to peers:
- [Configure static nodes](../../public-networks/how-to/connect/static-nodes.md)
- [Configure ports](../../public-networks/how-to/connect/configure-ports.md)
- [Manage peers](../../public-networks/how-to/connect/manage-peers.md)
- [Specify NAT method](../../public-networks/how-to/connect/specify-nat.md)
- Configure Java:
- [Install and update Java](../../public-networks/how-to/configure-java/install-update-java.md)
- [Pass JVM options](../../public-networks/how-to/configure-java/pass-jvm-options.md)
- [Manage JVM memory](../../public-networks/how-to/configure-java/manage-memory.md)
- Develop dapps:
- [Use Hardhat](../../public-networks/how-to/develop/hardhat.md)
- [Use client libraries](../../public-networks/how-to/develop/client-libraries.md)
- Troubleshoot:
- [Use EVM tool](../../public-networks/how-to/troubleshoot/evm-tool.md)
- [Trace transactions](../../public-networks/how-to/troubleshoot/trace-transactions.md)
---
## Use Chainlens Explorer
# Use Chainlens Blockchain Explorer
[Chainlens Blockchain Explorer](https://chainlens.com/) supports public and private EVM networks.
You can include Chainlens when generating a private network using the [Developer Quickstart](../../tutorials/quickstart.md).
Chainlens provides an overview of the entire network, including block information, contract
metadata, transaction searches, and [more](https://chainlens.com/).
:::note
In production networks, you must [secure access](../../../public-networks/how-to/use-besu-api/authenticate.md)
to RPC nodes.
:::
## Prerequisites
[Docker and Docker Compose](https://docs.docker.com/compose/install/) installed.
## Start Chainlens
Generate a private network using the [Developer Quickstart](../../tutorials/quickstart.md), with Chainlens enabled:
```bash
npx @consensys-software/besu-dev-quickstart --networkType private --outputPath ./besu-test-network --otel false --chainlens true
```
Start the generated network:
```bash
cd besu-test-network
./run.sh
```
Open `http://localhost:8081/dashboard` in your browser.
Chainlens may take a few minutes to index the latest blocks after the containers start.
If you already generated a private network without Chainlens, generate a new quickstart directory with `--chainlens true`.
The Developer Quickstart adds the Chainlens services to the Docker Compose file at generation time.
## View on Chainlens
After starting Chainlens, you can view information about your network.
:::note
Screenshots in this section are taken from the Chainlens Holesky network.
:::
The **Dashboard** page provides an aggregated view of network activities.

The **Blocks** page shows a real-time view of the finalized blocks.

You can view block details by selecting a block hash or number.

The **Transactions** page shows a paginated view of new and historical transactions.

If you select any transaction hash, you can get the **transaction details.**

The **Contracts** page shows all the smart contracts deployed on the network.

You can view smart contract details by selecting the contract address.

The **Events** page shows all the events generated on the network.

## Stop Chainlens
Chainlens runs as part of the generated quickstart network.
Stop the quickstart containers to stop Chainlens:
```bash
./stop.sh
```
---
## Use Elastic Stack
[Elastic Stack](https://www.elastic.co/elastic-stack/) (ELK) is an open-source log management platform you can use with Besu.
To use ELK, configure the following for your deployment:
- **Filebeat** - This configuration ingests logs.
See the [example Filebeat configuration](https://github.com/ConsenSys/quorum-dev-quickstart/blob/b72a0f64d685c851bf8be399a8e33bbdf0e09982/files/common/filebeat/filebeat.yml).
- **Metricbeat** - This configuration collects metrics from the nodes at regular defined intervals and outputs them to Redis for storage.
Redis provides a highly available mechanism enabling storage by any of the Elastic Beats and pulled by Logstash as required.
See the [example Metricbeat configuration](https://github.com/ConsenSys/quorum-dev-quickstart/blob/b72a0f64d685c851bf8be399a8e33bbdf0e09982/files/common/metricbeat/metricbeat.yml).
- **Pipeline configuration** - This defines the JSON format used for Besu logs and automatically picks up any new log fields.
See the [example pipeline configuration](https://github.com/ConsenSys/quorum-dev-quickstart/blob/b72a0f64d685c851bf8be399a8e33bbdf0e09982/files/common/logstash/pipeline/20_besu.conf).
:::note
The pipeline configuration must match the your log format.
If using the default log format, you can use the [Grok plugin](https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html) to extract the log fields.
:::
---
## Monitoring
Monitoring helps you identify node and network issues. In private networks, you can use the same [monitoring tools](../../../public-networks/how-to/monitor/index.md) as in public networks.
You can also use the following monitoring tools in private networks:
- [Loki](loki.md)
- [Elastic Stack](elastic-stack.md)
- [Splunk](splunk.md)
- [OpenTelemetry](opentelemetry.md)
- [Chainlens Explorer](chainlens.md)
For an overview of monitoring Besu, view [this recording](https://www.youtube.com/watch?v=7BuutRe0I28&feature=youtu.be).
---
## Use Grafana Loki
# Grafana Loki
[Grafana Loki] is an open-source log management platform that is available when using the [Developer Quickstart](../../tutorials/quickstart.md).
The generated quickstart network uses Grafana Alloy to collect Besu logs and send them to Loki.
## View quickstart logs in Loki
1. Generate a private network using the [Developer Quickstart](../../tutorials/quickstart.md).
2. Open the Grafana logs URL listed by `./list.sh`.
The URL uses Grafana Explore:
```text
http://localhost:3000/a/grafana-lokiexplore-app/explore
```
3. Select the Loki data source if Grafana doesn't select it automatically.
The logs display in Grafana.

[Grafana Loki]: https://grafana.com/oss/loki/
---
## Use OpenTelemetry
You can use the OpenTelemetry monitoring and tracing service to gather node metrics and traces. To enable OpenTelemetry to access Besu, use the [`--metrics-enabled`](../../../public-networks/reference/options.md#metrics-enabled) and [`--metrics-protocol=opentelemetry`](../../../public-networks/reference/options.md#metrics-protocol) options. Use [Splunk](https://splunk.com) to visualize the collected data.
:::tip
Use OpenTelemetry to monitor the sync time of your Besu node and show where time is spent internally and over the JSON-RPC interface.
[This office hours recording](https://lf-hyperledger.atlassian.net/wiki/spaces/BESU/pages/22154821/2021-01-19+Office+Hours+Notes) shows examples of monitoring Besu.
:::
## Install OpenTelemetry Collector
Download and install the [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector-contrib/releases).
:::tip
You can also install exporters that send system metrics to OpenTelemetry to monitor non-Besu-specific items such as disk and CPU usage. The OpenTelemetry Collector can connect to additional applications, and may be deployed in Kubernetes environments as a daemonset.
:::
## Setting up and running OpenTelemetry with Besu
1. Configure OpenTelemetry to accept data from Besu. For example, use the following configuration for your `otel-collector-config.yml` file, and send data to Splunk and Splunk APM:
```yml title="otel-collector-config.yml"
receivers:
otlp:
protocols:
grpc:
http:
exporters:
splunk_hec/traces:
# Splunk HTTP Event Collector token.
token: "11111111-1111-1111-1111-1111111111113"
# URL to a Splunk instance to send data to.
endpoint: "https://:8088/services/collector"
# Optional Splunk source: https://docs.splunk.com/Splexicon:Source
source: "besu:traces"
# Optional Splunk source type: https://docs.splunk.com/Splexicon:Sourcetype
sourcetype: "otlp"
# Splunk index, optional name of the Splunk index targeted.
index: "traces"
# Maximum HTTP connections to use simultaneously when sending data. Defaults to 100.
max_connections: 20
# Whether to disable gzip compression over HTTP. Defaults to false.
disable_compression: false
# HTTP timeout when sending data. Defaults to 10s.
timeout: 10s
# Whether to skip checking the certificate of the HEC endpoint when sending data over HTTPS. Defaults to false.
# For this demo, we use a self-signed certificate on the Splunk docker instance, so this flag is set to true.
insecure_skip_verify: true
splunk_hec/metrics:
# Splunk HTTP Event Collector token.
token: "11111111-1111-1111-1111-1111111111113"
# URL to a Splunk instance to send data to.
endpoint: "https://:8088/services/collector"
# Optional Splunk source: https://docs.splunk.com/Splexicon:Source
source: "besu:metrics"
# Optional Splunk source type: https://docs.splunk.com/Splexicon:Sourcetype
sourcetype: "prometheus"
# Splunk index, optional name of the Splunk index targeted.
index: "metrics"
# Maximum HTTP connections to use simultaneously when sending data. Defaults to 100.
max_connections: 20
# Whether to disable gzip compression over HTTP. Defaults to false.
disable_compression: false
# HTTP timeout when sending data. Defaults to 10s.
timeout: 10s
# Whether to skip checking the certificate of the HEC endpoint when sending data over HTTPS. Defaults to false.
# For this demo, we use a self-signed certificate on the Splunk docker instance, so this flag is set to true.
insecure_skip_verify: true
# Traces
sapm:
access_token: "${SPLUNK_ACCESS_TOKEN}"
endpoint: "https://ingest.${SPLUNK_REALM}.signalfx.com/v2/trace"
# Metrics + Events
signalfx:
access_token: "${SPLUNK_ACCESS_TOKEN}"
realm: "${SPLUNK_REALM}"
processors:
batch:
extensions:
health_check:
pprof:
zpages:
service:
extensions: [pprof, zpages, health_check]
pipelines:
traces:
receivers: [otlp]
exporters: [splunk_hec/traces, sapm]
processors: [batch]
metrics:
receivers: [otlp]
exporters: [splunk_hec/metrics, signalfx]
processors: [batch]
```
It is easiest to run the OpenTelemetry collector with Docker with the following command:
```bash
docker run -d \
-v ./otel-collector-config.yml:/etc/otel/config.yaml \
-e SPLUNK_ACCESS_TOKEN= \
-e SPLUNK_REALM= \
-p 4317:4317 \
otel/opentelemetry-collector-contrib:latest
```
```bash
docker run -d \
-v ./otel-collector-config.yml:/etc/otel/config.yaml \
-e SPLUNK_ACCESS_TOKEN=abcdefg654 \
-e SPLUNK_REALM=us1 \
-p 4317:4317 \
otel/opentelemetry-collector-contrib:latest
```
2. Start Besu with the [`--metrics-enabled`](../../../public-networks/reference/options.md#metrics-enabled) and [`--metrics-protocol=opentelemetry`](../../../public-networks/reference/options.md#metrics-protocol) options. For example, run the following command to start a single node:
```bash
OTEL_EXPORTER_OTLP_ENDPOINT=https://: besu --network=dev --rpc-http-cors-origins="all" --rpc-http-enabled --metrics-enabled --metrics-protocol=opentelemetry
```
```bash
OTEL_EXPORTER_OTLP_ENDPOINT=https://localhost:4317 besu --network=dev --rpc-http-cors-origins="all" --rpc-http-enabled --metrics-enabled --metrics-protocol=opentelemetry
```
The [OpenTelemetry SDK](https://github.com/open-telemetry/opentelemetry-specification/blob/8f7cdb73618a0b3afa9532b8f8103d719e352781/specification/sdk-environment-variables.md) mandates how to configure the OpenTelemetry gRPC client, so data flows to the collector from Besu.
You can use the following environment variables:
| Name | Description | Required |
|-------------------------------|-------------------------------------------------------------------------------------------------------------|----------|
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OpenTelemetry Collector endpoint, of the form `https://host:port`. The default is `https://localhost:4317`. | Yes |
| `OTEL_EXPORTER_OTLP_INSECURE` | Whether to allow insecure connections for OpenTelemetry data. The default is `false`. | No |
[Monitoring Besu synchronization to chain with Splunk]: https://github.com/splunk/splunk-connect-for-ethereum/tree/master/examples/besu-sync
---
## Use Splunk
[Splunk](https://splunkbase.splunk.com/app/4866/) is a third-party monitoring solution compatible with Besu. A Splunk server can receive Besu logs and enable complex search, visualization, and analysis.
Splunk can aggregate multiple logs in one place and run complex queries without being connected to the machine running Besu to read the standard output.
To use Splunk with Besu, run Splunk Enterprise [as a Docker container](#use-splunk-enterprise-as-a-docker-container)
or [as its own instance](#run-a-splunk-enterprise-instance).
## Use Splunk Enterprise as a Docker container
### Prerequisites
- [Docker](https://docs.docker.com/compose/install/)
- [Besu 1.4.4](https://github.com/besu-eth/besu/blob/750580dcca349d22d024cc14a8171b2fa74b505a/CHANGELOG.md#144) or later [installed](../../get-started/install/binary-distribution.md)
:::info
A Splunk license is not required to use the trial version of the Splunk Docker image. The image is not suitable for production use and has [restrictions on daily log volume](https://www.splunk.com/).
:::
:::note
If running [Besu as a Docker container](../../get-started/install/run-docker-image.md), consider using
[Kubernetes](../deploy/kubernetes.md) instead of the Splunk Enterprise trial container.
:::
### Steps
1. Start the Splunk Enterprise container:
```bash
docker run \
-e SPLUNK_START_ARGS=--accept-license \
-e SPLUNK_HEC_TOKEN=11111111-1111-1111-1111-1111111111113 \
-e SPLUNK_PASSWORD=changeme \
--rm \
-p8080:8000 -p8088:8088 \
-d \
--name splunk-demo \
splunk/splunk:latest
```
Once the service is started, connect on [`http://localhost:8080/`](http://localhost:8080/) and login as the `admin` user with a password of `changeme`.
:::tip
To follow the logs of the Splunk container:
```bash
docker logs -f splunk-demo
```
:::
2. Create the Besu index:
1. In the Splunk Web interface, navigate to the [index list in the settings](http://localhost:8080/en-US/manager/search/data/indexes).
2. [Create an event index] with an Index Name of `besu`.
3. Leave other fields with the default values.
4. Save the `besu` index.
3. Run Besu. To start a Besu node running in development mode, run the following command:
```bash
LOGGER=Splunk \
SPLUNK_URL=https://localhost:8088 \
SPLUNK_TOKEN=11111111-1111-1111-1111-1111111111113 \
SPLUNK_SKIPTLSVERIFY=true \
besu \
--network=dev \
--logging=trace
```
The environment variables specified send the Besu logs to Splunk. Only `LOGGER`, `SPLUNK_URL`, `SPLUNK_TOKEN` and `SPLUNK_SKIPTLSVERIFY` are required in this example. The complete list of options is in the [Splunk options reference table](#splunk-options-reference).
4. In the Splunk Web interface, navigate to the [search page](http://localhost:8080/en-US/app/search/search). Type `index="besu"` in the search field. Log events sent by Besu are displayed.
Congratulations! You can now play with the search and other Splunk features to explore your Besu logs.

5. Stop Besu with **ctrl+c**. Stop the Splunk container with `docker stop splunk-demo`.
## Run a Splunk Enterprise instance
### Prerequisites
- [Splunk Enterprise license](https://www.splunk.com/)
- [Besu 1.4.4](https://github.com/besu-eth/besu/blob/master/CHANGELOG.md#144) or later [installed](../../get-started/install/binary-distribution.md)
### Steps
1. Follow the steps in the [Splunk Enterprise documentation](https://docs.splunk.com/Documentation/Splunk/8.0.4/Installation) to download, install, and run Splunk Enterprise.
1. After logging into the Splunk Enterprise Web interface, navigate to the settings to:
1. [Create an HTTP Event Collector](https://docs.splunk.com/Documentation/Splunk/8.0.4/Data/UsetheHTTPEventCollector).
1. [Create an event index] named `besu`.
1. Run Besu as in step 3 in [using Splunk on Docker](#use-splunk-enterprise-as-a-docker-container). Set the `SPLUNK_URL` value to match the HTTP Event Collector address and port.
You can display logs and use the search engine as in step 4 in [using Splunk on Docker](#use-splunk-enterprise-as-a-docker-container).
## Splunk options reference
| Name | Description | Required |
| --- | --- | --- |
| `LOGGER` | Set to `Splunk` to activate sending logs to Splunk. | Yes |
| `HOST` | Current host. If in a Docker environment, the default value is the docker container ID. Otherwise, the default value is `localhost`. | No |
| `SPLUNK_URL` | URL of the Splunk HTTP Event Collector. For example, use `https://localhost:8088` | Yes |
| `SPLUNK_TOKEN` | Authentication token, usually of the form `11111111-1111-1111-1111-111111111111` | Yes |
| `SPLUNK_INDEX` | [Index](https://docs.splunk.com/Splexicon:Index) to store logs. Defaults to `besu` | No |
| `SPLUNK_SOURCE` | [Source of the logs](https://docs.splunk.com/Splexicon:Source). Defaults to `besu` | No |
| `SPLUNK_SOURCETYPE` | [Source type of the logs](https://docs.splunk.com/Splexicon:Sourcetype). Defaults to `besu` | No |
| `SPLUNK_BATCH_SIZE_BYTES` | Size of a log batch in bytes. Defaults to `65536` | No |
| `SPLUNK_BATCH_SIZE_COUNT` | Size of a log batch in number of events. Defaults to `1000` | No |
| `SPLUNK_BATCH_INTERVAL` | Interval at which to send log batches. Defaults to `500` | No |
| `SPLUNK_SKIPTLSVERIFY` | Whether to check the Splunk instance TLS certificate when sending data. Defaults to `false` | No |
[Create an event index]: https://docs.splunk.com/Documentation/Splunk/8.0.4/Indexer/Setupmultipleindexes#Create_events_indexes
---
## Create and send transactions(Send-transactions)
In private networks, you can create and [send regular transactions](../../../public-networks/how-to/send-transactions.md) as in public networks.
You can also:
- [Include revert reason in transactions](revert-reason.md).
- [Replace transactions in the transaction pool](../../../public-networks/concepts/transactions/pool.md#in-networks-with-zero-base-base-or-free-gas).
---
## Include revert reason
# Revert reason
In smart contracts, the [`revert`](https://docs.soliditylang.org/en/v0.8.12/control-structures.html#revert) operation triggers an exception to flag an error and revert the current call. The EVM passes back to the client an optional string message containing information about the error.
```sol
pragma solidity ^0.8.4;
contract VendingMachine {
address owner;
constructor() {
owner = msg.sender;
}
error Unauthorized();
function buy(uint amount) public payable {
if (amount > msg.value / 2 ether)
revert("Not enough Ether provided.");
// Alternative way to do it:
require(
amount <= msg.value / 2 ether,
"Not enough Ether provided."
);
// Perform the purchase.
}
function withdraw() public {
if (msg.sender != owner)
revert Unauthorized();
payable(msg.sender).transfer(address(this).balance);
}
}
```
## Enable revert reason
Use the [`--revert-reason-enabled`](../../../public-networks/reference/options.md#revert-reason-enabled) command line option to include the revert reason in the transaction receipt and the [`trace`](../../../public-networks/reference/api/trace.md#trace) response in Besu.
:::caution
Enabling revert reason may use a significant amount of memory. We do not recommend enabling revert reason when connected to public Ethereum networks.
:::
## Where the revert reason is included
With revert reason enabled, the transaction receipt returned by [`eth_getTransactionReceipt`](../../../public-networks/reference/api/eth/transaction.md#eth_gettransactionreceipt) includes the revert reason as an ABI-encoded string.
:::info
The revert reason is not included in the transaction receipt's root hash.
Not including the revert reason in the transaction receipt's root hash means the revert reason is only available to nodes that execute the transaction when importing the block.
Nodes that sync without executing historical blocks ([snap sync](../../../public-networks/concepts/node-sync.md#snap-synchronization)), won't have receipt revert reasons for those historical blocks.
:::
```json title="Example of transaction receipt"
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"blockHash": "0xe7212a92cfb9b06addc80dec2a0dfae9ea94fd344efeb157c41e12994fcad60a",
"blockNumber": "0x50",
"contractAddress": null,
"cumulativeGasUsed": "0x5208",
"from": "0x627306090abab3a6e1400e9345bc60c78a8bef57",
"gasUsed": "0x5208",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0xf17f52151ebef6c7334fad080c5704d77216b732",
"transactionHash": "0xc00e97af59c6f88de163306935f7682af1a34c67245e414537d02e422815efc3",
"transactionIndex": "0x0",
"revertReason": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4e6f7420656e6f7567682045746865722070726f76696465642e000000000000"
}
}
```
With revert reason enabled, the list items in the [`trace`](../../../public-networks/reference/api/trace.md#trace) response returned by [`trace_replayBlockTransactions`](../../../public-networks/reference/api/trace.md#trace_replayblocktransactions), [`trace_block`](../../../public-networks/reference/api/trace.md#trace_block), and [`trace_transaction`](../../../public-networks/reference/api/trace.md#trace_transaction) include the revert reason as an ABI-encoded string.
```json title="Example of trace response list item"
{
"jsonrpc": "2.0",
"id": 415,
"result": [
{
"action": {
"callType": "call",
"from": "0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"gas": "0xffadea",
"input": "0x",
"to": "0x0110000000000000000000000000000000000000",
"value": "0x0"
},
"blockHash": "0x220bc13dc4f1ed38dcca927a5be15eca16497d279f4c40d7b8fe9704eadf1464",
"blockNumber": 18,
"error": "Reverted",
"revertReason": "0x7d88c1856cc95352",
"subtraces": 0,
"traceAddress": [],
"transactionHash": "0xc388baa0e55e6b73e850b22dc7e9853700f6b995fd55d95dd6ccd5a13d63c566",
"transactionPosition": 1,
"type": "call"
}
]
}
```
By default, the error returned by [`eth_estimateGas`](../../../public-networks/reference/api/eth/execute.md#eth_estimategas) and [`eth_call`](../../../public-networks/reference/api/eth/execute.md#eth_call) includes the revert reason as an ABI-encoded string in the `data` field.
```json title="Example of eth_estimateGas and eth_call error"
{
"jsonrpc": "2.0",
"id": 3,
"error": {
"code": -32000,
"message": "Execution reverted: ERC20: transfer amount exceeds balance",
"data": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4e6f7420656e6f7567682045746865722070726f76696465642e000000000000"
}
}
```
## Revert reason format
As described in the [Solidity documentation], the revert reason is an ABI-encoded string consisting of:
```bash
0x08c379a0 // Function selector for Error(string)
0x0000000000000000000000000000000000000000000000000000000000000020 // Data offset
0x000000000000000000000000000000000000000000000000000000000000001a // String length
0x4e6f7420656e6f7567682045746865722070726f76696465642e000000000000 // String data
```
```bash title="Example of revert reason string for 'Not enough Ether provided' "
"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001a4e6f7420656e6f7567682045746865722070726f76696465642e000000000000"
```
## Dapp support
Client libraries, such as web3j, do not support extracting the revert reason from the transaction receipt. To extract the revert reason your dapp must interact directly with Besu using a custom JSON -> Object converter.
[Solidity documentation]: https://docs.soliditylang.org/en/v0.8.12/control-structures.html#revert
---
## Upgrade
# Network and protocol upgrades
:::info
Node upgrades upgrade your Besu client to a later version. In private networks, you can [upgrade your node](../../public-networks/how-to/upgrade-node.md) as in public networks.
:::
Network upgrades are the mechanism for upgrading the Ethereum protocol. Protocol upgrades occur during the network upgrades.
For Ethereum Mainnet and public testnets, the milestone block definitions are included in Besu. Upgrading your Besu client applies the network upgrade.
For private networks, all network participants must agree on the protocol upgrades and coordinate the network upgrades. The genesis file specifies the milestone block at which to apply the protocol upgrade.
## Upgrade the protocol
To upgrade the protocol in a private network:
1. Review included EIPs for breaking changes. A [meta EIP](https://eips.ethereum.org/meta) for each protocol upgrade lists included EIPs. For example, [Istanbul](https://eips.ethereum.org/EIPS/eip-1679).
1. Network participants agree on the block number at which to upgrade.
1. For each node in the network:
1. Add the [milestone block number](../../public-networks/reference/genesis-items.md#milestone-blocks) to the genesis file.
1. Restart the node before reaching milestone block.
:::caution
To avoid a forked network, all network participants must update their genesis file to include the agreed on milestone block and restart their node before reaching the milestone block.
:::
:::tip
- For compatibility with future protocol upgrades, don't hardcode any gas price assumptions.
- Implementing upgradeable contracts enables contracts to be upgraded if a protocol upgrade does include breaking changes.
:::
---
## Use local permissioning
[Local permissioning](../concepts/permissioning.md#specify-local-permissioning) supports node and account allowlisting.
## Node allowlisting
You can allow access to specified nodes in the [permissions configuration file](#permissions-configuration-file). With node allowlisting enabled, communication is only between nodes in the allowlist.
:::info
Node allowlists [support domain names] in enode URLs as an early access feature. Use the `--Xdns-enabled` option to enable domain name support.
If using Kubernetes, enable domain name support and use the `--Xdns-update-enabled` option to ensure that Besu can connect to a container after being restarted, even if the IP address of the container changes.
:::
```toml title="Nodes allowlist in the permissions configuration file"
nodes-allowlist=["enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.9:4567","enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.169.0.9:4568"]
```
Node allowlisting is at the node level. That is, each node in the network has a [permissions configuration file](#permissions-configuration-file) file in the [data directory](../../public-networks/reference/options.md#data-path) for the node.
Local permissioning doesn't check that the node using the permissions configuration file is listed in the allowlist, it only checks that the remote end of the connection is in the allowlist.
### Specify bootnodes in the allowlist
The nodes permissions list must include the [bootnodes](configure/bootnodes.md) or Besu doesn't start with node permissions enabled.
If you start Besu with specified bootnodes and have node permissioning enabled:
```bash
--bootnodes="enode://7e4ef30e9ec683f26ad76ffca5b5148fa7a6575f4cfad4eb0f52f9c3d8335f4a9b6f9e66fcc73ef95ed7a2a52784d4f372e7750ac8ae0b544309a5b391a23dd7@127.0.0.1:30303","enode://2feb33b3c6c4a8f77d84a5ce44954e83e5f163e7a65f7f7a7fec499ceb0ddd76a46ef635408c513d64c076470eac86b7f2c8ae4fcd112cb28ce82c0d64ec2c94@127.0.0.1:30304","enode://7b61d5ee4b44335873e6912cb5dd3e3877c860ba21417c9b9ef1f7e500a82213737d4b269046d0669fb2299a234ca03443f25fe5f706b693b3669e5c92478ade@127.0.0.1:30305"
```
The `nodes-allowlist` in the [permissions configuration file](#permissions-configuration-file) must contain the specified bootnodes.
:::tip
If your node has two different IP addresses for ingress and egress (for example, if you use Kubernetes implementing a load balancer for ingress and a NAT gateway IP address for egress), add both addresses to the allowlist, using the same public key for each IP address. This will allow the node to connect.
:::
### Enable node allowlisting
To enable node allowlisting, specify the [`--permissions-nodes-config-file-enabled`](../reference/options.md#permissions-nodes-config-file-enabled) option when starting Besu.
The `PERM` API methods are not enabled by default. To enable the `PERM` API methods, use the [`--rpc-http-api`](../../public-networks/reference/options.md#rpc-http-api) or [`--rpc-ws-api`](../../public-networks/reference/options.md#rpc-ws-api) options.
### Update the node allowlist
To update the nodes allowlist while the node is running, use the following JSON-RPC API methods:
- [`perm_addNodesToAllowlist`](../reference/api/perm.md#perm_addnodestoallowlist)
- [`perm_removeNodesFromAllowlist`](../reference/api/perm.md#perm_removenodesfromallowlist)
You can also update the [`permissions_config.toml`](#permissions-configuration-file) file directly and then update the allowlist using the [`perm_reloadPermissionsFromFile`](../reference/api/perm.md#perm_reloadpermissionsfromfile) method.
Updates to the permissions configuration file persist across node restarts.
### View the node allowlist
To view the nodes allowlist, use the [`perm_getNodesAllowlist`](../reference/api/perm.md#perm_getnodesallowlist) method.
:::note
Each node has a [permissions configuration file](#permissions-configuration-file), which means nodes can have different nodes allowlists. This means nodes might be participating in the network that are not on the allowlist of other nodes in the network. We recommend each node in the network has the same nodes allowlist.
:::
```text title="Example of different node allowlists"
Node 1 Allowlist = [Node 2, Node 3]
Node 2 Allowlist = [Node 3, Node 5]
Node 5 is participating in the same network as Node 1 even though Node 1 does not have Node 5
on their allowlist.
```
## Account allowlisting
You can specify accounts in the accounts allowlist in the [permissions configuration file](#permissions-configuration-file). A node with account permissioning accepts transactions only from accounts in the accounts allowlist.
:::info Accounts allowlist in the permissions configuration file
`accounts-allowlist=["0x0000000000000000000000000000000000000009"]`
:::
Account allowlisting is at the node level. That is, each node in the network has a [permissions configuration file](#permissions-configuration-file) in the [data directory](../../public-networks/reference/options.md#data-path) for the node.
Transaction validation against the accounts allowlist occurs at the following points:
- Submitted by JSON-RPC API method [`eth_sendRawTransaction`](../../public-networks/reference/api/eth/submit.md#eth_sendrawtransaction)
- Received via propagation from another node
- Added to a block by a mining node
After adding transactions to a block, the transactions are not validated against the allowlist when received by another node. That is, a node can synchronize and add blocks containing transactions from accounts that are not on the accounts allowlist of that node.
The following diagram illustrates where local permissioning rules are checked.

```text title="Example of different account allowlists"
Node 1 Allowlist = [Account A, Account B]
Node 2 Allowlist = [Account B, Account C]
Mining Node Allowlist = [Account A, Account B]
Account A submits a transaction on Node 1. Node 1 validates and propagates the transaction. The
Mining Node receives the transaction, validates it is from an account in the Mining Node
accounts allowlist, and includes the transaction in the block. Node 2 receives and adds
the block created by the Mining Node.
Node 2 now has a transaction in the blockchain from Account A, which is not on the accounts
allowlist for Node 2.
```
:::note
Each node has a [permissions configuration file](#permissions-configuration-file) which means nodes in the network can have different accounts allowlists. This means a transaction can be successfully submitted by Node A from an account in the Node A allowlist but rejected by Node B to which it's propagated if the account is not in the Node B allowlist. We recommend each node in the network has the same accounts allowlist.
:::
### Enable account allowlisting
To enable account allowlisting, specify the [`--permissions-accounts-config-file-enabled`](../reference/options.md#permissions-accounts-config-file-enabled) option when starting Besu.
The `PERM` API methods are not enabled by default. To enable the `PERM` API methods, use the [`--rpc-http-api`](../../public-networks/reference/options.md#rpc-http-api) or [`--rpc-ws-api`](../../public-networks/reference/options.md#rpc-ws-api) options.
### Update the account allowlist
To update the accounts allowlist when the node is running, use the JSON-RPC API methods:
- [`perm_addAccountsToAllowlist`](../reference/api/perm.md#perm_addaccountstoallowlist)
- [`perm_removeAccountsFromAllowlist`](../reference/api/perm.md#perm_removeaccountsfromallowlist).
You can also update the [`permissions_config.toml`](#permissions-configuration-file) file directly and use the [`perm_reloadPermissionsFromFile`](../reference/api/perm.md#perm_reloadpermissionsfromfile) method to update the allowlists.
Updates to the permissions configuration file persist across node restarts.
### View the account allowlist
To view the accounts allowlist, use the [`perm_getAccountsAllowlist`](../reference/api/perm.md#perm_getaccountsallowlist) method.
## Permissions configuration file
The permissions configuration file contains the nodes and accounts allowlists. If the [`--permissions-accounts-config-file`](../reference/options.md#permissions-accounts-config-file) and [`--permissions-nodes-config-file`](../reference/options.md#permissions-nodes-config-file) options are not specified, the name of the permissions configuration file must be [`permissions_config.toml`](#permissions-configuration-file) and must be in the [data directory](../../public-networks/reference/options.md#data-path) for the node.
You can specify the accounts and nodes allowlists in the same file or in separate files for accounts and nodes.
To specify a permissions configuration file (or separate files for accounts and nodes) in any location, use the [`--permissions-accounts-config-file`](../reference/options.md#permissions-accounts-config-file) and [`--permissions-nodes-config-file`](../reference/options.md#permissions-nodes-config-file) options.
:::note
The [`--permissions-accounts-config-file`](../reference/options.md#permissions-accounts-config-file) and [`permissions-nodes-config-file`](../reference/options.md#permissions-nodes-config-file) options are not used when running Besu from the [Docker image](../get-started/install/run-docker-image.md). Use a bind mount to [specify a permissions configuration file with Docker].
:::
```toml title="Sample permissions configuration file"
accounts-allowlist=["0xb9b81ee349c3807e46bc71aa2632203c5b462032", "0xb9b81ee349c3807e46bc71aa2632203c5b462034"]
nodes-allowlist=["enode://7e4ef30e9ec683f26ad76ffca5b5148fa7a6575f4cfad4eb0f52f9c3d8335f4a9b6f9e66fcc73ef95ed7a2a52784d4f372e7750ac8ae0b544309a5b391a23dd7@127.0.0.1:30303","enode://2feb33b3c6c4a8f77d84a5ce44954e83e5f163e7a65f7f7a7fec499ceb0ddd76a46ef635408c513d64c076470eac86b7f2c8ae4fcd112cb28ce82c0d64ec2c94@127.0.0.1:30304","enode://7b61d5ee4b44335873e6912cb5dd3e3877c860ba21417c9b9ef1f7e500a82213737d4b269046d0669fb2299a234ca03443f25fe5f706b693b3669e5c92478ade@127.0.0.1:30305"]
```
[specify a permissions configuration file with Docker]: ../get-started/install/run-docker-image.md
[support domain names]: ../../public-networks/concepts/node-keys.md#domain-name-support
---
## Private networks
# Besu for private (permissioned) networks
You can use Besu to develop enterprise applications requiring secure, high-performance transaction processing in a private network.
A private (also known as permissioned) network is a network not connected to Ethereum Mainnet or an Ethereum testnet. Private networks typically use a different [chain ID](../public-networks/concepts/network-and-chain-id.md) and proof of authority (PoA) consensus ([QBFT](how-to/configure/consensus/qbft.md) or [IBFT 2.0](how-to/configure/consensus/ibft.md)).
Besu supports [permissioning](concepts/permissioning.md), and has a modular [plugin](../plugins/index.md) framework.
Get started with the [Developer Quickstart](tutorials/quickstart.md) to rapidly generate local blockchain networks.
If you have any questions about Besu for private (permissioned) networks, ask on the **besu-enterprise** channel on
[Discord](https://discord.com/channels/905194001349627914/1172617318845657199).
## Architecture
The following diagram outlines the high-level architecture of Besu for private networks.

---
## Accounts for testing
You can use existing accounts for testing by including them in the genesis file for a private network. Besu also provides predefined accounts for use in development mode.
## Development mode
When you start Besu with the [`--network=dev`](../../public-networks/reference/options.md#network) command line option, Besu uses the `dev.json` genesis file by default.
The `dev.json` genesis file defines the following accounts used for testing.
:::danger **Do not use the test accounts on Ethereum Mainnet or any production network.**
The following accounts are test accounts and their private keys are publicly visible in this documentation and in publicly available source code.
They are not secure and everyone can use them.
**Using test accounts on Ethereum Mainnet and production networks can lead to loss of funds and identity fraud.**
In this documentation, we only provide test accounts for ease of testing and learning purposes; never use them for other purposes.
**Always secure your Ethereum Mainnet and any production account properly.**
See for instance [MyCrypto "Protecting Yourself and Your Funds" guide](https://support.mycrypto.com/staying-safe/protecting-yourself-and-your-funds).
:::
:::info "Test Account 1 (address `0xfe3b557e8fb62b89f4916b721be55ceb828dbd73`)"
Private key to copy :
```text
0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63
```
Initial balance : 200 Eth _(200000000000000000000 Wei)_
:::
:::info "Test Account 2 (address `0x627306090abaB3A6e1400e9345bC60c78a8BEf57`)"
Private key to copy :
```text
0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3
```
Initial balance : 90000 Eth _(90000000000000000000000 Wei)_
:::
:::info "Test Account 3 (address `0xf17f52151EbEF6C7334FAD080c5704D77216b732`)"
Private key to copy :
```text
0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f
```
Initial balance : 90000 Eth _(90000000000000000000000 Wei)_
:::
## Genesis file
To use existing test accounts, specify the accounts and balances in a genesis file for your test network. For an example of how to define accounts in the genesis file, see [`dev.json`](https://github.com/besu-eth/besu/blob/750580dcca349d22d024cc14a8171b2fa74b505a/config/src/main/resources/dev.json).
To start Besu with the genesis file defining the existing accounts, use the [`--genesis-file`](../../public-networks/reference/options.md#genesis-file) command line option .
---
## IBFT methods
# `IBFT` methods
The `IBFT` API methods provide access to the [IBFT 2.0](../../how-to/configure/consensus/ibft.md) consensus engine.
:::note
The `IBFT` API is not enabled by default for JSON-RPC.
Enable it using the [`--rpc-http-api`](../../../public-networks/reference/options.md#rpc-http-api) or
[`--rpc-ws-api`](../../../public-networks/reference/options.md#rpc-ws-api) option.
:::
## `ibft_discardValidatorVote`
Discards a proposal to [add or remove a validator](../../how-to/configure/consensus/ibft.md#add-and-remove-validators) with the specified address.
### Parameters
- `address`: _string_ - 20-byte address of the proposed validator.
### Returns
- Indicates if the proposal is discarded.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "ibft_discardValidatorVote",
"params": [
"0xef1bfb6a12794615c9b0b5a21e6741f01e570185"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "ibft_discardValidatorVote",
"params": [
"0xef1bfb6a12794615c9b0b5a21e6741f01e570185"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
---
## `ibft_getPendingVotes`
Returns [votes](../../how-to/configure/consensus/ibft.md#add-and-remove-validators) cast in the current [epoch](../../how-to/configure/consensus/ibft.md#genesis-file).
### Parameters
- None
### Returns
- Account addresses mapped to boolean values indicating the vote for each account.
`true` is a vote to add a validator; `false` is a vote to remove a validator.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "ibft_getPendingVotes",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "ibft_getPendingVotes",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"0xef1bfb6a12794615c9b0b5a21e6741f01e570185": true,
"0x42d4287eac8078828cf5f3486cfe601a275a49a5": true
}
}
```
---
## `ibft_getSignerMetrics`
Provides the following validator metrics for the specified range:
- Number of blocks from each validator.
- Block number of the last block proposed by each validator (if any proposed in the specified range).
- All validators present in the last block of the range.
### Parameters
- `fromBlockNumber`: _string_ - (Optional) Hexadecimal integer representing a block number, or one
of the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../public-networks/how-to/use-besu-api/json-rpc.md#block-parameter).
- `toBlockNumber`: _string_ - (Optional) Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../public-networks/how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
If you specify:
- No parameters, the call provides metrics for the last 100 blocks, or all blocks if there are fewer than 100 blocks.
- Only the first parameter, the call provides metrics for all blocks from the specified block to the latest block.
### Returns
- List of validator objects.
- `address`: _string_ - Address of the validator.
:::note
The proposer of the genesis block has address `0x0000000000000000000000000000000000000000`.
:::
- `proposedBlockCount`: _string_ - Hexadecimal integer representing the number of blocks proposed by the validator in the specified range.
- `lastProposedBlockNumber`: _string_ - Hexadecimal integer representing the block number of the last block proposed by the validator in the specified range.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "ibft_getSignerMetrics",
"params": [
"0x1",
"0x64"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "ibft_getSignerMetrics",
"params": [
"0x1",
"0x64"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"address": "0x7ffc57839b00206d1ad20c69a1981b489f772031",
"proposedBlockCount": "0x21",
"lastProposedBlockNumber": "0x61"
},
{
"address": "0x42eb768f2244c8811c63729a21a3569731535f06",
"proposedBlockCount": "0x21",
"lastProposedBlockNumber": "0x63"
},
{
"address": "0xb279182d99e65703f0076e4812653aab85fca0f0",
"proposedBlockCount": "0x21",
"lastProposedBlockNumber": "0x62"
}
]
}
```
---
## `ibft_getValidatorsByBlockHash`
Lists the validators defined in the specified block.
### Parameters
- `block`: _string_ - 32-byte block hash.
### Returns
- List of validator addresses.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "ibft_getValidatorsByBlockHash",
"params": [
"0xbae7d3feafd743343b9a4c578cab5e5d65eb735f6855fb845c00cab356331256"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "ibft_getValidatorsByBlockHash",
"params": [
"0xbae7d3feafd743343b9a4c578cab5e5d65eb735f6855fb845c00cab356331256"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0x42d4287eac8078828cf5f3486cfe601a275a49a5",
"0xb1b2bc9582d2901afdc579f528a35ca41403fa85",
"0xef1bfb6a12794615c9b0b5a21e6741f01e570185"
]
}
```
---
## `ibft_getValidatorsByBlockNumber`
Lists the validators defined in the specified block.
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of the
string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../public-networks/how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
### Returns
- List of validator addresses.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "ibft_getValidatorsByBlockNumber",
"params": [
"latest"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "ibft_getValidatorsByBlockNumber",
"params": [
"latest"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0x42d4287eac8078828cf5f3486cfe601a275a49a5",
"0xb1b2bc9582d2901afdc579f528a35ca41403fa85",
"0xef1bfb6a12794615c9b0b5a21e6741f01e570185"
]
}
```
---
## `ibft_proposeValidatorVote`
Proposes to [add or remove a validator](../../how-to/configure/consensus/ibft.md#add-and-remove-validators) with the specified address.
### Parameters
- `address`: _string_ - Account address.
- `proposal`: _boolean_ - `true` to propose adding a validator, or `false` to propose removing a validator.
### Returns
- `true`
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "ibft_proposeValidatorVote",
"params": [
"0x42d4287eac8078828cf5f3486cfe601a275a49a5",
true
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "ibft_proposeValidatorVote",
"params": [
"0x42d4287eac8078828cf5f3486cfe601a275a49a5",
true
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
---
## Private network JSON-RPC API methods
The Besu private network JSON-RPC API methods are grouped by namespace:
| Namespace | Description |
| --- | --- |
| [`IBFT`](ibft.md) | Access the [IBFT 2.0](../../how-to/configure/consensus/ibft.md) consensus engine. |
| [`PERM`](perm.md) | [Local permissioning](../../how-to/use-local-permissioning.md) functionality. |
| [`QBFT`](qbft.md) | Access the [QBFT](../../how-to/configure/consensus/qbft.md) consensus engine. |
:::caution Important
- This reference contains API methods that apply to only private networks. For API methods that apply to both private and public networks, see the [public network API reference](../../../public-networks/reference/api/index.md).
- All JSON-RPC HTTP examples use the default host and port endpoint `http://127.0.0.1:8545`. If using the [`--rpc-http-host`](../../../public-networks/reference/options.md#rpc-http-host) or [`--rpc-http-port`](../../../public-networks/reference/options.md#rpc-http-port) options, update the endpoint.
:::
---
## PERM methods
# `PERM` methods
The `PERM` API methods provide permissioning functionality.
Use these methods for [local permissioning](../../how-to/use-local-permissioning.md) only.
:::note
The `PERM` API is not enabled by default for JSON-RPC.
Enable it using the [`--rpc-http-api`](../../../public-networks/reference/options.md#rpc-http-api) or
[`--rpc-ws-api`](../../../public-networks/reference/options.md#rpc-ws-api) option.
:::
## `perm_addAccountsToAllowlist`
Adds accounts (participants) to the [accounts permission list](../../how-to/use-local-permissioning.md#account-allowlisting).
### Parameters
- `addresses`: _array_ of _strings_ - List of account addresses.
:::note
The parameters list contains a list, which is why the account addresses are enclosed by double square brackets.
:::
### Returns
- `Success`, or `error` if the request fails (for example, if you attempt to add accounts already on the allowlist, or include invalid account addresses).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "perm_addAccountsToAllowlist",
"params": [
[
"0xb9b81ee349c3807e46bc71aa2632203c5b462032",
"0xb9b81ee349c3807e46bc71aa2632203c5b462034"
]
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "perm_addAccountsToAllowlist",
"params": [
[
"0xb9b81ee349c3807e46bc71aa2632203c5b462032",
"0xb9b81ee349c3807e46bc71aa2632203c5b462034"
]
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## `perm_addNodesToAllowlist`
Adds nodes to the [nodes allowlist](../../how-to/use-local-permissioning.md#node-allowlisting).
To use domain names in enode URLs, [enable DNS support](../../../public-networks/concepts/node-keys.md#domain-name-support) to avoid receiving a `request contains an invalid node` error.
:::warning
Enode URL domain name support is an early access feature.
:::
### Parameters
- `enodes`: _array_ of _strings_ - List of [enode URLs](../../../public-networks/concepts/node-keys.md#enode-url).
:::note
The parameters list contains a list, which is why the enode URLs are enclosed by double square brackets.
:::
### Returns
- `Success`, or `error` if the request fails (for example, if you attempt to add nodes already on the allowlist, or include invalid enode URLs).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "perm_addNodesToAllowlist",
"params": [
[
"enode://7e4ef30e9ec683f26ad76ffca5b5148fa7a6575f4cfad4eb0f52f9c3d8335f4a9b6f9e66fcc73ef95ed7a2a52784d4f372e7750ac8ae0b544309a5b391a23dd7@127.0.0.1:30303",
"enode://2feb33b3c6c4a8f77d84a5ce44954e83e5f163e7a65f7f7a7fec499ceb0ddd76a46ef635408c513d64c076470eac86b7f2c8ae4fcd112cb28ce82c0d64ec2c94@127.0.0.1:30304"
]
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "perm_addNodesToAllowlist",
"params": [
[
"enode://7e4ef30e9ec683f26ad76ffca5b5148fa7a6575f4cfad4eb0f52f9c3d8335f4a9b6f9e66fcc73ef95ed7a2a52784d4f372e7750ac8ae0b544309a5b391a23dd7@127.0.0.1:30303",
"enode://2feb33b3c6c4a8f77d84a5ce44954e83e5f163e7a65f7f7a7fec499ceb0ddd76a46ef635408c513d64c076470eac86b7f2c8ae4fcd112cb28ce82c0d64ec2c94@127.0.0.1:30304"
]
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## `perm_getAccountsAllowlist`
Lists accounts (participants) in the [accounts permissions list](../../how-to/use-local-permissioning.md#account-allowlisting).
### Parameters
- None
### Returns
- List of accounts (participants) in the accounts allowlist.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "perm_getAccountsAllowlist",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "perm_getAccountsAllowlist",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0x0000000000000000000000000000000000000009",
"0xb9b81ee349c3807e46bc71aa2632203c5b462033"
]
}
```
---
## `perm_getNodesAllowlist`
Lists nodes in the [nodes allowlist](../../how-to/use-local-permissioning.md#node-allowlisting).
### Parameters
- None
### Returns
- [Enode URLs](../../../public-networks/concepts/node-keys.md#enode-url) of nodes in the nodes allowlist.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "perm_getNodesAllowlist",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "perm_getNodesAllowlist",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"enode://7b61d5ee4b44335873e6912cb5dd3e3877c860ba21417c9b9ef1f7e500a82213737d4b269046d0669fb2299a234ca03443f25fe5f706b693b3669e5c92478ade@127.0.0.1:30305",
"enode://2feb33b3c6c4a8f77d84a5ce44954e83e5f163e7a65f7f7a7fec499ceb0ddd76a46ef635408c513d64c076470eac86b7f2c8ae4fcd112cb28ce82c0d64ec2c94@127.0.0.1:30304"
]
}
```
---
## `perm_reloadPermissionsFromFile`
Reloads the accounts and nodes allowlists from the [permissions configuration file](../../how-to/use-local-permissioning.md#permissions-configuration-file).
### Parameters
- None
### Returns
- `Success`, or `error` if the permissions configuration file is not valid.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "perm_reloadPermissionsFromFile",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "perm_reloadPermissionsFromFile",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## `perm_removeAccountsFromAllowlist`
Removes accounts (participants) from the [accounts permissions list](../../how-to/use-local-permissioning.md#account-allowlisting).
### Parameters
- `addresses`: _array_ of _strings_ - List of account addresses.
:::note
The parameters list contains a list, which is why the account addresses are enclosed by double square brackets.
:::
### Returns
- `Success`, or `error` if the request fails (for example, if you attempt to remove accounts not on the allowlist, or include invalid account addresses).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "perm_removeAccountsFromAllowlist",
"params": [
[
"0xb9b81ee349c3807e46bc71aa2632203c5b462032",
"0xb9b81ee349c3807e46bc71aa2632203c5b462034"
]
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "perm_removeAccountsFromAllowlist",
"params": [
[
"0xb9b81ee349c3807e46bc71aa2632203c5b462032",
"0xb9b81ee349c3807e46bc71aa2632203c5b462034"
]
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## `perm_removeNodesFromAllowlist`
Removes nodes from the [nodes allowlist](../../how-to/use-local-permissioning.md#node-allowlisting).
### Parameters
- `enodes`: _array_ of _strings_ - List of [enode URLs](../../../public-networks/concepts/node-keys.md#enode-url).
:::note
The parameters list contains a list, which is why the enode URLs are enclosed by double square brackets.
:::
### Returns
- `Success`, or `error` if the request fails (for example, if you attempt to remove nodes not on the allowlist, or include invalid enode URLs).
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "perm_removeNodesFromAllowlist",
"params": [
[
"enode://7e4ef30e9ec683f26ad76ffca5b5148fa7a6575f4cfad4eb0f52f9c3d8335f4a9b6f9e66fcc73ef95ed7a2a52784d4f372e7750ac8ae0b544309a5b391a23dd7@127.0.0.1:30303",
"enode://2feb33b3c6c4a8f77d84a5ce44954e83e5f163e7a65f7f7a7fec499ceb0ddd76a46ef635408c513d64c076470eac86b7f2c8ae4fcd112cb28ce82c0d64ec2c94@127.0.0.1:30304"
]
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "perm_removeNodesFromAllowlist",
"params": [
[
"enode://7e4ef30e9ec683f26ad76ffca5b5148fa7a6575f4cfad4eb0f52f9c3d8335f4a9b6f9e66fcc73ef95ed7a2a52784d4f372e7750ac8ae0b544309a5b391a23dd7@127.0.0.1:30303",
"enode://2feb33b3c6c4a8f77d84a5ce44954e83e5f163e7a65f7f7a7fec499ceb0ddd76a46ef635408c513d64c076470eac86b7f2c8ae4fcd112cb28ce82c0d64ec2c94@127.0.0.1:30304"
]
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "Success"
}
```
---
## QBFT methods
# `QBFT` methods
The `QBFT` API methods provide access to the [QBFT](../../how-to/configure/consensus/qbft.md) consensus engine.
:::note
The `QBFT` API is not enabled by default for JSON-RPC.
Enable it using the [`--rpc-http-api`](../../../public-networks/reference/options.md#rpc-http-api) or
[`--rpc-ws-api`](../../../public-networks/reference/options.md#rpc-ws-api) option.
:::
## `qbft_discardValidatorVote`
Discards a proposal to [add or remove a validator](../../how-to/configure/consensus/qbft.md#add-and-remove-validators) with the specified address.
### Parameters
- `address`: _string_ - 20-byte address of the proposed validator.
### Returns
- Indicates if the proposal is discarded.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "qbft_discardValidatorVote",
"params": [
"0xef1bfb6a12794615c9b0b5a21e6741f01e570185"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "qbft_discardValidatorVote",
"params": [
"0xef1bfb6a12794615c9b0b5a21e6741f01e570185"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
---
## `qbft_getPendingVotes`
Returns [votes](../../how-to/configure/consensus/qbft.md#add-and-remove-validators) cast in the current [epoch](../../how-to/configure/consensus/qbft.md#genesis-file).
### Parameters
- None
### Returns
- Account addresses mapped to boolean values indicating the vote for each account.
`true` is a vote to add a validator; `false` is a vote to remove a validator.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "qbft_getPendingVotes",
"params": [],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "qbft_getPendingVotes",
"params": [],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"0xef1bfb6a12794615c9b0b5a21e6741f01e570185": true,
"0x42d4287eac8078828cf5f3486cfe601a275a49a5": true
}
}
```
---
## `qbft_getSignerMetrics`
Provides the following validator metrics for the specified range:
- Number of blocks from each validator.
- Block number of the last block proposed by each validator (if any proposed in the specified range).
- All validators present in the last block of the range.
### Parameters
- `fromBlockNumber`: _string_ - (Optional) Hexadecimal integer representing a block number, or one
of the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../public-networks/how-to/use-besu-api/json-rpc.md#block-parameter).
- `toBlockNumber`: _string_ - (Optional) Hexadecimal integer representing a block number, or one of
the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in
[block parameter](../../../public-networks/how-to/use-besu-api/json-rpc.md#block-parameter).
:::note
`pending` returns the same value as `latest`.
:::
If you specify:
- No parameters, the call provides metrics for the last 100 blocks, or all blocks if there are fewer than 100 blocks.
- Only the first parameter, the call provides metrics for all blocks from the specified block to the latest block.
### Returns
- List of validator objects.
- `address`: _string_ - Address of the validator.
:::note
The proposer of the genesis block has address `0x0000000000000000000000000000000000000000`.
:::
- `proposedBlockCount`: _string_ - Hexadecimal integer representing the number of blocks proposed by the validator in the specified range.
- `lastProposedBlockNumber`: _string_ - Hexadecimal integer representing the block number of the last block proposed by the validator in the specified range.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "qbft_getSignerMetrics",
"params": [
"0x1",
"0x64"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "qbft_getSignerMetrics",
"params": [
"0x1",
"0x64"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"address": "0x7ffc57839b00206d1ad20c69a1981b489f772031",
"proposedBlockCount": "0x21",
"lastProposedBlockNumber": "0x61"
},
{
"address": "0x42eb768f2244c8811c63729a21a3569731535f06",
"proposedBlockCount": "0x21",
"lastProposedBlockNumber": "0x63"
},
{
"address": "0xb279182d99e65703f0076e4812653aab85fca0f0",
"proposedBlockCount": "0x21",
"lastProposedBlockNumber": "0x62"
}
]
}
```
---
## `qbft_getValidatorsByBlockHash`
Lists the validators defined in the specified block.
### Parameters
- `block`: _string_ - 32-byte block hash.
### Returns
- List of validator addresses.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "qbft_getValidatorsByBlockHash",
"params": [
"0xbae7d3feafd743343b9a4c578cab5e5d65eb735f6855fb845c00cab356331256"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "qbft_getValidatorsByBlockHash",
"params": [
"0xbae7d3feafd743343b9a4c578cab5e5d65eb735f6855fb845c00cab356331256"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0x42d4287eac8078828cf5f3486cfe601a275a49a5",
"0xb1b2bc9582d2901afdc579f528a35ca41403fa85",
"0xef1bfb6a12794615c9b0b5a21e6741f01e570185"
]
}
```
---
## `qbft_getValidatorsByBlockNumber`
Lists the validators for the specified block.
For all blocks up to the chain head block, this method returns the validators that were used at the time the block was produced.
Use `blockNumber` to get the list of validators for that block.
For the chain head block, there are two validator lists associated with it:
1. The validators that were used at the time the block was produced. Passing `latest` as the input parameter returns this list.
2. The validators that will be used to produce the next block. Passing `pending` as the input parameter returns this list.
In most instances, the two lists for the chain head block are the same. However, when voting has completed to add or remove a validator, the validators that will be used to produce the next block are different. Comparing the two lists can help when diagnosing a stalled chain.
:::note
When the validator list changes, an `INFO` log message displays, showing the previous list of validators and the new list of validators.
:::
### Parameters
- `blockNumber`: _string_ - Hexadecimal integer representing a block number, or one of the string tags `latest`, `earliest`, `pending`, `finalized`, or `safe`, as described in [block parameter](../../../public-networks/how-to/use-besu-api/json-rpc.md#block-parameter).
### Returns
- List of validator addresses.
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "qbft_getValidatorsByBlockNumber",
"params": [
"latest"
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "qbft_getValidatorsByBlockNumber",
"params": [
"latest"
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0x42d4287eac8078828cf5f3486cfe601a275a49a5",
"0xb1b2bc9582d2901afdc579f528a35ca41403fa85",
"0xef1bfb6a12794615c9b0b5a21e6741f01e570185"
]
}
```
---
## `qbft_proposeValidatorVote`
Proposes to [add or remove a validator](../../how-to/configure/consensus/qbft.md#add-and-remove-validators) with the specified address.
### Parameters
- `address`: _string_ - Account address.
- `proposal`: _boolean_ - `true` to propose adding a validator, or `false` to propose removing a validator.
### Returns
- `true`
### Example
```bash
curl -X POST http://127.0.0.1:8545/ \
-H "Content-Type: application/json" \
--data '{
"jsonrpc": "2.0",
"method": "qbft_proposeValidatorVote",
"params": [
"0x42d4287eac8078828cf5f3486cfe601a275a49a5",
true
],
"id": 1
}'
```
```json
{
"jsonrpc": "2.0",
"method": "qbft_proposeValidatorVote",
"params": [
"0x42d4287eac8078828cf5f3486cfe601a275a49a5",
true
],
"id": 1
}
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
---
## Reference
This section provides reference material for private network features.
The following features and resources are shared with [public networks](../../public-networks/index.md) and the content can be found in the public networks section:
- [Standard Besu API methods](../../public-networks/reference/api/index.md)
- [Standard configuration options](../../public-networks/reference/options.md)
- [Standard subcommands](../../public-networks/reference/subcommands.md)
- [Genesis file items](../../public-networks/reference/genesis-items.md)
- [EVM tool options](../../public-networks/reference/evm-tool.md)
- [Transaction trace types](../../public-networks/reference/api/trace.md#trace-types)
- [Projects using Besu](../../public-networks/reference/projects-using-besu.md)
- [Security disclosure policy](../../public-networks/reference/disclosure.md)
---
## Private network configuration options
This reference describes the syntax of the Besu private network configuration options.
:::caution Important
This reference contains options that apply to only private networks. For options that apply to both private and public networks, see the [public network options reference](../../public-networks/reference/options.md).
:::
You can specify options:
- On the command line.
Options are part of the command line interface (CLI); run `besu --help` to display all options and [subcommands](subcommands.md).
- As an environment variable.
- In a [configuration file](../../public-networks/how-to/configure-besu/index.md).
If you specify an option in more than one place, the order of priority is command line, environment variable, configuration file.
If using Bash or Z shell, you can view option suggestions by entering `--` and pressing the Tab key twice.
```bash
besu --Tab+Tab
```
:::warning
Characters such as smart quotes and long (em) hyphens don't work in Besu command line options. Ensure quotes aren't automatically converted to smart quotes, or double hyphens combined into em hyphens.
:::
---
## `permissions-accounts-config-file`
```bash
--permissions-accounts-config-file=/home/me/me_configFiles/myPermissionsFile
```
```bash
BESU_PERMISSIONS_ACCOUNTS_CONFIG_FILE=/home/me/me_configFiles/myPermissionsFile
```
```bash
permissions-accounts-config-file="/home/me/me_configFiles/myPermissionsFile"
```
The [accounts permissions configuration file]. The default is the `permissions_config.toml` file in the [data directory](../../public-networks/reference/options.md#data-path).
:::tip
`--permissions-accounts-config-file` and [`--permissions-nodes-config-file`](#permissions-nodes-config-file) can use the same file.
:::
---
## `permissions-accounts-config-file-enabled`
```bash
--permissions-accounts-config-file-enabled=true
```
```bash
BESU_PERMISSIONS_ACCOUNTS_CONFIG_FILE_ENABLED=true
```
```bash
permissions-accounts-config-file-enabled=true
```
Enables or disables file-based account level permissions. The default is `false`.
---
## `permissions-nodes-config-file`
```bash
--permissions-nodes-config-file=/home/me/me_configFiles/myPermissionsFile
```
```bash
BESU_PERMISSIONS_NODES_CONFIG_FILE=/home/me/me_configFiles/myPermissionsFile
```
```bash
permissions-nodes-config-file="/home/me/me_configFiles/myPermissionsFile"
```
The [nodes permissions configuration file]. The default is the `permissions_config.toml` file in the [data directory](../../public-networks/reference/options.md#data-path).
:::tip
`--permissions-nodes-config-file` and [`--permissions-accounts-config-file`](#permissions-accounts-config-file) can use the same file.
:::
---
## `permissions-nodes-config-file-enabled`
```bash
--permissions-nodes-config-file-enabled=true
```
```bash
BESU_PERMISSIONS_NODES_CONFIG_FILE_ENABLED=true
```
```bash
permissions-nodes-config-file-enabled=true
```
Enables or disables file-based node level permissions. The default is `false`.
---
## `poa-block-txs-selection-max-time`
```bash
--poa-block-txs-selection-max-time=80
```
```bash
BESU_POA_BLOCK_TXS_SELECTION_MAX_TIME=80
```
```bash
poa-block-txs-selection-max-time=80
```
The maximum time that can be spent selecting transactions to be included in a block,
as a percentage of the fixed block time of the network.
The default is `75`, or 75%.
:::note
This option only applies to proof-of-authority networks.
For proof-of-stake networks, see
[`--block-txs-selection-max-time`](../../public-networks/reference/options.md#block-txs-selection-max-time).
:::
---
## `poa-discovery-retry-bootnodes`
```bash
--poa-discovery-retry-bootnodes=true
```
```bash
BESU_POA_DISCOVERY_RETRY_BOOTNODES=true
```
```bash
poa-discovery-retry-bootnodes=true
```
When enabled, Besu always uses [bootnodes](../how-to/configure/bootnodes.md) during peer table refresh on Proof of Authority (PoA) networks. When disabled, bootnodes are only used on first startup. If bootnodes are unavailable after startup, the node may not discover new peers until it is restarted. The default is `true`.
:::note
This option only applies to proof of authority (private) networks.
:::
[accounts permissions configuration file]: ../how-to/use-local-permissioning.md#permissions-configuration-file
[nodes permissions configuration file]: ../how-to/use-local-permissioning.md#permissions-configuration-file
[account permissioning]: ../concepts/permissioning.md#account-permissioning
---
## Private network subcommands
This reference describes the syntax of the Besu private network subcommands.
Subcommands are part of the command line interface (CLI); run `besu --help` to display all subcommands and [options](options.md).
:::caution Important
This reference contains subcommands that apply to only private networks. For subcommands that apply to both private and public networks, see the [public network subcommands reference](../../public-networks/reference/subcommands.md).
:::
To start a Besu node using subcommands, run:
```bash
besu [OPTIONS] [SUBCOMMAND] [SUBCOMMAND OPTIONS]
```
If using Bash or Z shell, you can view subcommand suggestions by pressing the Tab key twice.
```bash
besu Tab+Tab
```
---
## `operator`
Provides operator actions.
### `generate-blockchain-config`
```bash
besu operator generate-blockchain-config --config-file= --to= [--genesis-file-name=] [--private-key-file-name=] [--public-key-file-name=]
```
```bash
besu operator generate-blockchain-config --config-file=config.json --to=myNetworkFiles
```
Generates an [IBFT 2.0](../how-to/configure/consensus/ibft.md#genesis-file) or [QBFT](../how-to/configure/consensus/qbft.md#genesis-file) genesis file.
The configuration file has two nested JSON nodes. The first is the `genesis` property defining the IBFT 2.0 or QBFT genesis file, except for the `extraData` string. The second is the `blockchain` property defining the number of key pairs to generate.
---
## `rlp`
Provides RLP related actions.
### `decode`
```bash
besu rlp decode [--from=] [--to=] [--type=]
```
```bash
besu rlp decode --from=ibft_extra_data.txt --to=decoded_ibft_extra_data.txt --type=IBFT_EXTRA_DATA
```
```bash
cat ibft_extra_data.txt | besu rlp decode > decoded_ibft_extra_data.txt
```
Decodes the RLP hexadecimal string used as `extraData` in an
[IBFT 2.0](../how-to/configure/consensus/ibft.md#extra-data) or
[QBFT](../how-to/configure/consensus/qbft.md#extra-data) genesis file into a validator list.
This subcommand takes the following options:
- `from` - The file containing the RLP hexadecimal string to decode.
The default is standard input.
- `to` - The file to write the decoded validator list to.
The default is standard output.
- `type` - `IBFT_EXTRA_DATA` for an IBFT 2.0 `extraData` string, or `QBFT_EXTRA_DATA` for a QBFT
`extraData` string.
The default is `IBFT_EXTRA_DATA`.
### `encode`
```bash
besu rlp encode [--from=] [--to=] [--type=]
```
```bash
besu rlp encode --from=ibft_extra_data.json --to=extra_data_for_ibft_genesis.txt --type=IBFT_EXTRA_DATA
```
```bash
cat extra_data.json | besu rlp encode > rlp.txt
```
Encodes a validator list into an RLP hexadecimal string to use as `extraData` in an
[IBFT 2.0](../how-to/configure/consensus/ibft.md#extra-data) or
[QBFT](../how-to/configure/consensus/qbft.md#extra-data) genesis file.
This subcommand takes the following options:
- `from` - The file containing the validator list to encode.
The default is standard input.
- `to` - The file to write the RLP-encoded hexadecimal string to.
The default is standard output.
- `type` - `IBFT_EXTRA_DATA` for an IBFT 2.0 `extraData` string, or `QBFT_EXTRA_DATA` for a QBFT
`extraData` string.
The default is `IBFT_EXTRA_DATA`.
---
## IBFT 2.0 extra data
To generate the RLP encoded `extraData` string, specify a JSON input that is an array of validator addresses in ascending order.
:::tip JSON schema for `IBFT_EXTRA_DATA`
Use the following JSON schema to validate that your JSON data is well-formatted. To validate your JSON content, use an online validation tool, such as [JSON Schema Validator](https://www.jsonschemavalidator.net/).
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://org.hyperledger.besu/cli_rlp_ibft_extra_data.json",
"type": "array",
"definitions": {},
"title": "IBFT extra data",
"description": "JSON format used as input to generate an IBFT extra data RLP string",
"items": {
"$id": "#/address",
"type": "string",
"title": "Validator address",
"description": "The validator node address",
"default": "",
"examples": [
"be068f726a13c8d46c44be6ce9d275600e1735a4",
"5ff6f4b66a46a2b2310a6f3a93aaddc0d9a1c193"
],
"pattern": "^([0-9a-f]{40})$"
}
}
```
Example `IBFT_EXTRA_DATA` encoding:
```json
[
"be068f726a13c8d46c44be6ce9d275600e1735a4",
"5ff6f4b66a46a2b2310a6f3a93aaddc0d9a1c193"
]
```
```
0xf853a00000000000000000000000000000000000000000000000000000000000000000ea94be068f726a13c8d46c44be6ce9d275600e1735a4945ff6f4b66a46a2b2310a6f3a93aaddc0d9a1c193808400000000c0
```
---
## Deploy using Microsoft Azure
# Deploy private network example on Azure
The [Quorum Dev Quickstart on Azure Marketplace] enables deploying a private IBFT 2.0 network, which includes:
- A bootnode.
- An RPC node.
- Three regular nodes.
- A block explorer.
- Prometheus and Grafana with the Besu dashboard installed.
These are deployed on a single Azure VM in minutes.
Once deployed, you can develop and test applications and connect to the Visual Studio Code (VSCode) plugin using the RPC endpoint `http:///jsonrpc`.
## Overview
The following is a high-level overview of the deployed network.

## Deploy
To deploy the private network example on Azure:
1. Create a Resource Group in the [Azure Portal](https://portal.azure.com).
1. Go to the [Quorum Dev Quickstart on Azure Marketplace].
1. Click **Get It Now** and **Continue**. The Quickstart landing page is displayed.

1. Click **Create**. The **Basics** page is displayed.

1. Enter:
- Details of the Resource Group you created earlier.
- Basic user credentials to start a VM.
- Prefix for your new VM and any other resources created.
- Region to which you wish to deploy the VM.
1. Click **Next: Size** and select the size of the VM you want to use.
1. To start the deployment, click **Review + create** at the bottom left of the page.
The deployment typically takes 3--5 minutes. The progress of your deployment is displayed.
When the deployment is complete, the resources created are displayed.
1. Click **Go to Resource**. Everything created in the deployment is displayed.
1. Click on the VM name. The VM details such as the IP and DNS name are displayed. Use the IP and DNS name displayed to connect to the VM, either in browser or via RPC calls.
## Block explorer
To display the block explorer, open a new tab and enter either the IP of the VM or the DNS name.

## Metrics
The deployment includes Prometheus metrics and Grafana with a custom Besu Dashboard installed. To display the dashboard:
1. Open a new tab and enter the IP or DNS name appended with `/grafana`. For example: `http:///grafana`.
1. Click on home and select the Besu dashboard.

The dashboard provides a visual way to monitor your network and nodes as the chain progresses. Alerting can also be configured.
## Connect to VM RPC endpoint
You can connect dapps or develop directly from the IDE by using VSCode and connecting to the VM RPC endpoint. The endpoint is the DNS name appended with `/jsonrpc`: `http:///jsonrpc`.
## SSH
You can SSH into the VM to see how everything is set up and working. Use the credentials from step 5 of [deployment](#deploy) and your preferred client:
```bash
ssh username@
```
To list all containers running, run `docker ps`. Find the complete setup in `/home//besu-quickstart`.

[Quorum Dev Quickstart on Azure Marketplace]: https://azuremarketplace.microsoft.com/en-us/marketplace/apps/consensys.quorum-dev-quickstart
---
## Deploy a smart contract
# Deploy smart contracts to an Ethereum chain
This tutorial shows you how to deploy smart contracts as transactions to a network.
## Prerequisites
- A local blockchain network. You can use the [Developer Quickstart](../quickstart.md) to rapidly generate
one.
- Install the Solidity compiler using one of the following methods:
- Use the [Solidity releases](https://github.com/ethereum/solidity/releases) for the `solc` binary.
- Run `npm install -g solc` for the JavaScript version.
## Use `eth_sendSignedTransaction`
To deploy a smart contract using
[`eth_sendSignedTransaction`](https://web3js.readthedocs.io/en/v1.2.0/web3-eth.html#sendsignedtransaction), use an account's
private key to sign and serialize the transaction, and send the API request.
This example uses the [web3js](https://www.npmjs.com/package/web3) library to make the API calls.
Using the [`SimpleStorage.sol`](https://github.com/ConsenSys/quorum-dev-quickstart/blob/1e8cc281098923802845cd829ec20c88513c2e1c/files/common/smart_contracts/privacy/contracts/SimpleStorage.sol) smart contract as an example, create a new file called `compile.js` with the following content:
```js title="compile.js"
const fs = require("fs").promises;
const solc = require("solc");
async function main() {
// Load the contract source code
const sourceCode = await fs.readFile("SimpleStorage.sol", "utf8");
// Compile the source code and retrieve the ABI and bytecode
const { abi, bytecode } = compile(sourceCode, "SimpleStorage");
// Store the ABI and bytecode into a JSON file
const artifact = JSON.stringify({ abi, bytecode }, null, 2);
await fs.writeFile("SimpleStorage.json", artifact);
}
function compile(sourceCode, contractName) {
// Create the Solidity Compiler Standard Input and Output JSON
const input = {
language: "Solidity",
sources: { main: { content: sourceCode } },
settings: { outputSelection: { "*": { "*": ["abi", "evm.bytecode"] } } },
};
// Parse the compiler output to retrieve the ABI and bytecode
const output = solc.compile(JSON.stringify(input));
const artifact = JSON.parse(output).contracts.main[contractName];
return {
abi: artifact.abi,
bytecode: artifact.evm.bytecode.object,
};
}
main().then(() => process.exit(0));
```
Run `compile.js` to get the smart contract's output JSON:
```bash
node compile.js
```
Run the compiler to get the contract's bytecode and ABI:
If you installed the compiler from [Solidity releases](https://github.com/ethereum/solidity/releases):
```bash
solc SimpleStorage.sol --bin --abi
```
If you installed via `npm install -g solc`, use **`solcjs`**:
```bash
solcjs SimpleStorage.sol --bin --abi
```
Once you have the bytecode and ABI, you can rename the output files to make them easier to use; this tutorial refers to them as
`SimpleStorage.bin` and `SimpleStorage.abi`.
Create a new file named `public_tx.js` to send the transaction (or run the following commands in a JavaScript console).
The developer quickstart provides an
[example of a public transaction script](https://github.com/ConsenSys/quorum-dev-quickstart/blob/1e8cc281098923802845cd829ec20c88513c2e1c/files/besu/smart_contracts/privacy/scripts/public_tx.js).
```js titl="public_tx.js"
const web3 = new Web3(host);
// use an existing account, or make an account
const privateKey =
"0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63";
const account = web3.eth.accounts.privateKeyToAccount(privateKey);
// read in the contracts
const contractJsonPath = path.resolve(__dirname, "SimpleStorage.json");
const contractJson = JSON.parse(fs.readFileSync(contractJsonPath));
const contractAbi = contractJson.abi;
const contractBinPath = path.resolve(__dirname, "SimpleStorage.bin");
const contractBin = fs.readFileSync(contractBinPath);
// initialize the default constructor with a value `47 = 0x2F`; this value is appended to the bytecode
const contractConstructorInit =
"000000000000000000000000000000000000000000000000000000000000002F";
// get txnCount for the nonce value
const txnCount = await web3.eth.getTransactionCount(account.address);
const rawTxOptions = {
nonce: web3.utils.numberToHex(txnCount),
from: account.address,
to: null, //public tx
value: "0x00",
data: "0x" + contractBin + contractConstructorInit, // contract binary appended with initialization value
gasPrice: "0x0", //ETH per unit of gas
gasLimit: "0x24A22", //max number of gas units the tx is allowed to use
};
console.log("Creating transaction...");
const tx = new Tx(rawTxOptions);
console.log("Signing transaction...");
tx.sign(privateKey);
console.log("Sending transaction...");
var serializedTx = tx.serialize();
const pTx = await web3.eth.sendSignedTransaction(
"0x" + serializedTx.toString("hex").toString("hex"),
);
console.log("tx transactionHash: " + pTx.transactionHash);
console.log("tx contractAddress: " + pTx.contractAddress);
```
`rawTxOptions` contains the following fields:
- `nonce` - the number of transactions sent from an address.
- `from` - address of the sending account. For example `0xfe3b557e8fb62b89f4916b721be55ceb828dbd73`.
- `to` - address of the receiver. To deploy a contract, set to `null`.
- `gas` - amount of gas provided by the sender for the transaction.
- `gasPrice` - price for each unit of gas the sender is willing to pay.
- `data` - binary of the contract (in this example there's also a constructor initialization value, so we append that to the
binary value).
- `value` - amount of Ether/Wei transferred from the sender to the recipient.
Run the `public_tx.js` to send the transaction:
```bash
node public_tx.js
```
This example code creates the transaction `tx`, signs it with the private key of the account, serializes it, then calls
`eth_sendSignedTransaction` to deploy the contract.
## Use `eth_sendTransaction`
You can use [`eth_sendTransaction`](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction) as an alternative
to `eth_sendSignedTransaction`. However, Besu does not support the `eth_sendTransaction` API call and keeps account management
separate for stronger security. Configure [Web3Signer](https://docs.web3signer.consensys.net/) with your Besu node to make the
`eth_sendTransaction` API call.
Pass the following parameters to the [`eth_sendTransaction`](https://docs.web3signer.consensys.net/reference/api/json-rpc#eth_sendtransaction) call to Web3Signer. Web3Signer converts the request to an [`eth_sendRawTransaction`](../../../public-networks/reference/api/eth/submit.md#eth_sendrawtransaction) call that Besu uses:
- `to` - address of the receiver. To deploy a contract, set to `null`.
- `from` - address of the sender account. For example `0x9b790656b9ec0db1936ed84b3bea605873558198`.
- `gas` - amount of gas provided by the sender for the transaction
- `gasPrice` - price for each unit of gas the sender is willing to pay
- `data` - one of the following:
- For contract deployments (this use case) - compiled code of the contract
- For contract interactions - hash of the invoked method signature and encoded parameters (see
[Ethereum Contract ABI](https://solidity.readthedocs.io/en/develop/abi-spec.html))
- For simple ether transfers - empty
```json title="'eth_sendTransaction' parameters"
params: {
"to": null,
"from": "0x9b790656b9ec0db1936ed84b3bea605873558198",
"gas": "0x76c0",
"gasPrice": "0x9184e72a000",
"data": "0x608060405234801561001057600080fd5b5060405161014d38038061014d8339818101604052602081101561003357600080fd5b8101908080519060200190929190505050806000819055505060f38061005a6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80632a1afcd914604157806360fe47b114605d5780636d4ce63c146088575b600080fd5b604760a4565b6040518082815260200191505060405180910390f35b608660048036036020811015607157600080fd5b810190808035906020019092919050505060aa565b005b608e60b4565b6040518082815260200191505060405180910390f35b60005481565b8060008190555050565b6000805490509056fea2646970667358221220e6966e446bd0af8e6af40eb0d8f323dd02f771ba1f11ae05c65d1624ffb3c58264736f6c63430007060033"
}
```
Make the request using `eth_sendTransaction`:
```bash title="'eth_sendTransaction' curl HTTP request"
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{"from":"0x9b790656b9ec0db1936ed84b3bea605873558198", "to":null, "gas":"0x7600","gasPrice":"0x9184e72a000", "data":"0x608060405234801561001057600080fd5b5060405161014d38038061014d8339818101604052602081101561003357600080fd5b8101908080519060200190929190505050806000819055505060f38061005a6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80632a1afcd914604157806360fe47b114605d5780636d4ce63c146088575b600080fd5b604760a4565b6040518082815260200191505060405180910390f35b608660048036036020811015607157600080fd5b810190808035906020019092919050505060aa565b005b608e60b4565b6040518082815260200191505060405180910390f35b60005481565b8060008190555050565b6000805490509056fea2646970667358221220e6966e446bd0af8e6af40eb0d8f323dd02f771ba1f11ae05c65d1624ffb3c58264736f6c63430007060033"}], "id":1}'
```
---
## Interact with a deployed contract
# Interact with deployed smart contracts
You can get started with the [Developer Quickstart](../quickstart.md) to rapidly generate local blockchain networks.
This tutorial shows you how to interact with smart contracts that have been deployed to a network.
## Prerequisites
- A network with a deployed smart contract as in the [deploying smart contracts tutorial](index.md)
## Interact with public contracts
This tutorial uses the [`SimpleStorage.sol`](https://github.com/ConsenSys/quorum-dev-quickstart/blob/1e8cc281098923802845cd829ec20c88513c2e1c/files/common/smart_contracts/privacy/contracts/SimpleStorage.sol) contract:
```js
pragma solidity ^0.7.0;
contract SimpleStorage {
uint public storedData;
constructor(uint initVal) public {
storedData = initVal;
}
function set(uint x) public {
storedData = x;
}
function get() view public returns (uint retVal) {
return storedData;
}
}
```
Once the contract is deployed, you can perform a read operation using the `get` function call and a write operation using the `set` function call. This tutorial uses the [web3js](https://www.npmjs.com/package/web3) library to interact with the contract. A [full example](https://github.com/ConsenSys/quorum-dev-quickstart/blob/1e8cc281098923802845cd829ec20c88513c2e1c/files/besu/smart_contracts/privacy/scripts/public_tx.js) of these calls can be found in the [Developer Quickstart].
### 1. Perform a read operation
To perform a read operation, you need the address that the contract was deployed to and the contract's ABI. The contract's ABI can be obtained from compiling the contract; see the [deploying smart contracts tutorial](index.md) for an example.
Use the [`web3.eth.Contract`](https://web3js.readthedocs.io/en/v1.3.4/web3-eth-contract.html) object to create a new instance of the smart contract, then make the `get` function call from the contract's list of methods, which will return the value stored:
```js
async function getValueAtAddress(
host,
deployedContractAbi,
deployedContractAddress,
) {
const web3 = new Web3(host);
const contractInstance = new web3.eth.Contract(
deployedContractAbi,
deployedContractAddress,
);
const res = await contractInstance.methods.get().call();
console.log("Obtained value at deployed contract is: " + res);
return res;
}
```
### 2. Perform a write operation
To perform a write operation, send a transaction to update the stored value. As with the [`get` call](#1-perform-a-read-operation), you need to use the address that the contract was deployed to and the contract's ABI. The account address must correspond to an actual account with some ETH in it to perform the transaction. Because Besu doesn't manage accounts, this address is the address you use in [Web3Signer](https://docs.web3signer.consensys.net/) (or equivalent) to manage your accounts.
Make the `set` call passing in your account address, `value` as the updated value of the contract, and the amount of gas you are willing to spend for the transaction:
```js
// You need to use the accountAddress details provided to Besu to send/interact with contracts
async function setValueAtAddress(
host,
accountAddress,
value,
deployedContractAbi,
deployedContractAddress,
) {
const web3 = new Web3(host);
const contractInstance = new web3.eth.Contract(
deployedContractAbi,
deployedContractAddress,
);
const res = await contractInstance.methods
.set(value)
.send({ from: accountAddress, gasPrice: "0xFF", gasLimit: "0x24A22" });
return res;
}
```
### 3. Verify an updated value
To verify that a value has been updated, perform a `get` call after a `set` update call.
## Interact with private contracts
This private contracts example uses the same `SimpleStorage.sol` contract as in the [public contracts example](#interact-with-public-contracts), but it uses the [web3js-quorum](https://consensys.github.io/web3js-quorum/latest/index.html) library and the [`generateAndSendRawTransaction`](https://consensys.github.io/web3js-quorum/latest/module-priv.html#~generateAndSendRawTransaction) method to interact with the contract. Both read and write operations are performed using the `generateAndSendRawTransaction` API call. A [full example](https://github.com/ConsenSys/quorum-dev-quickstart/blob/1e8cc281098923802845cd829ec20c88513c2e1c/files/besu/smart_contracts/privacy/scripts/private_tx.js) can be found in the [Developer Quickstart].
### 1. Perform a read operation
As in the public contracts example, to perform a read operation, you need the address that the contract was deployed to and the contract's ABI. You also need your private and public keys and the recipient's public key.
Use the [`web3.eth.Contract`](https://web3js.readthedocs.io/en/v1.3.4/web3-eth-contract.html) object to create a new instance of the smart contract, extract the signature of function's ABI for the `get` method, and then use this value as the `data` parameter for the `generateAndSendRawTransaction` transaction.
The keys remain the same for the sender and recipient, and the `to` field is the contract's address. Once you make the request, you receive a `transactionHash`, which you can use to get a `transactionReceipt` containing the value stored:
```js
async function getValueAtAddress(
clientUrl,
address,
contractAbi,
fromPrivateKey,
fromPublicKey,
toPublicKey,
) {
const Web3 = require("web3");
const Web3Quorum = require("web3js-quorum");
const web3 = new Web3Quorum(new Web3("http://localhost:22000"));
// eslint-disable-next-line no-underscore-dangle
const functionAbi = contract._jsonInterface.find((e) => {
return e.name === "get";
});
const functionParams = {
to: address,
data: functionAbi.signature,
privateKey: fromPrivateKey,
privateFrom: fromPublicKey,
privateFor: [toPublicKey],
};
const transactionHash = await web3quorum.priv.generateAndSendRawTransaction(
functionParams,
);
// console.log(`Transaction hash: ${transactionHash}`);
const result = await web3quorum.priv.waitForTransactionReceipt(
transactionHash,
);
console.log(
"" + nodeName + " value from deployed contract is: " + result.output,
);
return result;
}
```
### 2. Perform a write operation
Performing a write operation is almost the same process as the read operation, except that you encode the new value to the `set` function's ABI, and then append these arguments to the `set` function's ABI and use this as the `data` field:
```js
async function setValueAtAddress(
clientUrl,
address,
value,
contractAbi,
fromPrivateKey,
fromPublicKey,
toPublicKey,
) {
const Web3 = require("web3");
const Web3Quorum = require("web3js-quorum");
const web3 = new Web3Quorum(new Web3("http://localhost:22000"));
// eslint-disable-next-line no-underscore-dangle
const functionAbi = contract._jsonInterface.find((e) => {
return e.name === "set";
});
const functionArgs = web3quorum.eth.abi
.encodeParameters(functionAbi.inputs, [value])
.slice(2);
const functionParams = {
to: address,
data: functionAbi.signature + functionArgs,
privateKey: fromPrivateKey,
privateFrom: fromPublicKey,
privateFor: [toPublicKey],
};
const transactionHash = await web3quorum.priv.generateAndSendRawTransaction(
functionParams,
);
console.log(`Transaction hash: ${transactionHash}`);
const result = await web3quorum.priv.waitForTransactionReceipt(
transactionHash,
);
return result;
}
```
### 3. Verify an updated value
To verify that a value has been updated, perform a `get` call after a `set` update call.
[Developer Quickstart]: ../quickstart.md
---
## Transfer account funds
# Transfer funds between accounts in a transaction
You can get started with the [Developer Quickstart](../quickstart.md) to rapidly generate local blockchain networks.
This tutorial shows you how to transfer funds (ETH) between accounts in a transaction.
## Prerequisites
- A [private network](../quickstart.md)
## Use `eth_sendSignedTransaction`
The simplest way to transfer funds between externally-owned accounts is using [`eth_sendSignedTransaction`](https://web3js.readthedocs.io/en/v1.2.11/web3-eth.html#sendsignedtransaction). This example uses `eth_sendSignedTransaction` and one of the [test accounts](../../reference/accounts-for-testing.md) to transfer funds to a newly created account.
:::danger Do not use the test accounts on Ethereum Mainnet or any production network
The private key is publicly displayed, which means the account is not secure.
:::
Before making the transaction, check the balances of both accounts to verify the funds transfer after the transaction.
```js
const web3 = new Web3(host);
// Pre-seeded account with 90000 ETH
const privateKeyA =
"0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3";
const accountA = web3.eth.accounts.privateKeyToAccount(privateKeyA);
var accountABalance = web3.utils.fromWei(
await web3.eth.getBalance(accountA.address),
);
console.log("Account A has balance of: " + accountABalance);
// Create a new account to transfer ETH to
var accountB = web3.eth.accounts.create();
var accountBBalance = web3.utils.fromWei(
await web3.eth.getBalance(accountB.address),
);
console.log("Account B has balance of: " + accountBBalance);
```
Use the test account address (Account A) for the `from` parameter, the recipient account address (Account B) for the `to` parameter, and the amount of ETH to transfer between accounts for the `value` parameter. Sign the transaction with Account A's private key and send it using `eth_sendSignedTransaction`.
```js
// Send some ETH from A to B
const rawTxOptions = {
nonce: web3.utils.numberToHex(
await web3.eth.getTransactionCount(accountA.address),
),
from: accountA.address,
to: accountB.address,
value: "0x100", // Amount of ETH to transfer
gasPrice: "0x0", // ETH per unit of gas
gasLimit: "0x24A22", // Max number of gas units the tx is allowed to use
};
console.log("Creating transaction...");
const tx = new Tx(rawTxOptions);
console.log("Signing transaction...");
tx.sign(Buffer.from(accountA.privateKey.substring(2), "hex"));
console.log("Sending transaction...");
var serializedTx = tx.serialize();
const pTx = await web3.eth.sendSignedTransaction(
"0x" + serializedTx.toString("hex").toString("hex"),
);
console.log("tx transactionHash: " + pTx.transactionHash);
```
Once it completes, you can see the updated balances.
```js
// After the transaction, there should be some ETH transferred
var accountABalance = await getAccountBalance(host, accountA);
console.log("Account A has an updated balance of: " + accountABalance);
var accountBBalance = await getAccountBalance(host, accountB);
console.log("Account B has an updatedbalance of: " + accountBBalance);
}
```
A [full example](https://github.com/ConsenSys/quorum-dev-quickstart/blob/1e8cc281098923802845cd829ec20c88513c2e1c/files/besu/smart_contracts/privacy/scripts/eth_tx.js) can be found in the Developer Quickstart.
## Use `eth_sendTransaction`
An alternative to using `eth_sendSignedTransaction` is [`eth_sendTransaction`](https://web3js.readthedocs.io/en/v1.2.11/web3-eth.html#sendtransaction). However, Besu does not support the `eth_sendTransaction` API call and keeps account management separate for stronger security. Instead, Besu uses [Web3Signer](https://docs.web3signer.consensys.net/) to make the `eth_sendTransaction` API call.
Use `eth_sendTransaction` similarly to [using `eth_sendSignedTransaction`](#use-eth_sendsignedtransaction) (without the signing step which is done by Web3Signer):
```js
const web3 = new Web3(host);
// Pre-seeded account with 90000 ETH
const privateKeyA = "0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3";
const accountA = web3.eth.accounts.privateKeyToAccount(privateKeyA);
var accountABalance = web3.utils.fromWei(await web3.eth.getBalance(accountA.address));
console.log("Account A has balance of: " + accountABalance);
// Create a new account to transfer ETH to
var accountB = web3.eth.accounts.create();
var accountBBalance = web3.utils.fromWei(await web3.eth.getBalance(accountB.address));
console.log("Account B has balance of: " + accountBBalance);
// Send some ETH from A to B
const txOptions = {
from: accountA.address,
to: accountB.address,
value: "0x100", // Amount of ETH to transfer
gasPrice: "0x0", // ETH per unit of gas
gasLimit: "0x24A22" // Max number of gas units the tx is allowed to use
};
console.log("Creating transaction...");
const pTx = await web3.eth.sendTransaction(txOptions);
console.log("tx transactionHash: " + pTx.transactionHash);
// After the transaction, there should be some ETH transferred
var accountABalance = await getAccountBalance(host, accountA);
console.log("Account A has an updated balance of: " + accountABalance);
var accountBBalance = await getAccountBalance(host, accountB);
console.log("Account B has an updatedbalance of: " + accountBBalance);
}
```
---
## Create a private network using IBFT 2.0
A private network provides a configurable network for testing. This private network uses the [IBFT 2.0 (proof of authority) consensus protocol](../../how-to/configure/consensus/ibft.md).
:::danger
The steps in this tutorial create an isolated, but not protected or secure, Ethereum private network. We recommend running the private network behind a properly configured firewall.
This tutorial configures a private network using IBFT 2.0 for educational purposes only. IBFT 2.0 requires 4 validators to be Byzantine fault tolerant.
:::
## Prerequisites
- [Besu](../../get-started/install/binary-distribution.md)
- [Curl (or similar webservice client)](https://curl.haxx.se/download.html).
## Steps
Listed on the right-hand side of the page are the steps to create a private network using IBFT 2.0 with four nodes. The four nodes are all validators.
### 1. Create directories
Each node requires a data directory for the blockchain data.
Create directories for your private network, each of the four nodes, and a data directory for each node:
```bash
IBFT-Network/
├── Node-1
│ ├── data
├── Node-2
│ ├── data
├── Node-3
│ ├── data
└── Node-4
├── data
```
### 2. Create a configuration file
The configuration file defines the [IBFT 2.0 genesis file](../../how-to/configure/consensus/ibft.md#genesis-file) and the number of node key pairs to generate.
The configuration file has two nested JSON nodes. The first is the `genesis` property defining the IBFT 2.0 genesis file, except for the `extraData` string, which Besu generates automatically in the resulting genesis file. The second is the `blockchain` property defining the number of key pairs to generate.
Copy the following configuration file definition to a file called `ibftConfigFile.json` and save it in the `IBFT-Network` directory:
```json
{
"genesis": {
"config": {
"chainId": 1337,
"berlinBlock": 0,
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
}
},
"nonce": "0x0",
"timestamp": "0x58ee40ba",
"gasLimit": "0x47b760",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "0xad78ebc5ac6200000"
},
"627306090abaB3A6e1400e9345bC60c78a8BEf57": {
"privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
},
"f17f52151EbEF6C7334FAD080c5704D77216b732": {
"privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
}
}
},
"blockchain": {
"nodes": {
"generate": true,
"count": 4
}
}
}
```
:::note
We recommend specifying the latest [milestone](../../../public-networks/reference/genesis-items.md#milestone-blocks) when creating the configuration file for a private network. This ensures you are using the most up-to-date protocol and have access to the most recent opcodes.
:::
:::warning
Do not use the accounts in `alloc` in the genesis file on Mainnet or any public network except for testing. The private keys display, which means the accounts are not secure.
:::
### 3. Generate node keys and a genesis file
In the `IBFT-Network` directory, generate the node key and genesis file:
```bash
besu operator generate-blockchain-config --config-file=ibftConfigFile.json --to=networkFiles --private-key-file-name=key
```
Besu creates the following in the `networkFiles` directory:
- `genesis.json` - The genesis file including the `extraData` property specifying the four nodes are validators.
- A directory for each node named using the node address and containing the public and private key for each node.
```bash
networkFiles/
├── genesis.json
└── keys
├── 0x438821c42b812fecdcea7fe8235806a412712fc0
│ ├── key
│ └── key.pub
├── 0xca9c2dfa62f4589827c0dd7dcf48259aa29f22f5
│ ├── key
│ └── key.pub
├── 0xcd5629bd37155608a0c9b28c4fd19310d53b3184
│ ├── key
│ └── key.pub
└── 0xe96825c5ab8d145b9eeca1aba7ea3695e034911a
├── key
└── key.pub
```
### 4. Copy the genesis file to the IBFT-Network directory
Copy the `genesis.json` file to the `IBFT-Network` directory.
### 5. Copy the node private keys to the node directories
For each node, copy the key files to the `data` directory for that node
```bash
IBFT-Network/
├── genesis.json
├── Node-1
│ ├── data
│ │ ├── key
│ │ ├── key.pub
├── Node-2
│ ├── data
│ │ ├── key
│ │ ├── key.pub
├── Node-3
│ ├── data
│ │ ├── key
│ │ ├── key.pub
├── Node-4
│ ├── data
│ │ ├── key
│ │ ├── key.pub
```
### 6. Start the first node as the bootnode
In the `Node-1` directory, start Node-1:
```bash
besu --data-path=data --genesis-file=../genesis.json --rpc-http-enabled --rpc-http-api=ETH,NET,IBFT --host-allowlist="*" --rpc-http-cors-origins="all" --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=../genesis.json --rpc-http-enabled --rpc-http-api=ETH,NET,IBFT --host-allowlist="*" --rpc-http-cors-origins="all" --profile=ENTERPRISE
```
The command line:
- Specifies the data directory for Node-1 using the [`--data-path`](../../../public-networks/reference/options.md#data-path) option.
- Enables the JSON-RPC API using the [`--rpc-http-enabled`](../../../public-networks/reference/options.md#rpc-http-enabled) option.
- Enables the ETH, NET, and IBFT APIs using the [`--rpc-http-api`](../../../public-networks/reference/options.md#rpc-http-api) option.
- Enables all-host access to the HTTP JSON-RPC API using the [`--host-allowlist`](../../../public-networks/reference/options.md#host-allowlist) option.
- Enables all-domain access to the node through the HTTP JSON-RPC API using the [`--rpc-http-cors-origins`](../../../public-networks/reference/options.md#rpc-http-cors-origins) option.
- Loads the [enterprise/private profile](../../../public-networks/how-to/configure-besu/profile.md#enterpriseprivate-profile)
using the [`--profile`](../../../public-networks/reference/options.md#profile) option.
When the node starts, the [enode URL](../../../public-networks/concepts/node-keys.md#enode-url) displays. Copy the enode URL to specify Node-1 as the bootnode in the following steps.

### 7. Start Node-2
Start another terminal, change to the `Node-2` directory and start Node-2 specifying the Node-1 enode URL copied when starting Node-1 as the bootnode:
```bash
besu --data-path=data --genesis-file=../genesis.json --bootnodes= --p2p-port=30304 --rpc-http-enabled --rpc-http-api=ETH,NET,IBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8546 --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=../genesis.json --bootnodes= --p2p-port=30304 --rpc-http-enabled --rpc-http-api=ETH,NET,IBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8546 --profile=ENTERPRISE
```
The command line specifies:
- The data directory for Node-2 using the [`--data-path`](../../../public-networks/reference/options.md#data-path) option.
- A different port to Node-1 for P2P discovery using the [`--p2p-port`](../../../public-networks/reference/options.md#p2p-port) option.
- A different port to Node-1 for HTTP JSON-RPC using the [`--rpc-http-port`](../../../public-networks/reference/options.md#rpc-http-port) option.
- The enode URL of Node-1 using the [`--bootnodes`](../../../public-networks/reference/options.md#bootnodes) option.
- Other options as for [Node-1](#6-start-the-first-node-as-the-bootnode).
### 8. Start Node-3
Start another terminal, change to the `Node-3` directory and start Node-3 specifying the Node-1 enode URL copied when starting Node-1 as the bootnode:
```bash
besu --data-path=data --genesis-file=../genesis.json --bootnodes= --p2p-port=30305 --rpc-http-enabled --rpc-http-api=ETH,NET,IBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8547 --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=../genesis.json --bootnodes= --p2p-port=30305 --rpc-http-enabled --rpc-http-api=ETH,NET,IBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8547 --profile=ENTERPRISE
```
The command line specifies:
- The data directory for Node-3 using the [`--data-path`](../../../public-networks/reference/options.md#data-path) option.
- A different port to Node-1 and Node-2 for P2P discovery using the [`--p2p-port`](../../../public-networks/reference/options.md#p2p-port) option.
- A different port to Node-1 and Node-2 for HTTP JSON-RPC using the [`--rpc-http-port`](../../../public-networks/reference/options.md#rpc-http-port) option.
- The bootnode as for [Node-2](#7-start-node-2).
- Other options as for [Node-1](#6-start-the-first-node-as-the-bootnode).
### 9. Start Node-4
Start another terminal, change to the `Node-4` directory and start Node-4 specifying the Node-1 enode URL copied when starting Node-1 as the bootnode:
```bash
besu --data-path=data --genesis-file=../genesis.json --bootnodes= --p2p-port=30306 --rpc-http-enabled --rpc-http-api=ETH,NET,IBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8548 --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=..\genesis.json --bootnodes= --p2p-port=30306 --rpc-http-enabled --rpc-http-api=ETH,NET,IBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8548 --profile=ENTERPRISE
```
The command line specifies:
- The data directory for Node-4 using the [`--data-path`](../../../public-networks/reference/options.md#data-path) option.
- A different port to Node-1, Node-2, and Node-3 for P2P discovery using the [`--p2p-port`](../../../public-networks/reference/options.md#p2p-port) option.
- A different port to Node-1, Node-2, and Node-3 for HTTP JSON-RPC using the [`--rpc-http-port`](../../../public-networks/reference/options.md#rpc-http-port) option.
- The bootnode as for [Node-2](#7-start-node-2).
- Other options as for [Node-1](#6-start-the-first-node-as-the-bootnode).
### 10. Confirm the private network is working
Start another terminal, use curl to call the JSON-RPC API [`ibft_getvalidatorsbyblocknumber`](../../reference/api/ibft.md#ibft_getvalidatorsbyblocknumber) method and confirm the network has four validators:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"ibft_getValidatorsByBlockNumber","params":["latest"], "id":1}' localhost:8545/ -H "Content-Type: application/json"
```
The result displays the four validators:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0x1e326b6da177ede2d3eb6d7247bd9f6901d40234",
"0x4aaac297fefe4466ebcb0b23ab90c5f466b11556",
"0xa267ead2e91e1673e0943b925176b51d9cd4f6d2",
"0xe3e680bc0ff485d1d415a384721f19e0db65fea7"
]
}
```
Look at the logs to confirm Besu is producing blocks:
```bash
2020-12-21 07:22:17.883+10:00 | EthScheduler-Workers-0 | INFO | PersistBlockTask | Imported #1 / 0 tx / 0 om / 0 (0.0%) gas / (0xde088192f27ca376eea969cb7a4a1de445bd923fde0444194c88e630f7705584) in 0.010s. Peers: 4
2020-12-21 07:22:19.057+10:00 | pool-8-thread-1 | INFO | IbftRound | Importing block to chain. round=ConsensusRoundIdentifier{Sequence=2, Round=0}, hash=0x2ca2652fa79ae2b3b6aadcfb13d5d362ffd6207c3b5ae47971e04eb9d05deaa9
2020-12-21 07:22:21.044+10:00 | pool-8-thread-1 | INFO | IbftRound | Importing block to chain. round=ConsensusRoundIdentifier{Sequence=3, Round=0}, hash=0x5d9a06cd17127712cfae7d1c25f705f302e146f4b64a73de3c814e1b5a3f9a16
2020-12-21 07:22:23.049+10:00 | pool-8-thread-1 | INFO | IbftRound | Importing block to chain. round=ConsensusRoundIdentifier{Sequence=4, Round=0}, hash=0x843981375f4cb2bb0f33a09b647ac27da5df2c539d940d8344c907eede57829c
2020-12-21 07:22:25.060+10:00 | pool-8-thread-1 | INFO | IbftRound | Importing block to chain. round=ConsensusRoundIdentifier{Sequence=5, Round=0}, hash=0x82b2069961d9185f7857cad1123de72d715729e122441335db486ea436834d6e
```
:::info
If the key files were not copied to the correct directory in [step 5](#5-copy-the-node-private-keys-to-the-node-directories), the network will not start producing blocks.
The logs for each node should indicate the public key was loaded from the `data/key` directory:
```bash
2020-12-21 07:16:18.360+10:00 | main | INFO | KeyPairUtil | Loaded public key 0xe143eadaf670d49afa3327cae2e655b083f5a89dac037c9af065914a9f8e6bceebcfe7ae2258bd22a9cd18b6a6de07b9790e71de49b78afa456e401bd2fb22fc from /IBFT-Network/Node-1/data/key
```
If the keys were not copied to the correct directory, Besu creates a key when starting up:
```bash
2020-12-21 07:33:11.458+10:00 | main | INFO | KeyPairUtil | Generated new public key 0x1a4a2ade5ebc0a85572e2492e0cdf3e96b8928c75fa55b4425de8849850cf9b3a8cad1e27d98a3d3afac326a5e8788dbe6cc40249715c92825aebb28abe3e346 and stored it to /IBFT-Network/Node-1/data/key
```
If a new key was created, the validator key specified in the configuration does not match the created key and the node cannot participate in creating blocks.
:::
## Next steps
Use the [IBFT API](../../reference/api/ibft.md) to remove or add validators.
:::note
To add or remove nodes as validators you need the node address. The directory [created for each node](#3-generate-node-keys-and-a-genesis-file) has the node address as the name.
This tutorial configures a private network using IBFT 2.0 for educational purposes only. IBFT 2.0 requires four validators to be Byzantine fault tolerant.
:::
Import accounts to MetaMask and send transactions as described in the [Quickstart tutorial](../quickstart.md#6-send-a-transaction-with-metamask).
:::info
Besu doesn't support [private key management](../../../public-networks/how-to/send-transactions.md).
:::
## Stop the nodes
When finished using the private network, stop all nodes using ++ctrl+c++ in each terminal window.
:::tip
To restart the IBFT 2.0 network in the future, start from [6. Start First Node as Bootnode](#6-start-the-first-node-as-the-bootnode).
:::
[IBFT 2.0 (proof of authority)consensus protocol]: ../../how-to/configure/consensus/ibft.md
\*[Byzantine fault tolerant]: Ability to function correctly and reach consensus despite nodes failing or propagating incorrect information to peers.
---
## Add and removing IBFT 2.0 validators
# Add and remove IBFT 2.0 validators
This example walks through [adding and removing an IBFT 2.0 validator](../../how-to/configure/consensus/ibft.md#add-and-remove-validators).
## Prerequisites
- [IBFT 2.0 network as configured in the IBFT 2.0 tutorial](index.md)
## Add a validator
### 1. Create directories
Create a working directory and a data directory for the new node that needs to be added:
```bash
mkdir -p Node-5/data
```
### 2. Start the node
Change into the working directory for the new Node-5 and start the node, specifying the [Node-1 enode URL](index.md#6-start-the-first-node-as-the-bootnode) as the bootnode:
```bash
besu --data-path=data --genesis-file=../genesis.json --bootnodes= --p2p-port=30307 --rpc-http-enabled --rpc-http-api=ETH,NET,IBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8549 --profile=ENTERPRISE
```
The command line specifies:
- The data directory for Node-5 using the [`--data-path`](../../../public-networks/reference/options.md#data-path) option.
- A different port to Node-1 for P2P discovery using the [`--p2p-port`](../../../public-networks/reference/options.md#p2p-port) option.
- A different port to Node-1 for HTTP JSON-RPC using the [`--rpc-http-port`](../../../public-networks/reference/options.md#rpc-http-port) option.
- The enode URL of Node-1 using the [`--bootnodes`](../../../public-networks/reference/options.md#bootnodes) option.
- Other options as for [Node-1](index.md#6-start-the-first-node-as-the-bootnode).
### 3. Copy the address of the node
Copy the address of the node. You can find the address in the logs when starting the new node:
```bash
2021-05-28 09:49:00.881+10:00 | main | INFO | DefaultP2PNetwork | Node address 0x90626e6a67445aabf1c0615410d108d4733aa90b
```
Or use the [`public-key export-address`](../../../public-networks/reference/subcommands.md#export-address) subcommand:
```bash
besu --data-path=IBFT-Network/Node-5/data public-key export-address
```
```bash
0x90626e6a67445aabf1c0615410d108d4733aa90b
```
### 4. Propose adding the new validator
Propose adding the new validator from more than half the number of current validators, using [`ibft_proposeValidatorVote`](../../reference/api/ibft.md#ibft_proposevalidatorvote), specifying the address of the proposed validator and `true`:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"ibft_proposeValidatorVote","params":["0x90626e6a67445aabf1c0615410d108d4733aa90b", true], "id":1}' http://127.0.0.1:8545/ -H "Content-Type: application/json"
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": true
}
```
Repeat the proposal process for this candidate node from at least two of the other nodes.
### 5. Verify the addition of the new validator
Verify that the new validator is now in the list of validators using [`ibft_getValidatorsByBlockNumber`](../../reference/api/ibft.md#ibft_getvalidatorsbyblocknumber):
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"ibft_getValidatorsByBlockNumber","params":["latest"], "id":1}' http://127.0.0.1:8545/ -H "Content-Type: application/json"
```
```json
[
"0x189d23d201b03ae1cf9113672df29a5d672aefa3",
"0x2aabbc1bb9bacef60a09764d1a1f4f04a47885c1",
"0x44b07d2c28b8ed8f02b45bd84ac7d9051b3349e6",
"0x4c1ccd426833b9782729a212c857f2f03b7b4c0d",
"0x90626e6a67445aabf1c0615410d108d4733aa90b"
]
```
The list of validators contains 5 addresses now.
## Remove a validator
The process for removing a validator is similar to [adding a validator](#add-a-validator) starting from step 2, except you specify `false` as the second parameter of [`ibft_proposeValidatorVote`](../../reference/api/ibft.md#ibft_proposevalidatorvote).
---
## Deploy charts
You can deploy Besu Helm charts for a Kubernetes cluster.
## Prerequisites
- Clone the [Quorum-Kubernetes](https://github.com/ConsenSys/quorum-kubernetes) repository
- A [running Kubernetes cluster](cluster.md)
- Install [Kubectl](https://kubernetes.io/docs/tasks/tools/)
- Install [Helm3](https://helm.sh/docs/intro/install/)
## Provision with Helm charts
Helm is a method of packaging a collection of objects into a chart which can then be deployed to the cluster. After you have cloned the [Quorum-Kubernetes](https://github.com/ConsenSys/quorum-kubernetes) repository, change the directory to `helm` for the rest of this tutorial.
```bash
cd helm
```
Each helm chart has the following key-map values which you will need to set depending on your needs. The `cluster.provider` is used as a key for the various cloud features enabled. Please specify only one cloud provider, not both. At present, the charts have full support for cloud native services in both AWS and Azure. Please note that if you use GCP, IBM etc please set `cluster.provider: local` and set `cluster.cloudNativeServices: false`.
Please update the `aws` or `azure` map as shown below if you deploy to either cloud provider.
```bash
cluster:
provider: local # choose from: local | aws | azure
cloudNativeServices: false # set to true to use Cloud Native Services (SecretsManager and IAM for AWS; KeyVault & Managed Identities for Azure)
reclaimPolicy: Delete # set to either Retain or Delete; note that PVCs and PVs will still exist after a 'helm delete'. Setting to Retain will keep volumes even if PVCs/PVs are deleted in kubernetes. Setting to Delete will remove volumes from EC2 EBS when PVC is deleted
quorumFlags:
privacy: false
removeKeysOnDelete: false
aws:
# the aws cli commands uses the name 'quorum-node-secrets-sa' so only change this if you altered the name
serviceAccountName: quorum-node-secrets-sa
# the region you are deploying to
region: ap-southeast-2
azure:
# the script/bootstrap.sh uses the name 'quorum-pod-identity' so only change this if you altered the name
identityName: quorum-pod-identity
# the clientId of the user assigned managed identity created in the template
identityClientId: azure-clientId
keyvaultName: azure-keyvault
# the tenant ID of the key vault
tenantId: azure-tenantId
# the subscription ID to use - this needs to be set explicitly when using multi tenancy
subscriptionId: azure-subscriptionId
```
Setting the `cluster.cloudNativeServices: true`:
- Stores keys in Azure Key Vault or AWS Secrets Manager.
- Uses Azure Managed Identities or AWS Identity and Access Management for pod identity access.
:::note
You can customize any of the charts in this repository to suit your requirements, and make pull requests to extend functionality.
:::
### 1. Check that you can connect to the cluster with `kubectl`
Verify kubectl is connected to cluster using: (use the latest version)
```bash
kubectl version
```
The result looks similar to:
```bash
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.1", GitCommit:"86ec240af8cbd1b60bcc4c03c20da9b98005b92e", GitTreeState:"clean", BuildDate:"2021-12-16T11:41:01Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.3", GitCommit:"c92036820499fedefec0f847e2054d824aea6cd1", GitTreeState:"clean", BuildDate:"2021-10-27T18:35:25Z", GoVersion:"go1.16.9", Compiler:"gc", Platform:"linux/amd64"}
```
### 2. Create the namespace
This tutorial isolates groups of resources (for example, StatefulSets and Services) within a single cluster.
:::note
The rest of this tutorial uses `besu` as the namespace, but you're free to pick any name when deploying, as long as it's consistent across the [infrastructure scripts](cluster.md) and charts.
:::
Run the following in a terminal window:
```bash
kubectl create namespace besu
```
### 3. Deploy the monitoring chart
This chart deploys Prometheus and Grafana to monitor the metrics of the cluster, nodes and state of the network.
Update the admin `username` and `password` in the [monitoring values file](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/helm/values/monitoring.yml). Configure alerts to the receiver of your choice (for example, email or Slack), then deploy the chart using:
```bash
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack --version 34.10.0 --namespace=besu --values ./values/monitoring.yml --wait
kubectl --namespace besu apply -f ./values/monitoring/
```
Metrics are collected via a [ServiceMonitor](https://github.com/prometheus-operator/prometheus-operator/blob/7c77626e5e270a2530e187b185d45eeed8a773bf/Documentation/user-guides/getting-started.md) that scrapes each Besu pod, using given [`annotations`](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) which specify the port and path to use. For example:
```bash
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: 9545
prometheus.io/path: "/metrics"
```
:::warning
For production use cases, configure Grafana with one of the supported [native auth mechanisms](https://grafana.com/docs/grafana/latest/auth/).
:::

Optionally you can also deploy the [Elastic Stack](https://www.elastic.co/elastic-stack/) to view logs (and metrics).
```bash
helm repo add elastic https://helm.elastic.co
helm repo update
# if on cloud
helm install elasticsearch --version 7.17.1 elastic/elasticsearch --namespace quorum --values ./values/elasticsearch.yml
# if local - set the replicas to 1
helm install elasticsearch --version 7.17.1 elastic/elasticsearch --namespace quorum --values ./values/elasticsearch.yml --set replicas=1 --set minimumMasterNodes: 1
helm install kibana --version 7.17.1 elastic/kibana --namespace quorum --values ./values/kibana.yml
helm install filebeat --version 7.17.1 elastic/filebeat --namespace quorum --values ./values/filebeat.yml
```
If you install `filebeat`, please create a `filebeat-*` index pattern in `kibana`. All the logs from the nodes are sent to the `filebeat` index. If you use The Elastic stack for logs and metrics, please deploy `metricbeat` in a similar manner to `filebeat` and create an index pattern in Kibana.

To connect to Kibana or Grafana, we also need to deploy an ingress so you can access your monitoring endpoints publicly. We use Nginx as our ingress here, and you are free to configure any ingress per your requirements.
```bash
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install quorum-monitoring-ingress ingress-nginx/ingress-nginx \
--namespace quorum \
--set controller.ingressClassResource.name="monitoring-nginx" \
--set controller.ingressClassResource.controllerValue="k8s.io/monitoring-ingress-nginx" \
--set controller.replicaCount=1 \
--set controller.nodeSelector."kubernetes\.io/os"=linux \
--set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
--set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
--set controller.service.externalTrafficPolicy=Local
kubectl apply -f ../ingress/ingress-rules-monitoring.yml
```
Once complete, view the IP address listed under the `Ingress` section if you're using the Kubernetes Dashboard or on the command line `kubectl -n quorum get services quorum-monitoring-ingress-ingress-nginx-controller`.
:::note
We refer to the ingress here as `external-nginx` because it deals with monitoring endpoints specifically. We also deploy a second ingress called `network-ingress` which is for the blockchain nodes only in [step 8](#9-connect-to-the-node-from-your-local-machine-via-an-ingress)
:::

You can view the Besu dashboard by going to:
```bash
http:///d/XE4V0WGZz/besu-overview?orgId=1&refresh=10s
```
You can view the Kibana dashboard (if deployed) by going to:
```bash
http:///kibana
```
### 4. Deploy the genesis chart
The genesis chart creates the genesis file and keys for the validators.
:::warning
It's important to keep the release names of the initial validator pool as per this tutorial, that is `validator-n`, where `n` is the node number. Any validators created after the initial pool can be named to anything you like.
:::
The override [values.yml](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/helm/values/genesis-besu.yml) looks like below:
```bash
---
quorumFlags:
removeGenesisOnDelete: true
cluster:
provider: local # choose from: local | aws | azure
cloudNativeServices: false
aws:
# the aws cli commands uses the name 'quorum-node-secrets-sa' so only change this if you altered the name
serviceAccountName: quorum-node-secrets-sa
# the region you are deploying to
region: ap-southeast-2
azure:
# the script/bootstrap.sh uses the name 'quorum-pod-identity' so only change this if you altered the name
identityName: quorum-pod-identity
# the clientId of the user assigned managed identity created in the template
identityClientId: azure-clientId
keyvaultName: azure-keyvault
# the tenant ID of the key vault
tenantId: azure-tenantId
# the subscription ID to use - this needs to be set explicitly when using multi tenancy
subscriptionId: azure-subscriptionId
# the raw Genesis config
# rawGenesisConfig.blockchain.nodes set the number of validators
rawGenesisConfig:
genesis:
config:
chainId: 1337
algorithm:
consensus: qbft # choose from: ibft2 | qbft
blockperiodseconds: 10
epochlength: 30000
requesttimeoutseconds: 20
gasLimit: '0x47b760'
difficulty: '0x1'
coinbase: '0x0000000000000000000000000000000000000000'
blockchain:
nodes:
generate: true
count: 4
accountPassword: 'password'
```
Please set the `aws`, `azure` and `cluster` keys are as per the [Provisioning](#provision-with-helm-charts) step. `quorumFlags.removeGenesisOnDelete: true` tells the chart to delete the genesis file when the chart is deleted. If you may wish to retain the genesis on deletion, please set that value to `false`.
The last config item is `rawGenesisConfig` which has details of the chain you are creating, please edit any of the parameters in there to match your requirements. To set the number of initial validators set the `rawGenesisConfig.blockchain.nodes` to the number that you'd like. We recommend using the Byzantine formula of `N=3F+1` when setting the number of validators.
One more thing to note is that when `cluster.cloudNativeServices: true` is set, the genesis job will not add the [Quickstart](../quickstart.md) test accounts into the genesis file.
When you are ready deploy the chart with :
```bash
cd helm
helm install genesis ./charts/besu-genesis --namespace besu --create-namespace --values ./values/genesis-besu.yml
```
Once completed, view the genesis and enodes (the list of static nodes) configuration maps that every Besu node uses, and the validator and bootnode node keys as secrets.


### 5. Deploy the bootnodes
This is an optional but recommended step. In a production setup we recommend the use of two ore more bootnodes for best practices. Each Besu node has a map that tells the StatefulSet what to deploy and how to clean up. The default `values.yml` for the StatefulSet define the following flags which are present in all the override values files.
```bash
---
quorumFlags:
privacy: false
removeKeysOnDelete: true
isBootnode: true # set this to true if this node is a bootnode
usesBootnodes: true # set this to true if the network you are connecting to use a bootnode/s that are deployed in the cluster
cluster:
provider: local # choose from: local | aws | azure
cloudNativeServices: false
reclaimPolicy: Delete # set to either Retain or Delete; note that PVCs and PVs will still exist after a 'helm delete'. Setting to Retain will keep volumes even if PVCs/PVs are deleted in kubernetes. Setting to Delete will remove volumes from EC2 EBS when PVC is deleted
aws:
# the aws cli commands uses the name 'quorum-node-secrets-sa' so only change this if you altered the name
serviceAccountName: quorum-node-secrets-sa
# the region you are deploying to
region: ap-southeast-2
azure:
# the script/bootstrap.sh uses the name 'quorum-pod-identity' so only change this if you altered the name
identityName: quorum-pod-identity
# the clientId of the user assigned managed identity created in the template
identityClientId: azure-clientId
keyvaultName: azure-keyvault
# the tenant ID of the key vault
tenantId: azure-tenantId
# the subscription ID to use - this needs to be set explicitly when using multi tenancy
subscriptionId: azure-subscriptionId
node:
besu:
metrics:
serviceMonitorEnabled: true
resources:
cpuLimit: 1
cpuRequest: 0.1
memLimit: "2G"
memRequest: "1G"
```
Please set the `aws`, `azure` and `cluster` keys are as per the [Provisioning](#provision-with-helm-charts) step. `quorumFlags.removeKeysOnDelete: true` tells the chart to delete the node's keys when the chart is deleted. If you may wish to retain the keys on deletion, please set that value to `false`.
For the bootnodes only, set the `quorumFlags.isBootnode: true`. When using bootnodes you have to also set `quorumFlags.usesBootnodes: true` to indicate that all nodes on the network will use these bootnodes.
:::note
If you use bootnodes, you must set `quorumFlags.usesBootnodes: true` in the override values.yaml for every other node type, that is validators.yaml, txnode.yaml and reader.yaml
:::
```bash
helm install bootnode-1 ./charts/besu-node --namespace besu --values ./values/bootnode.yml
helm install bootnode-2 ./charts/besu-node --namespace besu --values ./values/bootnode.yml
```
Once complete, you see two StatefulSets, and the two bootnodes discover themselves and peer. Because there are no validators present yet, there are no blocks created, as seen in the following logs.

### 6. Deploy the validators
The validators peer with the bootnodes and themselves, and when a majority of the validators have peered, blocks are proposed and created on the chain.
These are the next set of nodes that we will deploy. The charts use four validators (default) to replicate best practices for a network. The override [values.yml](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/helm/values/validator.yml) for the StatefulSet looks like below:
```bash
---
quorumFlags:
privacy: false
removeKeysOnDelete: false
isBootnode: false # set this to true if this node is a bootnode
usesBootnodes: true # set this to true if the network you are connecting to use a bootnode/s that are deployed in the cluster
```
Please set the `aws`, `azure` and `cluster` keys are as per the [Provisioning](#provision-with-helm-charts) step. `quorumFlags.removeKeysOnDelete: true` tells the chart to delete the node's keys when the chart is deleted. If you may wish to retain the keys on deletion, please set that value to `false`.
:::warning
Please note that if you delete a majority of the validators, the network will halt. Additionally, if the validator keys are deleted you may not be able to recover as you need a majority of the validators up to vote to add new validators into the pool
:::
When using bootnodes (if deployed in the previous step) you have to also set `quorumFlags.usesBootnodes: true` to indicate that all nodes on the network will use these bootnodes.
For the initial validator pool we set all the node flags to `false` and then deploy.
```bash
helm install validator-1 ./charts/besu-node --namespace besu --values ./values/validator.yml
helm install validator-2 ./charts/besu-node --namespace besu --values ./values/validator.yml
helm install validator-3 ./charts/besu-node --namespace besu --values ./values/validator.yml
helm install validator-4 ./charts/besu-node --namespace besu --values ./values/validator.yml
```
:::warning
It's important to keep the release names of the validators the same as it is tied to the keys that the genesis chart creates. So we use `validator-1`, `validator-2`, etc. in the following command.
:::
Once completed, you may need to give the validators a few minutes to peer and for round changes, depending on when the first validator was spun up, before the logs display blocks being created.

### 7. Add/Remove additional validators to the validator pool
To add (or remove) more validators to the initial validator pool, you need to deploy a node such as an RPC node (step 8) and then [vote](../../how-to/configure/consensus/ibft.md#add-and-remove-validators) that node in. The vote API call must be made on a majority of the existing pool and the new node will then become a validator.
Please refer to the [Ingress Section](#9-connect-to-the-node-from-your-local-machine-via-an-ingress) for details on making the API calls from your local machine or equivalent.
### 8. Deploy RPC nodes
An RPC node is a node that can be used to make public transactions or perform read heavy operations such as when connected to a chain explorer like [BlockScout](https://github.com/blockscout/blockscout).
The RPC override [values.yml](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/helm/values/reader.yml) for the StatefulSet looks identical to that of the validators above, and will create its own node keys before the node starts.
To deploy an RPC node:
```bash
helm install rpc-1 ./charts/besu-node --namespace besu --values ./values/reader.yml
```
Logs for Besu resemble the following:

:::note
In these examples we use `rpc-1` as a release name for the deployment. You can pick any release name that you'd like to use in place of those as per your requirements.
:::
### 9. Connect to the node from your local machine via an ingress
In order to view the Grafana dashboards or connect to the nodes to make transactions from your local machine you can deploy an ingress controller with rules. We use the `ingress-nginx` ingress controller which can be deployed as follows:
```bash
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install quorum-network-ingress ingress-nginx/ingress-nginx \
--namespace quorum \
--set controller.ingressClassResource.name="network-nginx" \
--set controller.ingressClassResource.controllerValue="k8s.io/network-ingress-nginx" \
--set controller.replicaCount=1 \
--set controller.nodeSelector."kubernetes\.io/os"=linux \
--set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
--set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
--set controller.service.externalTrafficPolicy=Local
```
Use [pre-defined rules](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/ingress/ingress-rules-besu.yml) to test functionality, and alter to suit your requirements (for example, restrict access for API calls to trusted CIDR blocks).
Edit the [rules](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/ingress/ingress-rules-besu.yml) file so that the service names match your release name. In the example, we deployed a transaction node with the release name `member-1` so the corresponding service is called `besu-node-member-1`. Once you have settings that match your deployments, deploy the rules as follows:
```bash
kubectl apply -f ../ingress/ingress-rules-besu.yml
```
Once complete, view the IP address listed under the `Ingress` section if you're using the Kubernetes Dashboard or on the command line `kubectl -n quorum get services quorum-network-ingress-ingress-nginx-controller`.

The following is an example RPC call, which confirms that the node running the JSON-RPC service is syncing:
```bash
curl -v -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http:///rpc
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x4e9"
}
```
### 10. Blockchain explorer
You can deploy [BlockScout](https://github.com/blockscout/blockscout) to aid with monitoring the blockchain. To do this, update the [BlockScout values file](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/helm/values/blockscout-besu.yml) and set the `database` and `secret_key_base` values.
:::important
Changes to the database requires changes to both the `database` and the `blockscout` dictionaries.
:::
Once completed, deploy the chart using:
```bash
helm dependency update ./charts/blockscout
helm install blockscout ./charts/blockscout --namespace quorum --values ./values/blockscout-goquorum.yaml
```
You can optionally deploy the [Quorum-Explorer](https://github.com/ConsenSys/quorum-explorer) as a lightweight blockchain explorer. The Quorum Explorer is not recommended for use in production and is intended for demonstration or Development purposes only. The Explorer can give an overview over the whole network, such as querying each node on the network for node or block information, voting (add/remove) validators from the network, and sending transactions between wallets as you would do in MetaMask. Please see the [Explorer](quorum-explorer.md) page for details on how to use the application.
:::warning
The accounts listed in the file below are for test purposes only and should not be used on a production network.
:::
To deploy the application, update the [Explorer values file](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/helm/values/explorer-besu.yaml) with details of your nodes and endpoints and then deploy.
```bash
helm install quorum-explorer ./charts/explorer --namespace besu --values ./values/explorer-besu.yaml
```
You will also need deploy the ingress (if not already done in [Monitoring](#3-deploy-the-monitoring-chart) to access the endpoint on `http:///explorer`

---
## Create a cluster
You can create a [local](#local-clusters) or [cloud](#cloud-clusters) cluster to deploy a Besu network using Kubernetes.
## Prerequisites
- Clone the [Quorum-Kubernetes](https://github.com/ConsenSys/quorum-kubernetes) repository
- Install [Kubectl](https://kubernetes.io/docs/tasks/tools/)
- Install [Helm3](https://helm.sh/docs/intro/install/)
- Install [AWS CLI](https://aws.amazon.com/cli/) and [`eksctl`](https://eksctl.io/) for AWS EKS clusters
- Install [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) for Azure AKS clusters
- Install the cloud-specific CLI
## Local Clusters
Use one of several options to create a local cluster. Select one listed below, or another that you're comfortable with.
### Minikube
[Minikube](https://minikube.sigs.k8s.io/docs/start/) is one of the most popular options to spin up a local Kubernetes cluster for development. You can [install a version](https://minikube.sigs.k8s.io/docs/start/) based on your architecture.
:::note
We recommend at least 2 CPUs and 16GB of RAM.
:::
To start the cluster, run the following command:
```bash
minikube start --cpus 2 --memory 16384 --cni auto
```
### kind
[kind (Kubernetes in Docker)](https://kind.sigs.k8s.io) is a lightweight tool for running local Kubernetes clusters. The [installation](https://kind.sigs.k8s.io/docs/user/quick-start#installation) is similar to [Minikube](#minikube).
To start the cluster, run the following command:
```bash
kind create cluster
```
### Rancher
[Rancher](https://github.com/rancher-sandbox/rancher-desktop/) is a lightweight open source desktop application for Mac, Windows, and Linux. It provides Kubernetes and container management, and allows you to choose the version of Kubernetes to run.
It can build, push, pull, and run container images. Built container images can be run without needing a registry.
:::note
The official Docker-CLI is not supported but rather uses [nerdctl](https://github.com/containerd/nerdctl) which is a Docker-CLI compatible tool for containerd, and is automatically installed with Rancher Desktop.
:::
:::note
For Windows, you must [install Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install) to install Rancher Desktop.
Refer to the [official Rancher Desktop documentation](https://docs.rancherdesktop.io/) for system requirements and installation instructions.
:::
## Cloud clusters
### AWS EKS
[AWS Elastic Kubernetes Service (AWS EKS)](https://aws.amazon.com/eks/) is one of the most popular platforms to deploy Besu.
To create a cluster in AWS, you must install the [AWS CLI](https://aws.amazon.com/cli/) and [`eksctl`](https://eksctl.io/).
The [template](https://github.com/ConsenSys/quorum-kubernetes/tree/master/aws) comprises the base infrastructure used to build the cluster and other resources in AWS. We also use some native services with the cluster for performance and best practices, these include:
- [Pod identities](https://github.com/aws/amazon-eks-pod-identity-webhook).
- [Secrets Store CSI drivers](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html).
- Dynamic storage classes backed by AWS EBS. The [volume claims](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) are fixed sizes and can be updated as you grow via helm updates, and won't need to re-provision the underlying storage class.
- [CNI](https://docs.aws.amazon.com/eks/latest/userguide/pod-networking.html) networking mode for EKS. By default, EKS clusters use `kubenet` to create a virtual network and subnet. Nodes get an IP address from a virtual network subnet. Network address translation (NAT) is then configured on the nodes, and pods receive an IP address "hidden" behind the node IP.
:::note
This approach reduces the number of IP addresses that you must reserve in your network space for pods, but constrains what can connect to the nodes from outside the cluster (for example, on-premise nodes or those on another cloud provider).
:::
AWS Container Networking Interface (CNI) provides each pod with an IP address from the subnet, and can be accessed directly. The IP addresses must be unique across your network space, and must be planned in advance. Each node has a configuration parameter for the maximum number of pods that it supports. The equivalent number of IP addresses per node are then reserved up front for that node. This approach requires more planning, and can lead to IP address exhaustion as your application demands grow, however makes it easier for external nodes to connect to your cluster.
:::warning
EKS clusters must not use 169.254.0.0/16, 172.30.0.0/16, 172.31.0.0/16, or 192.0.2.0/24 for the Kubernetes service address range.
:::
To provision the cluster:
1. Update [cluster.yml](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/aws/templates/cluster.yml)
2. Deploy the template:
```bash
eksctl create cluster -f ./templates/cluster.yml
```
3. Your `.kube/config` should be connected to the cluster automatically, but if not, run the commands below and replace `AWS_REGION` and `CLUSTER_NAME` with details that are specific to your deployment.
```bash
aws sts get-caller-identity
aws eks --region AWS_REGION update-kubeconfig --name CLUSTER_NAME
```
4. After the deployment completes, provision the EBS drivers for the volumes. While it is possible to use the in-tree `aws-ebs` driver that's natively supported by Kubernetes, it is no longer being updated and does not support newer EBS features such as the [cheaper and better gp3 volumes](https://stackoverflow.com/questions/68359043/whats-the-difference-between-ebs-csi-aws-com-vs-kubernetes-io-aws-ebs-for-provi). The `cluster.yml` file (from the steps above) that is included in this folder automatically deploys the cluster with the EBS IAM policies, but you need to install the EBS CSI drivers. This can be done through the AWS Management Console for simplicity, or via a CLI command as below. Replace `CLUSTER_NAME`, `AWS_REGION` and `AWS_ACCOUNT` with details that are specific to your deployment.
```bash
eksctl create iamserviceaccount --name ebs-csi-controller-sa --namespace kube-system --cluster CLUSTER_NAME --region AWS_REGION --attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy --approve --role-only --role-name AmazonEKS_EBS_CSI_DriverRole
eksctl create addon --name aws-ebs-csi-driver --cluster CLUSTER_NAME --region AWS_REGION --service-account-role-arn arn:aws:iam::AWS_ACCOUNT:role/AmazonEKS_EBS_CSI_DriverRole --force
```
5. Once the deployment is completed, provision the Secrets Manager IAM and CSI driver. Use `besu` (or equivalent) for `NAMESPACE` and replace `CLUSTER_NAME`, `AWS_REGION` and `AWS_ACCOUNT` with details that are specific to your deployment.
```bash
helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
helm install --namespace kube-system --create-namespace csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver
kubectl apply -f https://raw.githubusercontent.com/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml
POLICY_ARN=$(aws --region AWS_REGION --query Policy.Arn --output text iam create-policy --policy-name quorum-node-secrets-mgr-policy --policy-document '{
"Version": "2012-10-17",
"Statement": [ {
"Effect": "Allow",
"Action": ["secretsmanager:CreateSecret","secretsmanager:UpdateSecret","secretsmanager:DescribeSecret","secretsmanager:GetSecretValue","secretsmanager:PutSecretValue","secretsmanager:ReplicateSecretToRegions","secretsmanager:TagResource"],
"Resource": ["arn:aws:secretsmanager:AWS_REGION:AWS_ACCOUNT:secret:besu-node-*"]
} ]
}')
# If you have deployed the above policy before, you can acquire its ARN:
POLICY_ARN=$(aws iam list-policies --scope Local \
--query 'Policies[?PolicyName==`quorum-node-secrets-mgr-policy`].Arn' \
--output text)
eksctl create iamserviceaccount --name quorum-node-secrets-sa --namespace NAMESPACE --region=AWS_REGION --cluster CLUSTER_NAME --attach-policy-arn "$POLICY_ARN" --approve --override-existing-serviceaccounts
```
:::warning
The above command creates a service account called `quorum-node-secrets-sa` and is preconfigured in the helm charts override `values.yml` files, for ease of use.
:::
6. Optionally, deploy the [kubernetes dashboard](https://github.com/ConsenSys/quorum-kubernetes/tree/master/aws/templates/k8s-dashboard).
7. You can now use your cluster and you can deploy [Helm charts](charts.md) to it.
### Azure Kubernetes Service
[Azure Kubernetes Service (AKS)](https://azure.microsoft.com/en-us/services/kubernetes-service/) is another popular cloud platform that you can use to deploy Besu. To create a cluster in Azure, you must install the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and have admin rights on your Azure subscription to enable some preview features on AKS.
The [template](https://github.com/ConsenSys/quorum-kubernetes/tree/master/azure) comprises the base infrastructure used to build the cluster and other resources in Azure. We also make use Azure native services and features after the cluster is created. These include:
- [AAD pod identities](https://docs.microsoft.com/en-us/azure/aks/use-azure-ad-pod-identity).
- [Secrets Store CSI drivers](https://docs.microsoft.com/en-us/azure/key-vault/general/key-vault-integrate-kubernetes).
- Dynamic storage classes backed by Azure Files. The [volume claims](https://docs.microsoft.com/en-us/azure/aks/azure-disks-dynamic-pv) are fixed sizes and can be updated as you grow via helm updates, and won't need to re-provision the underlying storage class.
- [CNI](https://docs.microsoft.com/en-us/azure/aks/configure-azure-cni) networking mode for AKS. By default, AKS clusters use `kubenet`, to create a virtual network and subnet. Nodes get an IP address from a virtual network subnet. Network address translation (NAT) is then configured on the nodes, and pods receive an IP address "hidden" behind the node IP.
:::note
This approach reduces the number of IP addresses you must reserve in your network space for pods to use, but constrains what can connect to the nodes from outside the cluster (for example, on-premise nodes or other cloud providers).
:::
AKS Container Networking Interface (CNI) provides each pod with an IP address from the subnet, and can be accessed directly. These IP addresses must be unique across your network space, and must be planned in advance. Each node has a configuration parameter for the maximum number of pods that it supports. The equivalent number of IP addresses per node are then reserved up front for that node. This approach requires more planning, and can leads to IP address exhaustion as your application demands grow, however makes it easier for external nodes to connect to your cluster.
:::warning
Please do not create more than one AKS cluster in the same subnet. AKS clusters may not use `169.254.0.0/16`, `172.30.0.0/16`, `172.31.0.0/16`, or `192.0.2.0/24` for the Kubernetes service address range.
:::
To provision the cluster:
1. Enable the preview features that allow you to use AKS with CNI, and a managed identity to authenticate and run cluster operations with other services. We also enable [AAD pod identities](https://docs.microsoft.com/en-us/azure/aks/use-azure-ad-pod-identity) which use the managed identity. This is in preview, so you must enable this feature by registering the `EnablePodIdentityPreview` feature:
```bash
az feature register --name EnablePodIdentityPreview --namespace Microsoft.ContainerService
```
This takes a little while and you can check on progress by running:
```bash
az feature list --namespace Microsoft.ContainerService -o table
```
Install or update your local Azure CLI with preview features:
```bash
az extension add --name aks-preview
az extension update --name aks-preview
```
1. Create a resource group if you don't already have one:
```bash
az group create --name BesuGroup --location "East US"
```
1. Deploy the template:
1. Navigate to the [Azure portal](https://portal.azure.com), select **+ Create a resource** in the upper left corner.
1. Search for `Template deployment (deploy using custom templates)` and select **Create**.
1. Select **Build your own template in the editor**.
1. Remove the contents (JSON) in the editor and paste in the contents of [`azuredeploy.json`](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/azure/arm/azuredeploy.json)
1. Select **Save**.
1. Input provisioning parameters in the displayed user interface.
1. Provision the drivers:
1. Run the [bootstrap](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/azure/scripts/bootstrap.sh) script.
1. Use `besu` for `AKS_NAMESPACE`, and update `AKS_RESOURCE_GROUP`, `AKS_CLUSTER_NAME`, and `AKS_MANAGED_IDENTITY` in the commands below to match your settings and deployed resources from step 3.
```bash
./scripts/bootstrap.sh "AKS_RESOURCE_GROUP" "AKS_CLUSTER_NAME" "AKS_MANAGED_IDENTITY" "AKS_NAMESPACE"
```
1. You can now use your cluster and you can deploy [Helm charts](charts.md) to it.
---
## Deploy a Besu private network with Kubernetes
# Deploy Besu using Kubernetes
Use the [reference implementations](https://github.com/ConsenSys/besu-kubernetes) to install private networks using Kubernetes (K8s). Reference implementations are available using:
- [Helm](https://github.com/ConsenSys/quorum-kubernetes/tree/master/helm).
- [Helmfile](https://github.com/roboll/helmfile).
- [`kubectl`](https://github.com/ConsenSys/besu-kubernetes/tree/master/playground/kubectl).
Familiarize yourself with the reference implementations and customize them for your requirements.
## Quorum-Kubernetes
[Quorum-Kubernetes](https://github.com/ConsenSys/quorum-Kubernetes) is a repository containing Kubernetes manifests and Helm charts that you can customize and deploy on a local cluster or in the cloud.
:::important
We recommend starting with the [playground](https://github.com/ConsenSys/quorum-kubernetes/tree/master/playground) directory and working through the example setups before moving to the [`Helm charts`](https://github.com/ConsenSys/quorum-kubernetes/tree/master/helm/) directory.
:::
The `helm` directory contains charts for the various components, and each chart has a `cluster` map with features that you can toggle.
```bash
cluster:
provider: local # choose from: local | aws | azure
cloudNativeServices: false # set to true to use Cloud Native Services (SecretsManager and IAM for AWS; KeyVault & Managed Identities for Azure)
```
Setting `cluster.cloudNativeServices: true` stores keys in AWS Secrets Manager or Azure Key Vault instead of Kubernetes Secrets, and will also make use of AWS IAM or Azure Managed Identities for the pods.
### Cloud support
The repository's `helm` charts support on-premise and cloud providers such as AWS, Azure, GCP, IBM etc. You can configure the provider in the [values.yml](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/helm/values/genesis-besu.yml) file of the respective charts by setting `cluster.provider` to `local`, `aws`, or `azure`. If you use GCP, IBM etc., please set `cluster.provider: local` and `cluster.cloudNativeServices: false`.
The repository also contains [Azure ARM templates](https://github.com/ConsenSys/quorum-kubernetes/tree/master/azure) and [AWS `eksctl` templates](https://github.com/ConsenSys/quorum-kubernetes/tree/master/aws) to deploy the required base infrastructure.
## Limitations
When using multi-clusters, Kubernetes load balancers disallow TCP and UDP traffic on the same port, which inhibits discovery working natively for each pod. Use the following solutions to mitigate this limitation:
- Disallow discovery and use static nodes to allow only TCP traffic. This isn't an issue for load balancers or exposing nodes publicly.
- If you need to use discovery, use something such as [CNI](#cni) which is supported by all major cloud providers, and the cloud templates already have CNI implemented.
### CNI
With the traditional `kubenet` networking mode, nodes get an IP from the virtual network subnet. Each node in turn uses NAT to configure the pods so that they reach other pods on the virtual network. This limits where they can reach but also more specifically what can reach them. For example, an external VM which must have custom routes does not scale well.

CNI, on the other hand, allows every pod to get a unique IP directly from the virtual subnet which removes this restriction. Therefore, it has a limit on the maximum number of pods that can be spun up, so you must plan ahead to avoid IP exhaustion.

## Multi-cluster
You must enable [CNI](#cni) to use multi-cluster, or to connect external nodes to an existing Kubernetes cluster. To connect multiple clusters, they must each have different CIDR blocks to ensure no conflicts, and the first step is to peer the VPCs or VNets together and update the route tables. From that point on you can use static nodes and pods to communicate across the cluster.
The same setup also works to connect external nodes and business applications from other infrastructure, either in the cloud or on premise.

## Concepts
### Namespaces
In Kubernetes, [namespaces](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) provide a mechanism for isolating groups of resources within a single cluster. Both namespaces and resources (for example, Stateful Sets or Services) within a namespace must be unique, but resources across namespaces don't need to be.
:::note
Namespace-based scoping is not applicable for cluster-wide objects (for example, Storage Class or Persistent Volumes).
:::
### Nodes
Consider using Stateful Sets instead of Deployments for Besu. The term 'client node' refers to bootnode, validator and member/RPC nodes. For Besu nodes, we only use CLI arguments to keep things consistent.
### Role-based access controls
We encourage using role-based access controls (RBACs) for access to the private key of each node, that is, only a specific pod or statefulset is allowed to access a specific secret.
If you need to specify a Kube configuration file for each pod, use the `KUBE_CONFIG_PATH` variable.
### Storage
We use separate data volumes to store the blockchain data. This is similar to using separate volumes to store data when using docker containers natively or docker-compose. This is done for a few reasons:
- Containers are mortal and we do not want to store data on them.
- Kubernetes host nodes can fail and we want the chain data to persist.
Ensure that you provide enough data storage capacity for all nodes on the cluster. Select the appropriate type of [Storage Class](https://kubernetes.io/docs/concepts/storage/storage-classes/) based on your cloud provider. In the templates, the size of the [volume claims](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) is set to 20Gb by default; you can change this depending on your needs. If you have a different storage account than the one in the charts, you may edit those [Storage Classes](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/helm/charts/besu-node/templates/node-storage.yaml).
When using Persistent Volume Claims, set the `allowVolumeExpansion` to `true`. This helps keep costs low and enables growing the volume over time rather than creating new volumes and copying data across.
### Monitoring
We recommend deploying metrics to get an overview of the network, nodes, and volumes. You can also create alerts.
Besu publishes metrics to Prometheus, and you can configure metrics using the kubernetes scraper configuration. We also have custom Grafana dashboards to monitor the blockchain.
:::note
Refer to `values/monitoring.yml` to configure the alerts per your requirements (for example slack or email).
:::
```bash
cd helm
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack --version 34.10.0 --namespace=besu --create-namespace --values ./values/monitoring.yml --wait
kubectl --namespace besu apply -f ./values/monitoring/
```
You can configure Besu to suit your environment. For example, use the Elastic charts to log to a file that you can parse using Logstash into an ELK cluster.
```bash
cd helm
helm repo add elastic https://helm.elastic.co
helm repo update
# if on cloud
helm install elasticsearch --version 7.17.1 elastic/elasticsearch --namespace besu --create-namespace --values ./values/elasticsearch.yml
# if local - set the replicas to 1
helm install elasticsearch --version 7.17.1 elastic/elasticsearch --namespace besu --create-namespace --values ./values/elasticsearch.yml --set replicas=1 --set minimumMasterNodes: 1
helm install kibana --version 7.17.1 elastic/kibana --namespace besu --values ./values/kibana.yml
helm install filebeat --version 7.17.1 elastic/filebeat --namespace besu --values ./values/filebeat.yml
```
### Ingress Controllers
If you require the ingress controllers for the RPC calls or the monitoring dashboards, we have provided example [rules](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/ingress/ingress-rules-besu.yml) that are pre-configured for common use cases. Use these as a reference and develop solutions to match your network topology and requirements.
---
## Maintenance
You can perform maintenance for Besu on a Kubernetes cluster.
## Prerequisites
- Clone the [Quorum-Kubernetes](https://github.com/ConsenSys/quorum-kubernetes) repository
- A [running Kubernetes cluster](cluster.md) with a [network](charts.md)
- Install [Kubectl](https://kubernetes.io/docs/tasks/tools/)
- Install [Helm3](https://helm.sh/docs/intro/install/)
## Update a persistent volume claim size
Over time, as the chain grows, so will the amount of space used by the persistent volume claim (PVC). As of Kubernetes v1.11, [certain types of Storage Classes](https://kubernetes.io/docs/concepts/storage/storage-classes/#allow-volume-expansion) allow volume resizing. Production charts for Azure use Azure Files, and on AWS use EBS Block Store which allow for volume expansion.
To update the volume size, you must update the override values file. For example, to increase the size on the transaction nodes volumes, add the following snippet to the [`txnode values.yml`](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/helm/values/txnode.yml) file, with the new size limit (the following example uses 50Gi).
```bash
storage:
sizeLimit: "50Gi"
pvcSizeLimit: "50Gi"
```
Once complete, update the node via helm:
```bash
helm upgrade tx-1 ./charts/besu-node --namespace besu --values ./values/txnode.yml
```
## Update Besu versions
:::important
When updating Besu nodes across a cluster, perform the updates as a rolling update and not all at once, especially for the validator pool. If all the validators are taken offline, the chain halts, and you must wait for round changes to expire before blocks are created again.
:::
Updates for Besu can be done via Helm in exactly the same manner as other applications. Alternatively, this can be done via `kubectl`. This example updates a node called `besu-validator-3`:
1. Set the update policy to use rolling updates (if not done already):
```bash
kubectl patch statefulset besu-validator-3 --namespace besu -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}}'
```
2. Update the Besu version via Helm:
```bash
helm upgrade bootnode-1 ./charts/besu-node --namespace besu --values ./values/bootnode.yml --set image.besu.tag=21.10.0
```
Or via `kubectl`:
```bash
kubectl patch statefulset besu-validator-3 --namespace besu --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"hyperledger/besu:21.10.0"}]'
```
---
## Deploy Besu across multiple Kubernetes clusters across multiple cloud providers
The following tutorial is just one of many ways to connect nodes in one K8S cluster to nodes in another K8S
cluster across multiple cloud provider - in this case [Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/)
and [Azure Kubernetes Service (AKS)](https://azure.microsoft.com/en-au/products/kubernetes-service)
This tutorial walks you through using AWS as the main cluster and adding an extra node in Azure to the existing pool
## Overview
### Steps
#### 1. Create an AWC VPC
1. Use a CIDR block that doesn't overlap with that of Azure eg `10.0.0.0/16`
2. Create the EKS cluster as normal and use the default Kubernetes service range `172.20.0.0/16`
#### 2. Create an Azure Virtual Network
1. Use a CIDR block that doesn't overlap with that of AWS eg `10.1.0.0/16`
2. It is also recommended to create a subnet for the Gateway and use a CIDR of `/24` eg `10.1.1.0/24`
3. Create the AKS cluster as normal and use the different Kubernetes service range
`10.2.0.0/16` (the default `10.0.0.0/16` overlaps with the AWS VPC CIDR block)
#### 3. Connect the AWS VPC and Azure VNet with a site to site VPN
##### 3.1 On the Azure side create a Virtual Network Gateway
In the AZure VNet, create a Virtual Network Gateway with the following settings
| Setting | Value |
|----------------------|-------------|
| SKU | VpnGw2AZ (default) |
| Gateway Type | VPN |
| VPN Type | Route-based |
| Virtual Network | Use the network in step 2.1 |
| Gateway subnet | Use the subnet from step 2.2 |
| Public IP Address | Create new |
| Enable active-active mode | Disabled |
| Configure BGP | Disabled |
The other settings can remain as defaults or set to suit your requirements. Once this is complete
please note down the IP address that was created for the Virtual Network Gateway
##### 3.2 On the AWS side create a Customer Gateway
This Customer Gateway points to the Azure Virtual Network Gateay from step 3.1
| Setting | Value |
|----------------------|-------------|
| Routing | Static |
| IP Address | Use the IP of the Virtual Network Gateway in step 3.1 |
The other settings can remain as defaults or set to suit your requirements
##### 3.3 On the AWS side create a Virtual Private Gateway
Create an AWS Virtual Private Gateway and specify the name.
| Setting | Value |
|----------------------|-------------|
| ASN | Amazon Default ASN |
##### 3.4 On the AWS side attach the Virtual Private Gateway to the VPC
Select the Virtual Private Gateway and then select Actions and `Attach to VPC` and select
the VPC in step 1
##### 3.5 On the AWS side create the Site to Site VPN Connection
Create an AWS Site-to-Site VPN Connection with the following settings
| Setting | Value |
|----------------------|-------------|
| Target Gateway Type | Virtual Private Gateway |
| Virtual Private Gateway | Select the Virtual Private Gateway from step 3.3 |
| Customer Gateway | Existing |
| Customer Gateway ID | Select the Customer Gateway from step 3.2 |
| Routing Options | Static |
| Static IP Prefixes | Use the Azure VNet CIDR from step 2.1 |
| Tunnel inside IP version | IPV4 |
The other settings can remain as defaults or set to suit your requirements
##### 3.6 Download the VPN connection config file
Select the VPN connection once it has been created and use the following options and then save the file locally
| Setting | Value |
|----------------------|-------------|
| Vendor | Generic |
| Platform | Generic |
| Software | Vendor Agnostic |
Save the file and open it. In there you will find the shared keys and putlic address for each tunnel created above
You need to use the `Pre-Shared Key` in the next step in Azure as well as the `public IP` of Tunnel 1 of the VPN
connection (There are two created, and we just use #1 for this example)
##### 3.7 On the Azure side create a Local Network Gateway
Create an Azure Local Network Gateway using the pubic IP address from step 3.6 of the tunnel and the CIDR block of
the AWS VPC
| Setting | Value |
|----------------------|-------------|
| Endpoint | IP Address |
| IP Address | Use the IP address from step 3.6 of the VPN Connection |
| Address space | Use the AWS CIDR block from step 1 |
| Configure BGP | No |
##### 3.8 On the Azure side create a Connection on the existing Virtual Network Gateway
Open the settings of the Virtual Network Gateway created in step 3.1. Then select `Connections` and `Add`.
Use the settings below
| Setting | Value |
|----------------------|-------------|
| Connection Type | Site-to-Site IPSec |
| Virtual Network Gateway | Use the Virtual Network Gateway created in step 3.1 |
| Local Network Gateway | Use the Local Network Gateway created in step 3.7 |
| Authentication method | Shared Key (PSK) |
| Shared Key(PSK) | Use the key from the config file downloaded in step 3.6 |
| IKE Protocol | IKEv2 |
| BGP | Disabled |
| Use policy based traffic selector | Disabled |
The other settings can remain as defaults or set to suit your requirements
This may take a few minutes to setup. Once complete you should see the Tunnel from step 3.5 status show as `UP`
##### 3.9 High Availability on the Azure side
If you need high availability or this is a production setup, please use Tunnel #2 to create a second
Local Network Gateway (step 3.7) and then a second connection on the Virtual Network Gateway (step 3.8)
##### 3.10 On AWS update the subnet route table
On the AWS side please update the route tables of your subnets to use the Virtual gateway and set the destination
as the Azure VNet CIDR block
| Destination | Target |
|----------------------|-------------|
| 10.1.0.0/16 | vgw -..... |
Please replace the Azure CIDR block with that of your own and select the id of the Virtual Gateway from step 3.3
:::caution
Also note that if each subnet has a different route table, then this change needs to be added to each subnet that you
EKS nodes with Besu running on them
:::
#### 4. Update security groups to allow traffic
##### 4.1 On AWS side
Find the security group of the node pool that contains your Besu nodes and add this in to the `Inbound` rules to allow
traffic from the Azure VNet
| Type | Protocol | Port range | Destination | Description |
|------------|----------|------------|-------------|-------------|
| Custom UDP | UDP | `30303` | `10.1.0.0/16` | Azure |
| Custom TCP | TCP | `30303` | `10.1.0.0/16` | Azure |
| Custom TCP | TCP | `8545 ` | `10.1.0.0/16` | Azure |
Please update the CIDR to only be a subnet CIDR if you have your nodes in select subnets.
##### 4.2 On Azure side
Find the network security group of the node pool that contains your Besu nodes and add this in to the `Inbound` rules to allow
traffic from the Azure VNet
| Type | Protocol | Port range | Destination | Name |
|------------|----------|------------|-------------|-------------|
| UDP | UDP | `30303` | `10.0.0.0/16` | AWS |
| TCP | TCP | `30303` | `10.0.0.0/16` | AWS |
| TCP | TCP | `8545 ` | `10.0.0.0/16` | AWS |
Please update the CIDR to only be a subnet CIDR if you have your nodes in select subnets.
---
## Local playground
# Deploy in a local environment
The [playground](https://github.com/ConsenSys/quorum-kubernetes/tree/master/playground) was created to provide an opportunity to deploy [quorum-kubernetes](https://github.com/ConsenSys/quorum-kubernetes/) in a local environment before attempting in a live environment (such as in the cloud or on-premise). Local deployment can be done with any local Kubernetes tool. Minikube and Rancher Desktop have been tested to work, but any complete Kubernetes solution with support for `kubectl` should suffice.
## Steps
1. Navigate to the playground [`README`](https://github.com/ConsenSys/quorum-kubernetes/tree/master/playground).
1. Ensure that your system meets the requirements specified.
1. Choose your Ethereum client (Besu or GoQuorum): `quorum-besu` or `quorum-go`.
1. Choose your consensus algorithm. The playground supports IBFT2 for Besu, and IBFT for GoQuorum.
1. Follow the instructions from the `README` for the chosen client and consensus algorithm folder.
## Important notes
Consider the following when deploying and developing with the playground:
- The playground is created specifically for developers and operators to become familiar with the deployment of Besu in a Kubernetes environment in preparation for going into a cloud or on-premise environment. Thus, it should **not** be deployed into a production environment.
- The playground is not a complete reflection of the `helm` charts as it does not use `Helm`, but rather static or non-templated code that is deployed through `kubectl apply -f`. This means that without `Helm` there's a significant amount of repeated code. This is fine for development but not ideal for a production environment.
- The playground uses static/hard-coded keys. Automatic key generation is only supported in `helm` charts.
- As the playground is for local development, no cloud integration or lifecycle support is offered.
---
## Production
# Deploy for production
You can deploy Besu for production on a Kubernetes cluster.
## Prerequisites
- Clone the [Quorum-Kubernetes](https://github.com/ConsenSys/quorum-kubernetes) repository
- A [running Kubernetes cluster](cluster.md)
- [Kubectl](https://kubernetes.io/docs/tasks/tools/)
- [Helm3](https://helm.sh/docs/intro/install/)
## Overview
To get things production-ready, we'll use the same charts, and set a few of the values in the `cluster` map as in the [Deploy](#deploy-the-network) section.
:::warning
The following tutorial ONLY supports AWS and Azure currently. Other cloud providers will be added in time.
:::
:::warning
We recommend using AWS RDS or Azure PostgreSQL in High Availability mode for any Tessera nodes that you use. The templates don't include that functionality. They can be provisioned with CloudFormation or Azure Resource Manager, respectively. Once created, please specify the connection details to the `values.yml`.
:::
## Deploy
### Check that you can connect to the cluster with `kubectl`
Once you have a [cluster running](cluster.md), verify `kubectl` is connected to cluster with:
```bash
kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.1", GitCommit:"86ec240af8cbd1b60bcc4c03c20da9b98005b92e", GitTreeState:"clean", BuildDate:"2021-12-16T11:41:01Z", GoVersion:"go1.17.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.3", GitCommit:"c92036820499fedefec0f847e2054d824aea6cd1", GitTreeState:"clean", BuildDate:"2021-10-27T18:35:25Z", GoVersion:"go1.16.9", Compiler:"gc", Platform:"linux/amd64"}
```
### Deploy the network
For the rest of this tutorial we use Helm charts. After you have cloned the [Quorum-Kubernetes](https://github.com/ConsenSys/quorum-kubernetes) repository, change the directory to `helm` for the rest of this tutorial.
```bash
cd helm
```
Each helm chart has the following keys that must be set.
Specify either `aws` or `azure` for the `cluster.provider`. Additionally, set `cloudNativeServices: true` and `reclaimPolicy: Retain` so that it looks like the following for AWS:
```bash
cluster:
provider: aws # choose from: aws | azure
cloudNativeServices: true # set to true to use Cloud Native Services (SecretsManager and IAM for AWS; KeyVault & Managed Identities for Azure)
reclaimPolicy: Retain # set to either Retain or Delete; note that PVCs and PVs will still exist after a 'helm delete'. Setting to Retain will keep volumes even if PVCs/PVs are deleted in kubernetes. Setting to Delete will remove volumes from EC2 EBS when PVC is deleted
```
Follow the steps outlined in the [deploy charts](charts.md) tutorial to deploy the network.
## Best practices
The most important thing is to plan your network out on paper first and then test it in a Dev cluster to make sure connectivity works with your applications and you get the required throughput in transactions per second (TPS). We also recommend you test the entire process, from provisioning infrastructure to updating nodes on a Dev cluster, prior to launching your production network.
By default, the cloud Kubernetes clusters take care of availability and do multi-zones within a region. The scheduler also ensures that deployments are spread out across zones. Where possible, we recommend you use multiple bootnodes and static nodes to speed up peering.
You can connect to APIs and services outside the cluster normally, but connecting into your network (such as adding an on-premise node to the network) might require more configuration. Please check the [limitations](index.md#limitations) and use CNI where possible. To connect an external node to your cluster, the easiest way is to use a VPN as seen in the following [multi-cluster](#multi-cluster-support) setup.
Finally, we recommend setting up monitoring and alerting from the beginning, so you can get early warnings of issues rather than after failure. We have a monitoring chart which uses Grafana and you can use it with Alertmanager to create alerts or alternatively alert via Cloudwatch or Azure Monitoring.
## Multi-cluster support
When CNI is used, multi-cluster support is simple, but you have to cater for cross-cluster DNS names. Ideally, you want to create two separate VPCs (or VNets) and make sure they have different base CIDR blocks so that IP addresses don't conflict. Once done, peer the VPCs together and update the subnet route table, so they are effectively a giant single network.

When you [spin up clusters](cluster.md), use [CNI](index.md#limitations) and CIDR blocks to match the subnet's CIDR settings. Then deploy the genesis chart on one cluster and copy across the genesis file and static nodes config maps. Depending on your DNS settings, they might be fine as is, or they might need to be actual IP addresses. That is, you can provision cluster B only after cluster A has Besu nodes up and running.
Deploy the network on cluster A, and then on cluster B. Besu nodes on cluster A should work as expected, and Besu nodes on cluster B should use the list of peers provided to communicate with the nodes on cluster A.
Keeping the list of peers on the clusters live and up to date can be challenging, so we recommend using the cloud service provider's DNS service such as Route 53 or Azure DNS and adapting the charts to create entries for each node when it comes up.
---
## Use the Quorum Explorer
You can use the Quorum Explorer on a Kubernetes cluster.
## Prerequisites
- Clone the [Quorum-Kubernetes](https://github.com/ConsenSys/quorum-kubernetes) repository
- A [running Kubernetes cluster](cluster.md)
- [Kubectl](https://kubernetes.io/docs/tasks/tools/)
- [Helm3](https://helm.sh/docs/intro/install/)
- [Existing network](charts.md)
## Deploy the Quorum Explorer helm chart
[Quorum-Explorer](https://github.com/ConsenSys/quorum-explorer) as a lightweight blockchain explorer. The Quorum Explorer is **not** recommended for use in production and is intended for demonstration or development purposes only.
The explorer can provide an overview over the whole network, such as block information, voting or removing validators from the network, and sending transactions between wallets in one interface.
To use the explorer, update the [Quorum-Explorer values file](https://github.com/ConsenSys/quorum-kubernetes/blob/5920caff6dd15b4ca17f760ad9e4d7d2e43b41a1/helm/values/explorer-besu.yaml) with your node details and endpoints, and then [deploy](charts.md).
## Nodes
The **Nodes** page provides an overview of the nodes on the network. Select the node you would like to interact with from the drop-down on the top right, and you'll get details of the node, block height, peers, queued transactions etc.

## Validators
The **Validators** page simulates a production environment or consortium where each node individually runs API calls to vote to add a validator or remove an existing validator.
When using the buttons to remove, discard pending validators, or proposing a validator, the app sends an API request to the selected node in the drop-down only. To add or remove a validator you need to select a majority of the existing validator pool individually, and perform the vote API call by clicking the button. Each node can call a discard on the voting process during or after the validator has been added.
The vote calls made from non-validator nodes have no effect on overall consensus.

## Explorer
The **Explorer** page gives you the latest blocks from the chain and the latest transactions as they occur on the network. In addition, you can search by block number or transaction hash using the respective search bar.

## Contracts
Use the **Contracts** page to compile and deploy a smart contract. Currently, the only contract available for deployment through the app is the `SimpleStorage` contract. However, in time, we plan to add more contracts to that view.
In this example, we deploy from `member-1` and select `member-1` and `member-3` in the **Private For** multi-select. Then click on `Compile` and `Deploy`

Once deployed, you can interact with the contract. As this is a new transaction, select `member-1` and `member-3` in **Interact** multi-select, and then click on the appropriate method call to `get` or `set` the value at the deployed contract address.

To test the private transaction functionality, select `member-2` from the drop-down on the top right, you'll notice that you are unable to interact with the contract because `member-2` was not part of the transaction. Only `members-1` and `member-3` responds correctly.
## Wallet
The **Wallet** page gives you the functionality to send simple ETH transactions between accounts by providing the account's private key, the recipient's address, and transfer amount in Wei.

---
## Create a permissioned network
The following steps set up a permissioned network with local node and account permissions. The network uses the [IBFT 2.0 proof of authority consensus protocol].
:::danger
A permissioned Ethereum network as described here is not protected against all attack vectors. We recommend applying defense in depth to protect your infrastructure.
:::
## Prerequisites
- [Besu](../../get-started/install/binary-distribution.md)
- [curl (or similar Web service client)](https://curl.haxx.se/download.html)
## Steps
### 1. Create folders
Each node requires a data directory for the blockchain data.
Create directories for your permissioned network and each of the three nodes, and a data directory for each node:
```bash
Permissioned-Network/
├── Node-1
│ ├── data
├── Node-2
│ ├── data
└── Node-3
│ ├── data
└── Node-4
├── data
```
### 2. Create the configuration file
The configuration file defines the [IBFT 2.0 genesis file](../../how-to/configure/consensus/ibft.md#genesis-file) and the number of node key pairs to generate.
The configuration file has two nested JSON nodes. The first is the `genesis` property defining the IBFT 2.0 genesis file, except for the `extraData` string, which Besu generates automatically in the resulting genesis file. The second is the `blockchain` property defining the number of key pairs to generate.
Copy the following configuration file definition to a file called `ibftConfigFile.json` and save it in the `Permissioned-Network` directory:
```json
{
"genesis": {
"config": {
"chainId": 1337,
"berlinBlock": 0,
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
}
},
"nonce": "0x0",
"timestamp": "0x58ee40ba",
"gasLimit": "0x47b760",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "0xad78ebc5ac6200000"
},
"627306090abaB3A6e1400e9345bC60c78a8BEf57": {
"privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
},
"f17f52151EbEF6C7334FAD080c5704D77216b732": {
"privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
}
}
},
"blockchain": {
"nodes": {
"generate": true,
"count": 4
}
}
}
```
:::danger Security warning
Don't use the accounts in the genesis file on Mainnet or any public network except for testing. The private keys display, which means the accounts are not secure.
:::
### 3. Generate node keys and a genesis file
In the `Permissioned-Network` directory, generate the node key and genesis file:
```bash
besu operator generate-blockchain-config --config-file=ibftConfigFile.json --to=networkFiles --private-key-file-name=key
```
Besu creates the following in the `networkFiles` directory:
- `genesis.json` - The genesis file including the `extraData` property specifying the four nodes are validators.
- A directory for each node named using the node address and containing the public and private key for each node.
```bash
networkFiles/
├── genesis.json
└── keys
├── 0x438821c42b812fecdcea7fe8235806a412712fc0
│ ├── key
│ └── key.pub
├── 0xca9c2dfa62f4589827c0dd7dcf48259aa29f22f5
│ ├── key
│ └── key.pub
├── 0xcd5629bd37155608a0c9b28c4fd19310d53b3184
│ ├── key
│ └── key.pub
└── 0xe96825c5ab8d145b9eeca1aba7ea3695e034911a
├── key
└── key.pub
```
### 4. Copy the genesis file to the Permissioned-Network directory
Copy the `genesis.json` file to the `Permissioned-Network` directory.
### 5. Copy the node private keys to the node directories
For each node, copy the key files to the `data` directory for that node
```bash
Permissioned-Network/
├── genesis.json
├── Node-1
│ ├── data
│ │ ├── key
│ │ ├── key.pub
├── Node-2
│ ├── data
│ │ ├── key
│ │ ├── key.pub
├── Node-3
│ ├── data
│ │ ├── key
│ │ ├── key.pub
├── Node-4
│ ├── data
│ │ ├── key
│ │ ├── key.pub
```
### 6. Create the permissions configuration file
The [permissions configuration file](../../how-to/use-local-permissioning.md#permissions-configuration-file) defines the nodes and accounts allowlists.
Copy the following permissions configuration to a file called `permissions_config.toml` and save a copy in the `Node-1/data`, `Node-2/data`, `Node-3/data`, and `Node-4/data` directories:
```toml title="permissions_config.toml"
accounts-allowlist=["0xfe3b557e8fb62b89f4916b721be55ceb828dbd73", "0x627306090abaB3A6e1400e9345bC60c78a8BEf57"]
nodes-allowlist=[]
```
The permissions configuration file includes the first two accounts from the genesis file.
Use the [`perm_addNodesToAllowlist`](../../reference/api/perm.md#perm_addnodestoallowlist) JSON-RPC API method to add permissioned nodes after starting the nodes.
### 7. Start Node-1
Use the following command:
```bash
besu --data-path=data --genesis-file=../genesis.json --permissions-nodes-config-file-enabled --permissions-accounts-config-file-enabled --rpc-http-enabled --rpc-http-api=ADMIN,ETH,NET,PERM,IBFT --host-allowlist="*" --rpc-http-cors-origins="*" --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=..\genesis.json --permissions-nodes-config-file-enabled --permissions-accounts-config-file-enabled --rpc-http-enabled --rpc-http-api=ADMIN,ETH,NET,PERM,IBFT --host-allowlist="*" --rpc-http-cors-origins="*" --profile=ENTERPRISE
```
The command line enables:
- Nodes and accounts permissions using [`--permissions-nodes-config-file-enabled`](../../reference/options.md#permissions-nodes-config-file-enabled) and [`--permissions-accounts-config-file-enabled`](../../reference/options.md#permissions-accounts-config-file-enabled).
- The JSON-RPC API using [`--rpc-http-enabled`](../../../public-networks/reference/options.md#rpc-http-enabled).
- The `ADMIN`, `ETH`, `NET`, `PERM`, and `IBFT` APIs using [`--rpc-http-api`](../../../public-networks/reference/options.md#rpc-http-api).
- All-host access to the HTTP JSON-RPC API using [`--host-allowlist`](../../../public-networks/reference/options.md#host-allowlist).
- All-domain access to the node through the HTTP JSON-RPC API using [`--rpc-http-cors-origins`](../../../public-networks/reference/options.md#rpc-http-cors-origins).
- The [enterprise/private profile](../../../public-networks/how-to/configure-besu/profile.md#enterpriseprivate-profile)
using the [`--profile`](../../../public-networks/reference/options.md#profile) option.
When the node starts, the [enode URL](../../../public-networks/concepts/node-keys.md#enode-url) displays. You need the enode URL to specify Node-1 as a peer and update the permissions configuration file in the following steps.

### 8. Start Node-2
Start another terminal, change to the `Node-2` directory, and start Node-2:
```bash
besu --data-path=data --genesis-file=../genesis.json --permissions-nodes-config-file-enabled --permissions-accounts-config-file-enabled --rpc-http-enabled --rpc-http-api=ADMIN,ETH,NET,PERM,IBFT --host-allowlist="*" --rpc-http-cors-origins="*" --p2p-port=30304 --rpc-http-port=8546 --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=..\genesis.json --permissions-nodes-config-file-enabled --permissions-accounts-config-file-enabled --rpc-http-enabled --rpc-http-api=ADMIN,ETH,NET,PERM,IBFT --host-allowlist="*" --rpc-http-cors-origins="*" --p2p-port=30304 --rpc-http-port=8546 --profile=ENTERPRISE
```
The command line specifies:
- A different port to Node-1 for P2P discovery using [`--p2p-port`](../../../public-networks/reference/options.md#p2p-port).
- A different port to Node-1 for HTTP JSON-RPC using [`--rpc-http-port`](../../../public-networks/reference/options.md#rpc-http-port).
- A data directory for Node-2 using [`--data-path`](../../../public-networks/reference/options.md#data-path).
- Other options as for [Node-1](#7-start-node-1).
When the node starts, the [enode URL](../../../public-networks/concepts/node-keys.md#enode-url) displays. You need the enode URL to update the permissions configuration file in the following steps.
### 9. Start Node-3
Start another terminal, change to the `Node-3` directory, and start Node-3:
```bash
besu --data-path=data --genesis-file=../genesis.json --permissions-nodes-config-file-enabled --permissions-accounts-config-file-enabled --rpc-http-enabled --rpc-http-api=ADMIN,ETH,NET,PERM,IBFT --host-allowlist="*" --rpc-http-cors-origins="*" --p2p-port=30305 --rpc-http-port=8547 --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=..\genesis.json --permissions-nodes-config-file-enabled --permissions-accounts-config-file-enabled --rpc-http-enabled --rpc-http-api=ADMIN,ETH,NET,PERM,IBFT --host-allowlist="*" --rpc-http-cors-origins="*" --p2p-port=30305 --rpc-http-port=8547 --profile=ENTERPRISE
```
The command line specifies:
- A different port to Node-1 and Node-2 for P2P discovery using [`--p2p-port`](../../../public-networks/reference/options.md#p2p-port).
- A different port to Node-1 and Node-2 for HTTP JSON-RPC using [`--rpc-http-port`](../../../public-networks/reference/options.md#rpc-http-port).
- A data directory for Node-3 using [`--data-path`](../../../public-networks/reference/options.md#data-path).
- Other options as for [Node-1](#7-start-node-1).
When the node starts, the [enode URL](../../../public-networks/concepts/node-keys.md#enode-url) displays. You need the enode URL to update the permissions configuration file in the following steps.
### 10. Start Node-4
Start another terminal, change to the `Node-4` directory, and start Node-4:
```bash
besu --data-path=data --genesis-file=../genesis.json --permissions-nodes-config-file-enabled --permissions-accounts-config-file-enabled --rpc-http-enabled --rpc-http-api=ADMIN,ETH,NET,PERM,IBFT --host-allowlist="*" --rpc-http-cors-origins="*" --p2p-port=30306 --rpc-http-port=8548 --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=..\genesis.json --permissions-nodes-config-file-enabled --permissions-accounts-config-file-enabled --rpc-http-enabled --rpc-http-api=ADMIN,ETH,NET,PERM,IBFT --host-allowlist="*" --rpc-http-cors-origins="*" --p2p-port=30306 --rpc-http-port=8548 --profile=ENTERPRISE
```
The command line specifies:
- A different port to Node-1, Node-2, and Node-3 for P2P discovery using [`--p2p-port`](../../../public-networks/reference/options.md#p2p-port).
- A different port to Node-1, Node-2, and Node-3 for HTTP JSON-RPC using [`--rpc-http-port`](../../../public-networks/reference/options.md#rpc-http-port).
- A data directory for Node-4 using [`--data-path`](../../../public-networks/reference/options.md#data-path).
- Other options as for [Node-1](#7-start-node-1).
When the node starts, the [enode URL](../../../public-networks/concepts/node-keys.md#enode-url) displays. You need the enode URL to update the permissions configuration file in the following steps.
### 11. Add enode URLs for nodes to permissions configuration file
Start another terminal and use the [`perm_addNodesToAllowlist`](../../reference/api/perm.md#perm_addnodestoallowlist) JSON-RPC API method to add the nodes to the permissions configuration file for each node.
Replace ``, ``, ``, and `` with the enode URL displayed when starting each node.
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"perm_addNodesToAllowlist","params":[["","","",""]], "id":1}' http://127.0.0.1:8545/ -H "Content-Type: application/json"
```
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"perm_addNodesToAllowlist","params":[["","","",""]], "id":1}' http://127.0.0.1:8546
```
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"perm_addNodesToAllowlist","params":[["","","",""]], "id":1}' http://127.0.0.1:8547
```
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"perm_addNodesToAllowlist","params":[["","","",""]], "id":1}' http://127.0.0.1:8548
```
:::tip
The curl call is the same for each node except for the JSON-RPC endpoint.
:::
### 12. Add nodes as peers
Use the [`admin_addPeer`](../../../public-networks/reference/api/admin.md#admin_addpeer) JSON-RPC API method to add Node-1 as a peer for Node-2, Node-3, and Node-4.
Replace `` with the enode URL displayed when starting Node-1.
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":[""],"id":1}' http://127.0.0.1:8546
```
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":[""],"id":1}' http://127.0.0.1:8547
```
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":[""],"id":1}' http://127.0.0.1:8548
```
:::tip
The curl call is the same for each node except for the JSON-RPC endpoint.
:::
Replace `` with the enode URL displayed when starting Node-2.
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":[""],"id":1}' http://127.0.0.1:8547
```
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":[""],"id":1}' http://127.0.0.1:8548
```
Replace `` with the enode URL displayed when starting Node-3.
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"admin_addPeer","params":[""],"id":1}' http://127.0.0.1:8548
```
### 13. Confirm permissioned network is working
#### Check peer count
Use curl to call the JSON-RPC API [`net_peerCount`](../../../public-networks/reference/api/net.md#net_peercount) method and confirm the nodes are functioning as peers:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}' localhost:8545/ -H "Content-Type: application/json"
```
The result confirms Node-1 (the node running the JSON-RPC service) has three peers (Node-2, Node-3 and Node-4):
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x3"
}
```
#### Send a transaction from an account in the allowlist
Import the first account from the genesis file into MetaMask and send transactions, as described in the [Quickstart tutorial]:
:::info Account 1
- Address: `0xfe3b557e8fb62b89f4916b721be55ceb828dbd73`
- Private key : `0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63`
- Initial balance : `0xad78ebc5ac6200000` (200000000000000000000 in decimal)
:::
:::info
Besu doesn't support [private key management](../../../public-networks/how-to/send-transactions.md).
:::
#### Try sending a transaction from an account not in the accounts allowlist
Import the third account from the genesis file into MetaMask and try to send a transaction, as described in the [Quickstart tutorial]:
:::info Account 3
- Address: `0xf17f52151EbEF6C7334FAD080c5704D77216b732`
- Private key: `0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f`
- Initial balance: `0x90000000000000000000000` (2785365088392105618523029504 in decimal)
:::
#### Start a node not on the nodes allowlist
In your `Permissioned-Network` directory, create a `Node-5` directory and `data` directory inside it.
Change to the `Node-5` directory and start Node-5 specifying the Node-1 enode URL as the bootnode:
```bash
besu --data-path=data --bootnodes="" --genesis-file=../genesis.json --rpc-http-enabled --rpc-http-api=ADMIN,ETH,NET,PERM,IBFT --host-allowlist="*" --rpc-http-cors-origins="*" --p2p-port=30307 --rpc-http-port=8549
```
```bash
besu --data-path=data --bootnodes="" --genesis-file=..\genesis.json --rpc-http-enabled --rpc-http-api=ADMIN,ETH,NET,PERM,IBFT --host-allowlist="*" --rpc-http-cors-origins="*" --p2p-port=30307 --rpc-http-port=8549
```
Start another terminal and use curl to call the JSON-RPC API [`net_peerCount`](../../../public-networks/reference/api/net.md#net_peercount) method:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}' localhost:8549
```
The result confirms Node-5 has no peers even though it specifies Node-1 as a bootnode:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x0"
}
```
## Stop nodes
When finished using the permissioned network, stop all nodes using Ctrl+C in each terminal window.
:::tip
To restart the permissioned network in the future, start from [step 7](#7-start-node-1).
:::
[IBFT 2.0 proof of authority consensus protocol]: ../../how-to/configure/consensus/ibft.md
[Quickstart tutorial]: ../quickstart.md#6-send-a-transaction-with-metamask
---
## Create a QBFT network
# Create a private network using QBFT
A private network provides a configurable network for testing. This private network uses the [QBFT (proof of authority) consensus protocol](../how-to/configure/consensus/qbft.md).
The QBFT network in this tutorial implements the [block header validator selection method] to manage validators. For a tutorial on how to implement the [contract validator selection method], follow the steps in the [example smart contract repository].
:::important
The steps in this tutorial create an isolated, but not protected or secure, Ethereum private network. We recommend running the private network behind a properly configured firewall.
This tutorial configures a private network using QBFT for educational purposes only. QBFT requires 4 validators to be Byzantine fault tolerant.
:::
## Prerequisites
- [Besu](../get-started/install/binary-distribution.md)
- [Curl (or similar webservice client)](https://curl.haxx.se/download.html).
## Steps
Listed on the right-hand side of the page are the steps to create a private network using QBFT with four nodes. The four nodes are all validators.
### 1. Create directories
Each node requires a data directory for the blockchain data.
Create directories for your private network, each of the four nodes, and a data directory for each node:
```bash
QBFT-Network/
├── Node-1
│ ├── data
├── Node-2
│ ├── data
├── Node-3
│ ├── data
└── Node-4
├── data
```
### 2. Create a configuration file
The configuration file defines the [QBFT genesis file](../how-to/configure/consensus/qbft.md#genesis-file) and the number of node key pairs to generate.
The configuration file has two nested JSON nodes. The first is the `genesis` property defining the QBFT genesis file, except for the `extraData` string, which Besu generates automatically in the resulting genesis file. The second is the `blockchain` property defining the number of key pairs to generate.
Copy the following configuration file definition to a file called `qbftConfigFile.json` and save it in the `QBFT-Network` directory:
```json
{
"genesis": {
"config": {
"chainId": 1337,
"berlinBlock": 0,
"qbft": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
}
},
"nonce": "0x0",
"timestamp": "0x58ee40ba",
"gasLimit": "0x47b760",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "0xad78ebc5ac6200000"
},
"627306090abaB3A6e1400e9345bC60c78a8BEf57": {
"privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
},
"f17f52151EbEF6C7334FAD080c5704D77216b732": {
"privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
}
}
},
"blockchain": {
"nodes": {
"generate": true,
"count": 4
}
}
}
```
:::note
We recommend specifying the latest [milestone](../../public-networks/reference/genesis-items.md#milestone-blocks) when creating the genesis file for a private network. This ensures you are using the most up-to-date protocol and have access to the most recent opcodes.
:::
:::warning
Do not use the accounts in `alloc` in the genesis file on Mainnet or any public network except for testing. The private keys display, which means the accounts are not secure.
:::
### 3. Generate node keys and a genesis file
In the `QBFT-Network` directory, generate the node key and genesis file:
```bash
besu operator generate-blockchain-config --config-file=qbftConfigFile.json --to=networkFiles --private-key-file-name=key
```
Besu creates the following in the `networkFiles` directory:
- `genesis.json` - The genesis file including the `extraData` property specifying the four nodes are validators.
- A directory for each node named using the node address and containing the public and private key for each node.
```text
networkFiles/
├── genesis.json
└── keys
├── 0x438821c42b812fecdcea7fe8235806a412712fc0
│ ├── key
│ └── key.pub
├── 0xca9c2dfa62f4589827c0dd7dcf48259aa29f22f5
│ ├── key
│ └── key.pub
├── 0xcd5629bd37155608a0c9b28c4fd19310d53b3184
│ ├── key
│ └── key.pub
└── 0xe96825c5ab8d145b9eeca1aba7ea3695e034911a
├── key
└── key.pub
```
### 4. Copy the genesis file to the QBFT-Network directory
Copy the `genesis.json` file to the `QBFT-Network` directory.
### 5. Copy the node private keys to the node directories
For each node, copy the key files to the `data` directory for that node
```text
QBFT-Network/
├── genesis.json
├── Node-1
│ ├── data
│ │ ├── key
│ │ ├── key.pub
├── Node-2
│ ├── data
│ │ ├── key
│ │ ├── key.pub
├── Node-3
│ ├── data
│ │ ├── key
│ │ ├── key.pub
├── Node-4
│ ├── data
│ │ ├── key
│ │ ├── key.pub
```
### 6. Start the first node as the bootnode
In the `Node-1` directory, start Node-1:
```bash
besu --data-path=data --genesis-file=../genesis.json --rpc-http-enabled --rpc-http-api=ETH,NET,QBFT --host-allowlist="*" --rpc-http-cors-origins="all" --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=..\genesis.json --rpc-http-enabled --rpc-http-api=ETH,NET,QBFT --host-allowlist="*" --rpc-http-cors-origins="all" --profile=ENTERPRISE
```
The command line:
- Specifies the data directory for Node-1 using the [`--data-path`](../../public-networks/reference/options.md#data-path) option.
- Enables the JSON-RPC API using the [`--rpc-http-enabled`](../../public-networks/reference/options.md#rpc-http-enabled) option.
- Enables the ETH, NET, and QBFT APIs using the [`--rpc-http-api`](../../public-networks/reference/options.md#rpc-http-api) option.
- Enables all-host access to the HTTP JSON-RPC API using the [`--host-allowlist`](../../public-networks/reference/options.md#host-allowlist) option.
- Enables all-domain access to the node through the HTTP JSON-RPC API using the [`--rpc-http-cors-origins`](../../public-networks/reference/options.md#rpc-http-cors-origins) option.
- Loads the [enterprise/private profile](../../public-networks/how-to/configure-besu/profile.md#enterpriseprivate-profile)
using the [`--profile`](../../public-networks/reference/options.md#profile) option.
When the node starts, the [enode URL](../../public-networks/concepts/node-keys.md#enode-url) displays. Copy the enode URL to specify Node-1 as the bootnode in the following steps.

### 7. Start Node-2
Start another terminal, change to the `Node-2` directory and start Node-2 specifying the Node-1 enode URL copied when starting Node-1 as the bootnode:
```bash
besu --data-path=data --genesis-file=../genesis.json --bootnodes= --p2p-port=30304 --rpc-http-enabled --rpc-http-api=ETH,NET,QBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8546 --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=..\genesis.json --bootnodes= --p2p-port=30304 --rpc-http-enabled --rpc-http-api=ETH,NET,QBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8546 --profile=ENTERPRISE
```
The command line specifies:
- The data directory for Node-2 using the [`--data-path`](../../public-networks/reference/options.md#data-path) option.
- A different port to Node-1 for P2P discovery using the [`--p2p-port`](../../public-networks/reference/options.md#p2p-port) option.
- A different port to Node-1 for HTTP JSON-RPC using the [`--rpc-http-port`](../../public-networks/reference/options.md#rpc-http-port) option.
- The enode URL of Node-1 using the [`--bootnodes`](../../public-networks/reference/options.md#bootnodes) option.
- Other options as for [Node-1](#6-start-the-first-node-as-the-bootnode).
### 8. Start Node-3
Start another terminal, change to the `Node-3` directory and start Node-3 specifying the Node-1 enode URL copied when starting Node-1 as the bootnode:
```bash
besu --data-path=data --genesis-file=../genesis.json --bootnodes= --p2p-port=30305 --rpc-http-enabled --rpc-http-api=ETH,NET,QBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8547 --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=..\genesis.json --bootnodes= --p2p-port=30305 --rpc-http-enabled --rpc-http-api=ETH,NET,QBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8547 --profile=ENTERPRISE
```
The command line specifies:
- The data directory for Node-3 using the [`--data-path`](../../public-networks/reference/options.md#data-path) option.
- A different port to Node-1 and Node-2 for P2P discovery using the [`--p2p-port`](../../public-networks/reference/options.md#p2p-port) option.
- A different port to Node-1 and Node-2 for HTTP JSON-RPC using the [`--rpc-http-port`](../../public-networks/reference/options.md#rpc-http-port) option.
- The bootnode as for [Node-2](#7-start-node-2).
- Other options as for [Node-1](#6-start-the-first-node-as-the-bootnode).
### 9. Start Node-4
Start another terminal, change to the `Node-4` directory and start Node-4 specifying the Node-1 enode URL copied when starting Node-1 as the bootnode:
```bash
besu --data-path=data --genesis-file=../genesis.json --bootnodes= --p2p-port=30306 --rpc-http-enabled --rpc-http-api=ETH,NET,QBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8548 --profile=ENTERPRISE
```
```bash
besu --data-path=data --genesis-file=..\genesis.json --bootnodes= --p2p-port=30306 --rpc-http-enabled --rpc-http-api=ETH,NET,QBFT --host-allowlist="*" --rpc-http-cors-origins="all" --rpc-http-port=8548 --profile=ENTERPRISE
```
The command line specifies:
- The data directory for Node-4 using the [`--data-path`](../../public-networks/reference/options.md#data-path) option.
- A different port to Node-1, Node-2, and Node-3 for P2P discovery using the [`--p2p-port`](../../public-networks/reference/options.md#p2p-port) option.
- A different port to Node-1, Node-2, and Node-3 for HTTP JSON-RPC using the [`--rpc-http-port`](../../public-networks/reference/options.md#rpc-http-port) option.
- The bootnode as for [Node-2](#7-start-node-2).
- Other options as for [Node-1](#6-start-the-first-node-as-the-bootnode).
### 10. Confirm the private network is working
Start another terminal, use curl to call the JSON-RPC API [`qbft_getvalidatorsbyblocknumber`](../reference/api/qbft.md#qbft_getvalidatorsbyblocknumber) method and confirm the network has four validators:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"qbft_getValidatorsByBlockNumber","params":["latest"], "id":1}' localhost:8545/ -H "Content-Type: application/json"
```
The result displays the four validators:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0x73ced0bd3def2e2d9859e3bd0882683a2e6835fb",
"0x7a175f3542ceb60bf80fb536b3f42e7a30c0a6d7",
"0x7f6efa6e34f8c9b591a9ad4763e21b3fca31bcd6",
"0xc64140f1c9d5bb82e54976e568ad39958c3e94be"
]
}
```
Look at the logs to confirm Besu is producing blocks:
```bash
2021-05-26 08:47:00.221+10:00 | EthScheduler-Workers-0 | INFO | PersistBlockTask | Imported #1 / 0 tx / 0 om / 0 (0.0%) gas / (0x4ee4456536e2793523df87288fae76518089eec91c3f7e05e220f1f4d3f6f95b) in 0.016s. Peers: 4
2021-05-26 08:47:02.071+10:00 | pool-8-thread-1 | INFO | QbftBesuControllerBuilder | Imported #2 / 0 tx / 0 pending / 0 (0.0%) gas / (0x6fc47ada7146d75f6a46911d8d4038795b0c99970bbd4ce0c6d6aa60955f66fe)
2021-05-26 08:47:04.051+10:00 | pool-8-thread-1 | INFO | QbftBesuControllerBuilder | Imported #3 / 0 tx / 0 pending / 0 (0.0%) gas / (0x3cb663880a65103266b11a8d8631beca5c482d515ac287125aa077b2e31b80b0)
2021-05-26 08:47:06.058+10:00 | pool-8-thread-1 | INFO | QbftBesuControllerBuilder | Produced #4 / 0 tx / 0 pending / 0 (0.0%) gas / (0xc2927915ac0c94bab5fc9acea6608455f1c857d69e97191dc2c39e4ac411817b)
2021-05-26 08:47:08.058+10:00 | pool-8-thread-1 | INFO | QbftBesuControllerBuilder | Imported #5 / 0 tx / 0 pending / 0 (0.0%) gas / (0xba63471d62c936733add9b884f5213c3842af9f52460268e39e0666ab82f02a5)
```
:::important
If the key files were not copied to the correct directory in [step 5](#5-copy-the-node-private-keys-to-the-node-directories), the network will not start producing blocks.
The logs for each node should indicate the public key was loaded from the `data/key` directory:
```bash
2021-05-26 08:43:16.592+10:00 | main | INFO | KeyPairUtil | Loaded public key 0x931d32f1aec4e45b150ee38f3c74157a750fc53f523e63fe2b07bf3fce43a3de64587fc9aaf3736444f2e3eef0eea90be3b67d18be7b5b2b7cb2fcd670416a7e from /QBFT-Network/Node-1/data/key
```
If the keys were not copied to the correct directory, Besu creates a key when starting up:
```bash
2021-05-26 08:43:16.592+10:00 | main | INFO | KeyPairUtil | Generated new public key 0x1a4a2ade5ebc0a85572e2492e0cdf3e96b8928c75fa55b4425de8849850cf9b3a8cad1e27d98a3d3afac326a5e8788dbe6cc40249715c92825aebb28abe3e346 and stored it to /QBFT-Network/Node-1/data/key
```
If a new key was created, the validator key specified in the configuration does not match the created key and the node cannot participate in creating blocks.
:::
## Next steps
Use the [QBFT API](../reference/api/qbft.md) to remove or add validators, or import accounts to MetaMask and send transactions as described in the [Quickstart tutorial](quickstart.md#6-send-a-transaction-with-metamask).
:::note
To add or remove nodes as validators you need the node address. The directory [created for each node](#3-generate-node-keys-and-a-genesis-file) has the node address as the name.
Besu doesn't support [private key management](../../public-networks/how-to/send-transactions.md).
:::
You can switch from the [block header validator selection method] configured here, to the [contract validator selection method] by updating the genesis file and [configuring a transition].
## Stop the nodes
When finished using the private network, stop all nodes using ++ctrl+c++ in each terminal window.
:::tip
To restart the QBFT network in the future, start from [step 6](#6-start-the-first-node-as-the-bootnode).
:::
[block header validator selection method]: ../how-to/configure/consensus/qbft.md#add-and-remove-validators-using-block-headers
[contract validator selection method]: ../how-to/configure/consensus/qbft.md#add-and-remove-validators-using-a-smart-contract
[example smart contract repository]: https://github.com/ConsenSys/validator-smart-contracts
[configuring a transition]: ../how-to/configure/consensus/qbft.md#transitions
\*[Byzantine fault tolerant]: Ability to function correctly and reach consensus despite nodes failing or propagating incorrect information to peers.
---
## Developer Quickstart with privacy
The Besu Developer Quickstart generates a local private
[QBFT](../how-to/configure/consensus/qbft.md) network of Besu nodes with privacy from
[LFDT Paladin](../concepts/privacy-with-paladin.md), all managed by Docker Compose.
Paladin is an open-source privacy layer from the Linux Foundation Decentralized Trust (LFDT),
separate from Besu.
Use this tutorial to create a development network, test each Paladin privacy domain, send JSON-RPC
requests, view blocks and transactions, monitor nodes, and test a transaction from MetaMask.
:::caution
This tutorial runs a private network suitable for education or demonstration purposes and is not
intended for running production networks.
:::
The generated private network includes four validators, one non-validator RPC node, three member
nodes (each a Besu node paired with a Paladin node), and monitoring services.
You can optionally enable Chainlens Explorer and OpenTelemetry (OTel) when you generate the
network.
This quickstart deploys all three Paladin privacy domains (Pente, Noto, and Zeto) so you can test
each.
For an explanation of each domain and how the factory contracts work, see
[Privacy with Paladin](../concepts/privacy-with-paladin.md).
## Prerequisites
- [Docker and Docker Compose](https://docs.docker.com/compose/install/) v2 or later
- [Node.js](https://nodejs.org/en/download/) or [Yarn](https://yarnpkg.com/cli/node)
- [curl](https://curl.haxx.se/download.html)
- [MetaMask](https://metamask.io/)
:::info
Allow Docker to use up to 16 GB of memory for the private network.
On Windows, use Windows 11 with WSL2 kernel 6.6 or later.
You can use Docker Desktop or Docker Engine with the Compose plugin in the WSL2 environment.
:::
### Native Linux / WSL2 without Docker Desktop
If you are running Docker directly inside WSL2 (that is, the Docker daemon is installed in the
WSL2 distro itself, not via Docker Desktop), you only need to tune the WSL2 VM resource
allocation.
WSL2 is still a Hyper-V lightweight VM and defaults cap CPU well below your physical core count.
Create or edit `%USERPROFILE%\.wslconfig` on the Windows host
(for example, `C:\Users\\.wslconfig`):
```ini
[wsl2]
processors=8 # Physical cores to expose to the WSL2 VM (up to your machine's core count).
memory=16GB # RAM for the VM. Allow at least 8 GB for Zeto proof generation.
swap=0 # Optional. Disable swap to avoid latency spikes during proof generation.
```
Apply by restarting the VM from PowerShell:
```powershell
wsl --shutdown
```
Then reopen your WSL2 terminal.
The change takes effect immediately on the next WSL2 start.
If you are on **native Linux** (not WSL2 at all), no tuning is needed.
Docker runs directly on the host kernel and proof times are in the 30 to 60 second range.
### Docker Desktop and WSL2
If you are using Docker Desktop with the WSL2 backend, you have two resource caps to raise:
1. Set the WSL2 VM limits using the same `.wslconfig` as above.
2. Match Docker Desktop's own cap.
Docker Desktop has a separate CPU and memory limit that overrides the WSL2 allocation if it is
lower.
In Docker Desktop, go to **Settings** > **Resources**, set CPUs and Memory to match your
`.wslconfig` values, then select **Apply & Restart**.
Without step 2, Docker Desktop silently ignores the extra WSL2 resources and you get no benefit.
### ZK proof performance
Zeto ZK proof generation is the slowest part of this quickstart.
The proofs are computed by the Paladin container using WASM-compiled Groth16 circuits bundled at
`/app/domains/zeto/zkp/` inside the image.
WASM JIT is 10 to 50 times slower than native code, and proof times depend heavily on your runtime
environment.
| Setup | First proof (WASM cold start) | Subsequent proofs |
| ------------------------------------------ | ----------------------------- | -------------------------- |
| Docker Desktop and WSL2 (default limits) | 10+ minutes | 3 to 5 minutes |
| Docker Desktop and WSL2 (tuned limits) | 3 to 5 minutes | 1 to 2 minutes |
| Docker native in WSL2 (no Docker Desktop) | 2 to 4 minutes | 30 seconds to 1 minute |
| Native Linux (bare metal or VM) | 30 to 60 seconds | 10 to 30 seconds |
The warm-up only happens once per `docker compose up`.
After the first proof, the WASM circuit instance stays loaded in the Paladin process.
Subsequent proofs reuse it and are noticeably faster.
A `docker compose down` restarts the process and resets the timer.
## Steps
### 1. Generate the private network files
Run the Developer Quickstart.
The quickstart generates a folder (`./besu-test-network` by default) with the Docker Compose
files, scripts, and Besu configuration in it.
```bash
npx @consensys-software/besu-dev-quickstart
```
When prompted, select the following options:
| Prompt | Selection |
| ------------------------------------------- | --------------------- |
| Network type | **Private** |
| Add privacy (using paladin) to the network? | **Y** |
| Add OTel Collector spans to Grafana? | **N** |
| Enable Chainlens Explorer? | **Y** |
| Config files directory | `./besu-test-network` |
To skip the prompts, run:
```bash
npx @consensys-software/besu-dev-quickstart --networkType private --outputPath ./besu-test-network --privacy true --otel false --chainlens true
```
### 2. Start the network
Go to the generated directory and start the containers:
```bash
cd besu-test-network
./run.sh
```
The script builds the Docker images and starts the network.
The private network contains four QBFT validators named `validator1` through `validator4`, one
non-validator node named `rpcnode`, and three member nodes each paired with a Paladin node.
When startup finishes, the script lists the available endpoints:
```log title="Services list"
*************************************
Besu Dev Quickstart
*************************************
----------------------------------
List endpoints and services
----------------------------------
JSON-RPC HTTP service endpoint : http://localhost:8545
JSON-RPC WebSocket service endpoint : ws://localhost:8546
Prometheus address : http://localhost:9090/graph
Grafana metrics : http://localhost:3000/d/XE4V0WGZz/besu-overview?orgId=1&refresh=10s&from=now-30m&to=now&var-system=All
Grafana logs : http://localhost:3000/a/grafana-lokiexplore-app/explore
Chainlens Explorer (if selected) : http://localhost:8081/dashboard
For more information on the endpoints and services, refer to README.md in the installation directory.
****************************************************************
```
Use the endpoints as follows:
- Use the JSON-RPC HTTP endpoint to send requests to `rpcnode`.
- Use the JSON-RPC WebSocket endpoint for WebSocket subscriptions.
- Use Prometheus and Grafana to monitor node metrics.
- Use Grafana logs to view Besu logs in Loki.
- Use Chainlens Explorer to inspect blocks and transactions if you enabled it.
To display the list of endpoints again, run:
```bash
./list.sh
```
You now have a running private Besu network.
### 3. Run JSON-RPC requests
Send JSON-RPC requests to `http://localhost:8545`.
You can also use `ws://localhost:8546` for WebSocket connections.
This tutorial uses [curl](https://curl.haxx.se/download.html) to send JSON-RPC requests over HTTP.
#### Request the node version
Run the following command from the host shell.
The result displays the client version of the running node:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}' http://localhost:8545/ -H "Content-Type: application/json"
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "besu/v26.2.0/linux-aarch_64/openjdk-java-21"
}
```
The exact version, architecture, and Java runtime can differ depending on the Besu image used by
your generated network.
Successfully calling this method shows that you can connect to the network using JSON-RPC over
HTTP.
#### Count the peers
Peers are the other nodes connected to the node receiving the JSON-RPC request.
Poll the peer count using
[`net_peerCount`](../../public-networks/reference/api/index.md#net_peercount).
The result indicates that `rpcnode` has seven peers:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}' http://localhost:8545/ -H "Content-Type: application/json"
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x7"
}
```
#### Request the most recent block number
Call [`eth_blockNumber`](../../public-networks/reference/api/index.md#eth_blocknumber) to retrieve
the highest block number on `rpcnode`.
The result indicates the highest block number synchronized on this node:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http://localhost:8545/ -H "Content-Type: application/json"
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x2a"
}
```
The hexadecimal value `0x2a` translates to `42`, the number of blocks received by the node so far.
### 4. Verify the Paladin bootstrap
The `paladin-bootstrap` container starts automatically after the validators are healthy and deploys
the three factory contracts, one per privacy domain.
For an explanation of factory contracts, see
[Privacy with Paladin](../concepts/privacy-with-paladin.md#factory-contracts).
The bootstrap scripts are in the generated network at
`smart_contracts/scripts/paladin_bootstrap/`: `deploy_pente_factory.ts`,
`deploy_noto_factory.ts`, and `deploy_zeto_factory.ts`.
See `config/paladin/README.md` in the generated network for more details on how Paladin is
configured in this quickstart.
Check the bootstrap logs to confirm all three factory contracts deployed successfully:
```bash
docker compose logs paladin-bootstrap
```
The output should resemble the following.
In the logs, each `registryAddress` is the factory contract address for that privacy domain.
If any deployment step is missing, the Paladin nodes will fail to start correctly.
```log title="Paladin bootstrap logs"
> besu-paladin-smart-contracts@1.0.0 precompile
> node scripts/paladin_bootstrap/get_abis.mjs
Fetching Paladin ABIs (v1.0.0)...
✓ PenteFactory.json
✓ NotoFactory.json
✓ Noto.json
✓ ZetoFactory.json
Fetching Zeto contracts (v0.2.0)...
✓ Zeto_Anon.json
✓ Groth16Verifier_Deposit.json
✓ Groth16Verifier_Withdraw.json
✓ Groth16Verifier_WithdrawBatch.json
✓ Groth16Verifier_Anon.json
✓ Groth16Verifier_AnonBatch.json
> besu-paladin-smart-contracts@1.0.0 compile
> hardhat compile
Downloading compiler 0.8.27
Downloading compiler 0.8.27
Generating typings for: 11 artifacts in dir: typechain-types for target: ethers-v6
Successfully generated 38 typings!
Compiled 12 Solidity files successfully (evm target: paris).
Deploying PenteFactory from account: 0xC9C913c8c3C1Cd416d80A0abF475db2062F161f6
PenteFactory deployed at: 0xBca0fDc68d9b21b5bfB16D784389807017B2bbbc
Add this to each paladin*.yaml under domains.pente:
registryAddress: "0xBca0fDc68d9b21b5bfB16D784389807017B2bbbc"
Deploying NotoFactory from account: 0xC9C913c8c3C1Cd416d80A0abF475db2062F161f6
Current nonce: 1
1. Noto implementation: 0x9A8ea6736DF00Af70D1cD70b1Daf3619C8c0D7F4
2. NotoFactory logic: 0xeB35B7bA819DAD84E60752c357d45e5ce41D85c5
3. NotoFactory proxy: 0x9393486896D3ae612B4939afAF2C367Df17CC39B
Add to each paladin*.yaml under domains.noto:
registryAddress: "0x9393486896D3ae612B4939afAF2C367Df17CC39B"
Deploying ZetoFactory from account: 0xC9C913c8c3C1Cd416d80A0abF475db2062F161f6
Current nonce: 4
1. ZetoFactory logic: 0x1ADB4e782226cf66FF065FDF2D52B1ee7D831A64
2. ZetoFactory proxy: 0x49f8866d90ffDa8B12AC5677966e963acEc6d80E ← registryAddress
3. Groth16Verifier_Deposit : 0x6410E8e6321f46B7A34B9Ea9649a4c84563d8045
4. Groth16Verifier_Withdraw : 0x6468751F5D94540338058254D8F9BD1AcEa498Fe
5. Groth16Verifier_WithdrawBatch: 0x9b3241A4050670aC6598381501953911555dC53E
6. Groth16Verifier_Anon : 0x0C66Ce3b115507fFFF6eDC75116044675ABbc2c1
7. Groth16Verifier_AnonBatch : 0xBe5e64248757D402a596c0C5A7742ccAdA270aeC
8. Zeto_Anon implementation: 0x836114F71F13321808D9CAd370D1f5c5158f09cE
9. registerImplementation("Zeto_Anon") ✓
Add to each paladin*.yaml under domains.zeto:
registryAddress: "0x49f8866d90ffDa8B12AC5677966e963acEc6d80E"
```
### 5. Create a Pente privacy group
This example creates a privacy group containing `member1` and `member2`, deploys a
`SimpleStorage` contract privately into the group, sets a value, and reads it back from all three
members.
`member1` and `member2` return the value.
`member3` receives an error because it is not a member of the privacy group.
From the generated network directory, run:
```bash
cd smart_contracts
npm install
npm run pente-tx
```
The output resembles the following:
```log title="Pente example output"
> besu-paladin-smart-contracts@1.0.0 pente-tx
> ts-node scripts/privacy/pente_tx.ts
=== PRIVATE CONTRACT DEMO (Paladin / Pente) ===
member1 key: member@paladin1
member2 key: member@paladin2
member3 key: outsider@paladin3 (excluded from group)
1. Creating Pente privacy group for member1 + member2 ...
Privacy group address: 0x57a0aa749dc96523441563f5c4a50ec77fc89e70
2. Deploying SimpleStorage privately (initVal=47) ...
Private contract address: 0x82dd7e78ec835a1db64bb3c434f01f9af03ec7cf
3. Reading constructor-initialized value from member1 ...
member1 get() => 47 (expected: 47)
4. Setting value to 123 from member1 ...
set(123) mined
5. Verifying privacy: reading from member1, member2, member3 ...
member1 get() => 123 (expected: 123) ✓
member2 get() => 123 (expected: 123) ✓
Attempting member3 read (not in privacy group) ...
JSON-RPC error from pgroup_call (200 OK) PD012502: Privacy group '0xa0004eccd032092fc41176255b0d2f5a8eed08f636104fecf53e377e388d12c5' not found
member3 correctly denied — "PD012502: Privacy group '0xa0004eccd032092fc41176255b0d2f5a8eed08f636104fecf53e377e388d12c5' not found" ✓
=== DONE ===
```
### 6. Transfer notarized tokens with Noto
This example deploys a Noto token with `member1` as the notary in `notaryMode: basic`, where only
the notary can mint tokens and the notary must co-sign every token operation.
`member1` mints 2000 tokens, transfers 1000 to `member2`, and `member2` transfers 800 to
`member3`.
The script then reads the final balances of all three members.
To let other members mint tokens, see `notaryMode: hooks` in the
[Paladin documentation](https://lfdt-paladin.github.io/paladin/head/architecture/overview/).
From the `smart_contracts` directory, run:
```bash
npm install
npm run noto-tx
```
The output resembles the following:
```log title="Noto example output"
> besu-paladin-smart-contracts@1.0.0 noto-tx
> ts-node scripts/privacy/noto_tx.ts
=== NOTARIZED TOKEN DEMO (Paladin / Noto) ===
member1 (notary): member@paladin1
member2: member@paladin2
member3: member@paladin3
1. Deploying Noto token (member1 = notary, notaryMode = basic) ...
Token address: 0x3fdb4bb84d78fd695e83a4dbd5d558e1971ac904
2. Minting 2000 tokens to member1 ...
member1 balance: 2000 (expected: 2000) ✓
3. Transferring 1000 from member1 → member2 ...
member2 balance: 1000 (expected: 1000) ✓
4. Transferring 800 from member2 → member3 ...
5. Final balances:
member1: 1000 (expected: 1000) ✓
member2: 200 (expected: 200) ✓
member3: 800 (expected: 800) ✓
=== DONE ===
```
### 7. Transfer private tokens with Zeto
This example deploys a `Zeto_Anon` token and transfers it between members using zero-knowledge
succinct non-interactive arguments of knowledge (ZK-SNARK) proofs.
`member1` mints 1000 tokens, transfers 400 to `member2`, and `member2` transfers 300 to
`member3`.
Each operation waits for Paladin to generate a proof, and the first proof after startup can take
several minutes.
See [ZK proof performance](#zk-proof-performance) for expected times.
This quickstart uses the `Zeto_Anon` token variant for simplicity.
For other Zeto variants, see the
[Paladin Zeto documentation](https://lfdt-paladin.github.io/paladin/head/architecture/zeto/).
From the `smart_contracts` directory, run:
```bash
npm install
npm run zeto-tx
```
The output resembles the following:
```log title="Zeto example output"
> besu-paladin-smart-contracts@1.0.0 zeto-tx
> ts-node scripts/privacy/zeto_tx.ts
=== ZK TOKEN DEMO (Paladin / Zeto_Anon) ===
Zeto_Anon is an anonymous token where amounts and balances are hidden from
on-chain observers using ZK-SNARKs. Unlike Noto (which relies on a trusted
notary), Zeto uses cryptographic proofs — no third party sees your balance.
member1: member@paladin1
member2: member@paladin2
member3: member@paladin3
1. Deploying Zeto_Anon token ...
The ZetoFactory proxy creates a new token instance on-chain.
No ZK proof required for deployment.
Token address: 0x8e2fcc765a0a101451d199417f02a3501f911082
2. Minting 1000 tokens to member1 ...
[ZK proof] circuit: 'deposit', submitter: member@paladin1
Paladin is generating a Groth16 SNARK proof server-side inside libzeto.so.
No ZK tooling is needed on your machine — the circuits are bundled in the Docker image.
Expected time: 3-5 min first proof (WASM cold start in Docker/WSL2),
30s-2min for subsequent proofs (WASM instance stays loaded).
On production hardware with native binaries this typically takes < 30s.
Waiting for on-chain confirmation...
member1 balance: 1000 (expected: 1000) ✓
3. Transferring 400 from member1 → member2 ...
[ZK proof] circuit: 'anon', submitter: member@paladin1 → member@paladin2
Paladin is generating a Groth16 SNARK proof server-side inside libzeto.so.
No ZK tooling is needed on your machine — the circuits are bundled in the Docker image.
Expected time: 3-5 min first proof (WASM cold start in Docker/WSL2),
30s-2min for subsequent proofs (WASM instance stays loaded).
On production hardware with native binaries this typically takes < 30s.
Waiting for on-chain confirmation...
member2 balance: 400 (expected: 400) ✓
4. Transferring 300 from member2 → member3 ...
WASM circuit is already loaded — this proof should be faster than the first.
[ZK proof] circuit: 'anon', submitter: member@paladin2 → member@paladin3
Paladin is generating a Groth16 SNARK proof server-side inside libzeto.so.
No ZK tooling is needed on your machine — the circuits are bundled in the Docker image.
Expected time: 3-5 min first proof (WASM cold start in Docker/WSL2),
30s-2min for subsequent proofs (WASM instance stays loaded).
On production hardware with native binaries this typically takes < 30s.
Waiting for on-chain confirmation...
5. Final balances:
Each node queries its own private state — only states you own are visible to you.
member1: 600 (expected: 600) ✓
member2: 100 (expected: 100) ✓
member3: 300 (expected: 300) ✓
=== DONE ===
```
### 8. View the network in Chainlens
If you enabled Chainlens when generating the network, open `http://localhost:8081/dashboard` in
your browser.
Chainlens connects to `rpcnode` and displays network activity, blocks, and transactions.
If the dashboard is empty at first, wait for the ingestion service to index the latest blocks,
then refresh the page.
To add Chainlens after generating the network, generate a new quickstart directory with
`--chainlens true`.
The Developer Quickstart adds the Chainlens services to the generated Docker Compose file at
generation time.
### 9. Monitor nodes with Prometheus, Grafana, and Loki
The Developer Quickstart starts Prometheus, Grafana, Loki, and Grafana Alloy with the private
network.
Use these services to inspect node metrics and logs.
- Open `http://localhost:9090/graph` to query metrics in Prometheus.
- Open the Grafana metrics URL listed by `./list.sh` to view the Besu overview dashboard.
- Open the Grafana logs URL listed by `./list.sh` to view logs from Loki.
If you generated the network with `--otel true`, the Developer Quickstart also includes an OTel
Collector and Tempo.
Use Grafana to inspect the additional tracing data.
Learn more about how to [monitor metrics](../../public-networks/how-to/monitor/metrics.md).
### 10. Send a transaction with MetaMask
Connect MetaMask to the local JSON-RPC endpoint and send a transaction between the prefunded test
accounts.
#### Import test accounts
Import two of the following test accounts into MetaMask.
These accounts are already funded in the generated genesis file.
:::danger **Do not use the test accounts on Ethereum Mainnet or any production network.**
The following accounts are test accounts and their private keys are publicly visible in this documentation and in publicly available source code.
They are not secure and everyone can use them.
**Using test accounts on Ethereum Mainnet and production networks can lead to loss of funds and identity fraud.**
In this documentation, we only provide test accounts for ease of testing and learning purposes; never use them for other purposes.
**Always secure your Ethereum Mainnet and any production account properly.**
See for instance [MyCrypto "Protecting Yourself and Your Funds" guide](https://support.mycrypto.com/staying-safe/protecting-yourself-and-your-funds).
:::
:::info "Test Account 1 (address `0xfe3b557e8fb62b89f4916b721be55ceb828dbd73`)"
Private key to copy :
```text
0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63
```
Initial balance : 200 Eth _(200000000000000000000 Wei)_
:::
:::info "Test Account 2 (address `0x627306090abaB3A6e1400e9345bC60c78a8BEf57`)"
Private key to copy :
```text
0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3
```
Initial balance : 90000 Eth _(90000000000000000000000 Wei)_
:::
:::info "Test Account 3 (address `0xf17f52151EbEF6C7334FAD080c5704D77216b732`)"
Private key to copy :
```text
0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f
```
Initial balance : 90000 Eth _(90000000000000000000000 Wei)_
:::
#### Add the network
In MetaMask, add a custom network with the following values:
| Field | Value |
| --------------- | ----------------------- |
| Network name | `Besu Dev Quickstart` |
| RPC URL | `http://localhost:8545` |
| Chain ID | `1337` |
| Currency symbol | `ETH` |
#### Send the transaction
From one imported test account, send a small amount of ETH to another imported test account.
The private network has zero gas price configured, so the transaction doesn't require a gas fee.
After MetaMask confirms the transaction, copy the transaction hash.
If Chainlens is enabled, search for the transaction hash in `http://localhost:8081/dashboard`.
### 11. Add a non-validator node
Add a non-validator Besu node to the private network by generating node keys, adding a Docker
Compose service, and allowing the node in the network configuration.
To add a validator instead, use the
[QBFT validator voting process](../how-to/configure/consensus/qbft.md#add-and-remove-validators)
after the node is running.
#### Generate node keys
From the `besu-test-network` directory, generate the node details:
```bash
cd extra
npm install
node generate_node_details.js --password "Password"
```
The script writes the following files:
- `nodekey`
- `nodekey.pub`
- `address`
- `accountKeystore`
- `accountPrivateKey`
- `accountPassword`
Create a directory for the new node and copy the files:
```bash
cd ..
mkdir -p config/nodes/node5
cp extra/nodekey extra/nodekey.pub extra/accountKeystore extra/accountPassword config/nodes/node5/
```
#### Add the Docker Compose service
In `docker-compose.yml`, add a service for `node5`.
Use an unused IP address in the `besu-dev-quickstart` subnet:
```yaml
node5:
<< : *besu-def
container_name: node5
environment:
- OTEL_RESOURCE_ATTRIBUTES=service.name=node5,service.version=${BESU_VERSION:-latest}
volumes:
- ./config/besu/:/config
- ./config/nodes/node5:/opt/besu/keys
- ./logs/besu:/tmp/besu
depends_on:
- validator1
ports:
- 21005:8545/tcp
- 30303
- 9545
networks:
besu-dev-quickstart:
ipv4_address: 172.16.239.16
```
#### Allow and discover the node
Create the enode URL for the new node using the contents of `config/nodes/node5/nodekey.pub`:
```text
enode://@172.16.239.16:30303
```
Add the enode URL to `config/besu/permissions_config.toml`.
Also add it to `config/besu/static-nodes.json` so existing nodes discover it when they restart.
#### Add the node to Prometheus
In `config/prometheus/prometheus.yml`, add a scrape job for `node5`:
```yaml
- job_name: "node5"
metrics_path: /metrics
scheme: http
static_configs:
- targets: [node5:9545]
```
#### Restart the network
Restart the network for the updated Docker Compose and Besu configuration files to take effect:
```bash
./stop.sh
./resume.sh
```
After the containers start, confirm that `node5` appears in Docker and that the peer count has
increased:
```bash
docker compose ps node5
curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}' http://localhost:8545/ -H "Content-Type: application/json"
```
### 12. Stop and restart the network
Stop the containers without deleting the chain data:
```bash
./stop.sh
```
Restart the containers with the existing data:
```bash
./resume.sh
```
### 13. Remove the network
Stop the containers and remove the generated container volumes:
```bash
./remove.sh
```
The command doesn't delete the generated files in `besu-test-network`.
## Next steps
- [Privacy with Paladin](../concepts/privacy-with-paladin.md).
- [Configure QBFT consensus](../how-to/configure/consensus/qbft.md).
- [Configure local permissioning](../how-to/use-local-permissioning.md).
- [Deploy and interact with smart contracts](./contracts/interact.md).
- [Monitor Besu metrics](/public-networks/how-to/monitor/metrics).
---
## Developer Quickstart
The Besu Developer Quickstart generates a local private [QBFT](../how-to/configure/consensus/qbft.md) network of Besu nodes managed by Docker Compose.
Use this tutorial to create a development network, send JSON-RPC requests, view blocks and transactions, monitor nodes, and test a transaction from MetaMask.
:::caution
This tutorial runs a private network suitable for education or demonstration purposes and is not intended for running production
networks.
:::
The generated private network includes four validators, one non-validator RPC node, and monitoring services.
You can optionally enable Chainlens Explorer and OpenTelemetry (OTel) when you generate the network.
## Prerequisites
- [Docker and Docker Compose](https://docs.docker.com/compose/install/) v2 or later
- [Node.js](https://nodejs.org/en/download/) or [Yarn](https://yarnpkg.com/cli/node)
- [curl](https://curl.haxx.se/download.html)
- [MetaMask](https://metamask.io/)
:::info
Allow Docker to use up to 6 GB of memory for the private network.
On Windows, use Windows 11 with WSL2 kernel 6.6 or later.
You can use Docker Desktop or Docker Engine with the Compose plugin in the WSL2 environment.
:::
## Steps
### 1. Generate the private network files
Run the Developer Quickstart.
The quickstart generates a folder (`./besu-test-network` by default) with the Docker Compose files, scripts, and Besu configuration in it.
```bash
npx @consensys-software/besu-dev-quickstart
```
When prompted, select the following options:
| Prompt | Selection |
| ------------------------------------ | --------------------- |
| Network type | **Private** |
| Add privacy (using paladin) to the network? | **N** |
| Add OTel Collector spans to Grafana? | **N** |
| Enable Chainlens Explorer? | **Y** |
| Config files directory | `./besu-test-network` |
To skip the prompts, run:
```bash
npx @consensys-software/besu-dev-quickstart --networkType private --outputPath ./besu-test-network --otel false --chainlens true
```
### 2. Start the network
Go to the generated directory and start the containers:
```bash
cd besu-test-network
./run.sh
```
The script builds the Docker images and starts the network.
The private network contains four QBFT validators named `validator1` through `validator4`, and one non-validator node named `rpcnode`.
When startup finishes, the script lists the available endpoints:
```log title="Services list"
*************************************
Besu Dev Quickstart
*************************************
----------------------------------
List endpoints and services
----------------------------------
JSON-RPC HTTP service endpoint : http://localhost:8545
JSON-RPC WebSocket service endpoint : ws://localhost:8546
Prometheus address : http://localhost:9090/graph
Grafana metrics : http://localhost:3000/d/XE4V0WGZz/besu-overview?orgId=1&refresh=10s&from=now-30m&to=now&var-system=All
Grafana logs : http://localhost:3000/a/grafana-lokiexplore-app/explore
Chainlens Explorer (if selected) : http://localhost:8081/dashboard
For more information on the endpoints and services, refer to README.md in the installation directory.
****************************************************************
```
Use the endpoints as follows:
- Use the JSON-RPC HTTP endpoint to send requests to `rpcnode`.
- Use the JSON-RPC WebSocket endpoint for WebSocket subscriptions.
- Use Prometheus and Grafana to monitor node metrics.
- Use Grafana logs to view Besu logs in Loki.
- Use Chainlens Explorer to inspect blocks and transactions if you enabled it.
To display the list of endpoints again, run:
```bash
./list.sh
```
You now have a running private Besu network.
### 3. Run JSON-RPC requests
Send JSON-RPC requests to `http://localhost:8545`.
You can also use `ws://localhost:8546` for WebSocket connections.
This tutorial uses [curl](https://curl.haxx.se/download.html) to send JSON-RPC requests over HTTP.
#### Request the node version
Run the following command from the host shell:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}' http://localhost:8545/ -H "Content-Type: application/json"
```
The result displays the client version of the running node:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "besu/v26.2.0/linux-aarch_64/openjdk-java-21"
}
```
The exact version, architecture, and Java runtime can differ depending on the Besu image used by your generated network.
Successfully calling this method shows that you can connect to the network using JSON-RPC over HTTP.
#### Count the peers
Peers are the other nodes connected to the node receiving the JSON-RPC request.
Poll the peer count using [`net_peerCount`](../../public-networks/reference/api/net.md#net_peercount):
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}' http://localhost:8545/ -H "Content-Type: application/json"
```
The result indicates that `rpcnode` has four peers:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x4"
}
```
#### Request the most recent block number
Call [`eth_blockNumber`](../../public-networks/reference/api/eth/client.md#eth_blocknumber) to retrieve the highest block number on `rpcnode`:
```bash
curl -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http://localhost:8545/ -H "Content-Type: application/json"
```
The result indicates the highest block number synchronized on this node:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x2a"
}
```
The hexadecimal value `0x2a` translates to `42`, the number of blocks received by the node so far.
### 4. View the network in Chainlens
If you enabled Chainlens when generating the network, open `http://localhost:8081/dashboard` in your browser.
Chainlens connects to `rpcnode` and displays network activity, blocks, and transactions.
If the dashboard is empty at first, wait for the ingestion service to index the latest blocks, then refresh the page.
To add Chainlens after generating the network, generate a new quickstart directory with `--chainlens true`.
The Developer Quickstart adds the Chainlens services to the generated Docker Compose file at generation time.
### 5. Monitor nodes with Prometheus, Grafana, and Loki
The Developer Quickstart starts Prometheus, Grafana, Loki, and Grafana Alloy with the private network.
Use these services to inspect node metrics and logs.
- Open `http://localhost:9090/graph` to query metrics in Prometheus.
- Open the Grafana metrics URL listed by `./list.sh` to view the Besu overview dashboard.
- Open the Grafana logs URL listed by `./list.sh` to view logs from Loki.
If you generated the network with `--otel true`, the Developer Quickstart also includes an OTel Collector and Tempo.
Use Grafana to inspect the additional tracing data.
Learn more about how to [monitor metrics](../../public-networks/how-to/monitor/metrics.md).
### 6. Send a transaction with MetaMask
Connect MetaMask to the local JSON-RPC endpoint and send a transaction between the prefunded test accounts.
#### Import test accounts
Import two of the following test accounts into MetaMask.
These accounts are already funded in the generated genesis file.
:::danger **Do not use the test accounts on Ethereum Mainnet or any production network.**
The following accounts are test accounts and their private keys are publicly visible in this documentation and in publicly available source code.
They are not secure and everyone can use them.
**Using test accounts on Ethereum Mainnet and production networks can lead to loss of funds and identity fraud.**
In this documentation, we only provide test accounts for ease of testing and learning purposes; never use them for other purposes.
**Always secure your Ethereum Mainnet and any production account properly.**
See for instance [MyCrypto "Protecting Yourself and Your Funds" guide](https://support.mycrypto.com/staying-safe/protecting-yourself-and-your-funds).
:::
:::info "Test Account 1 (address `0xfe3b557e8fb62b89f4916b721be55ceb828dbd73`)"
Private key to copy :
```text
0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63
```
Initial balance : 200 Eth _(200000000000000000000 Wei)_
:::
:::info "Test Account 2 (address `0x627306090abaB3A6e1400e9345bC60c78a8BEf57`)"
Private key to copy :
```text
0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3
```
Initial balance : 90000 Eth _(90000000000000000000000 Wei)_
:::
:::info "Test Account 3 (address `0xf17f52151EbEF6C7334FAD080c5704D77216b732`)"
Private key to copy :
```text
0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f
```
Initial balance : 90000 Eth _(90000000000000000000000 Wei)_
:::
#### Add the network
In MetaMask, add a custom network with the following values:
| Field | Value |
| --------------- | ----------------------- |
| Network name | `Besu Dev Quickstart` |
| RPC URL | `http://localhost:8545` |
| Chain ID | `1337` |
| Currency symbol | `ETH` |
#### Send the transaction
From one imported test account, send a small amount of ETH to another imported test account.
The private network has zero gas price configured, so the transaction doesn't require a gas fee.
After MetaMask confirms the transaction, copy the transaction hash.
If Chainlens is enabled, search for the transaction hash in `http://localhost:8081/dashboard`.
### 7. Stop and restart the network
Stop the containers without deleting the chain data:
```bash
./stop.sh
```
Restart the containers with the existing data:
```bash
./resume.sh
```
### 8. Remove the network
Stop the containers and remove the generated container volumes:
```bash
./remove.sh
```
The command doesn't delete the generated files in `besu-test-network`.
### 9. Add a non-validator node
You can add a non-validator Besu node to the private network by generating node keys, adding a Docker Compose service, and allowing the node in the network configuration.
To add a validator instead, use the [QBFT validator voting process](../how-to/configure/consensus/qbft.md#add-and-remove-validators) after the node is running.
#### Generate node keys
From the `besu-test-network` directory, generate the node details:
```bash
cd extra
npm install
node generate_node_details.js --password "Password"
```
The script writes the following files:
- `nodekey`
- `nodekey.pub`
- `address`
- `accountKeystore`
- `accountPrivateKey`
- `accountPassword`
Create a directory for the new node and copy the files:
```bash
cd ..
mkdir -p config/nodes/node5
cp extra/nodekey extra/nodekey.pub extra/accountKeystore extra/accountPassword config/nodes/node5/
```
#### Add the Docker Compose service
In `docker-compose.yml`, add a service for `node5`.
Use an unused IP address in the `besu-dev-quickstart` subnet:
```yaml
node5:
<< : *besu-def
container_name: node5
environment:
- OTEL_RESOURCE_ATTRIBUTES=service.name=node5,service.version=${BESU_VERSION:-latest}
volumes:
- ./config/besu/:/config
- ./config/nodes/node5:/opt/besu/keys
- ./logs/besu:/tmp/besu
depends_on:
- validator1
ports:
- 21005:8545/tcp
- 30303
- 9545
networks:
besu-dev-quickstart:
ipv4_address: 172.16.239.16
```
#### Allow and discover the node
Create the enode URL for the new node using the contents of `config/nodes/node5/nodekey.pub`:
```text
enode://@172.16.239.16:30303
```
Add the enode URL to `config/besu/permissions_config.toml`.
Also add it to `config/besu/static-nodes.json` so existing nodes discover it when they restart.
#### Add the node to Prometheus
In `config/prometheus/prometheus.yml`, add a scrape job for `node5`:
```yaml
- job_name: "node5"
metrics_path: /metrics
scheme: http
static_configs:
- targets: [node5:9545]
```
#### Restart the network
Restart the network for the updated Docker Compose and Besu configuration files to take effect:
```bash
./stop.sh
./resume.sh
```
After the containers start, confirm that `node5` appears in Docker and that the peer count has increased:
```bash
docker compose ps node5
curl -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}' http://localhost:8545/ -H "Content-Type: application/json"
```
## Next steps
- [Privacy with Paladin](./quickstart-with-privacy.md).
- [Configure QBFT consensus](../how-to/configure/consensus/qbft.md).
- [Configure local permissioning](../how-to/use-local-permissioning.md).
- [Deploy and interact with smart contracts](./contracts/interact.md).
- [Monitor Besu metrics](/public-networks/how-to/monitor/metrics).
---
## Test_accounts
:::danger **Do not use the test accounts on Ethereum Mainnet or any production network.**
The following accounts are test accounts and their private keys are publicly visible in this documentation and in publicly available source code.
They are not secure and everyone can use them.
**Using test accounts on Ethereum Mainnet and production networks can lead to loss of funds and identity fraud.**
In this documentation, we only provide test accounts for ease of testing and learning purposes; never use them for other purposes.
**Always secure your Ethereum Mainnet and any production account properly.**
See for instance [MyCrypto "Protecting Yourself and Your Funds" guide](https://support.mycrypto.com/staying-safe/protecting-yourself-and-your-funds).
:::
:::info "Test Account 1 (address `0xfe3b557e8fb62b89f4916b721be55ceb828dbd73`)"
Private key to copy :
```text
0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63
```
Initial balance : 200 Eth _(200000000000000000000 Wei)_
:::
:::info "Test Account 2 (address `0x627306090abaB3A6e1400e9345bC60c78a8BEf57`)"
Private key to copy :
```text
0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3
```
Initial balance : 90000 Eth _(90000000000000000000000 Wei)_
:::
:::info "Test Account 3 (address `0xf17f52151EbEF6C7334FAD080c5704D77216b732`)"
Private key to copy :
```text
0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f
```
Initial balance : 90000 Eth _(90000000000000000000000 Wei)_
:::
---
## Plugin lifecycle
A Besu plugin is a Java class that implements the [`BesuPlugin`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/BesuPlugin.html) interface.
Besu discovers plugin JARs using Java's `ServiceLoader`, then calls the plugin lifecycle methods during
startup, runtime, reload, and shutdown.
## Lifecycle methods
| Method | Purpose |
| --- | --- |
| `getName` | Returns the plugin name. Besu uses this name for plugin-specific actions. The default is the plugin class name. |
| `register(ServiceManager)` | Called early in the Besu lifecycle. Store the [`ServiceManager`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/ServiceManager.html) and perform early registration such as CLI options and RPC endpoints. |
| `beforeExternalServices` | Optional hook called after Besu loads configuration and before external services (like metrics and HTTP) start. |
| `start` | Called after Besu loads configuration and starts external services, but before the main loop is up. Start runtime work here. |
| `afterExternalServicePostMainLoop` | Optional hook called after external services and main-loop setup. |
| `reloadConfiguration` | Optional hook called by the `plugins_reloadPluginConfig` RPC method. Implement it only for configuration that can be reloaded safely. |
| `stop` | Called when Besu shuts down or disables the plugin. Remove listeners and stop background work here. |
| `getVersion` | Returns plugin version information from package implementation metadata. |
## Lifecycle diagram
The following sequence diagram shows where plugin discovery and lifecycle callbacks fit into Besu startup,
normal execution, and shutdown.
```mermaid
sequenceDiagram
participant Besu
Besu->>Besu: Basic startup
create participant Loader as Java ServiceLoader
Besu->>Loader: Discover plugin providers
create participant Plugin as Besu plugin
Loader->>Plugin: Create plugin instances
destroy Loader
Loader->>Besu: Return BesuPluginimplementations
loop For each plugin
Besu->>Plugin: register(ServiceManager)
Plugin->>Besu: Register CLI options and RPC endpoints
end
Besu->>Besu: Full startup
loop For each plugin
Besu->>Plugin: start
Plugin->>Besu: Register listeners, metrics, and runtime work
end
Besu->>Besu: Normal execution
loop For each plugin
Besu->>Plugin: stop
Plugin->>Besu: Remove listeners and clean up resources
end
```
## Service availability
Besu services are available at different parts of the plugin lifecycle.
Some are available and used in `register` before startup completes, and others interact with live data and are used in `start`.
[`PicoCLIOptions`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/PicoCLIOptions.html) and [`RpcEndpointService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/RpcEndpointService.html) must be used in `register`.
The following services are typically used in `register`:
- [`BesuConfiguration`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BesuConfiguration.html)
- [`MetricCategoryRegistry`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/metrics/MetricCategoryRegistry.html)
- [`PermissioningService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/PermissioningService.html)
- [`SecurityModuleService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/SecurityModuleService.html)
- [`TransactionPoolValidatorService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/TransactionPoolValidatorService.html)
- [`TransactionSelectionService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/TransactionSelectionService.html)
- [`TransactionValidatorService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/TransactionValidatorService.html)
[`BlockchainService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BlockchainService.html) and [`TransactionSimulationService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/TransactionSimulationService.html) are available at `register`, but typically used in `start`.
The remaining services only become available at `start`:
- [`BesuEvents`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BesuEvents.html)
- [`BftQueryService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/query/BftQueryService.html)
- [`BlockSimulationService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BlockSimulationService.html)
- [`MetricsSystem`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/MetricsSystem.html)
- [`MiningService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/mining/MiningService.html)
- [`P2PService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/p2p/P2PService.html)
- [`PoaQueryService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/query/PoaQueryService.html)
- [`RlpConverterService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/rlp/RlpConverterService.html)
- [`SynchronizationService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/sync/SynchronizationService.html)
- [`TraceService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/TraceService.html)
- [`TransactionPoolService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/transactionpool/TransactionPoolService.html)
- [`WorldStateService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/WorldStateService.html)
---
## Quickstart
Follow this quickstart to learn the essential workflow to create and deploy a Besu plugin.
## Prerequisites
- Java 25+.
You can install Java using `brew install openjdk@25` or manually install the
[Java JDK](https://www.oracle.com/java/technologies/downloads).
- [Gradle](https://gradle.org/install/).
- A [Besu installation](../../public-networks/get-started/install/index.md).
## Steps
### 1. Set up your project
A Besu plugin is a standalone Java project; create a new directory for it.
Besu provides a [Gradle plugin](https://github.com/Consensys/besu-plugin-gradle-plugin) to simplify
the plugin developer experience.
It automatically adds and manages dependencies, and packages the plugin artifacts when you
distribute the project.
In your plugin project, apply the latest version of the [Gradle plugin](https://github.com/Consensys/besu-plugin-gradle-plugin)
(`net.consensys.besu-plugin-distribution`) and set the Besu version you want to compile your plugin against:
```groovy title="build.gradle"
plugins {
id 'net.consensys.besu-plugin-distribution' version '0.2.1'
}
besuPlugin {
besuVersion = '26.6.0'
}
```
Generate the [Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html) so the
project builds with a consistent Gradle version:
```bash
gradle wrapper
```
### 2. Implement the plugin class
Create a class that implements [`BesuPlugin`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/BesuPlugin.html).
The three required methods are `register`, `start`, and `stop`.
Besu calls `register(ServiceManager)` early in startup.
[`ServiceManager`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/ServiceManager.html) is the interface through which your plugin accesses all Besu services.
Store `ServiceManager` in a field if your plugin needs to retrieve services later.
The `getName` method is optional; it defaults to the fully qualified class name, but overriding it with
a short string gives your plugin a readable identifier.
```java title="ExamplePlugin.java"
package example;
public class ExamplePlugin implements BesuPlugin {
private ServiceManager serviceManager;
@Override
public String getName() {
return "example";
}
@Override
public void register(final ServiceManager serviceManager) {
this.serviceManager = serviceManager;
}
@Override
public void start() {}
@Override
public void stop() {}
}
```
### 3. Register the plugin for discovery
Besu discovers plugin classes using Java's `ServiceLoader`.
Register your plugin by including a service provider entry for `BesuPlugin`.
You can generate the entry using Google's `@AutoService` annotation processor:
```java title="ExamplePlugin.java"
package example;
// highlight-next-line
// highlight-next-line
@AutoService(BesuPlugin.class)
public class ExamplePlugin implements BesuPlugin { ... }
```
### 4. Register CLI options
Use the `register` method to add plugin CLI options to the Besu command line.
Retrieve the [`PicoCLIOptions`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/PicoCLIOptions.html) service and call `addPicoCLIOptions`, passing a short namespace string and
the object whose fields carry [PicoCLI](https://picocli.info/) `@Option` annotations.
```java title="ExamplePlugin.java"
// highlight-start
// highlight-end
public class ExamplePlugin implements BesuPlugin {
private ServiceManager serviceManager;
// highlight-start
@Option(names = "--plugin-example-enabled", description = "Enable the example plugin feature.")
private boolean enabled = false;
// highlight-end
@Override
public void register(final ServiceManager serviceManager) {
this.serviceManager = serviceManager;
// highlight-start
serviceManager
.getService(PicoCLIOptions.class)
.ifPresent(cli -> cli.addPicoCLIOptions("example", this));
// highlight-end
}
...
}
```
:::warning Important
Plugin CLI option names must use the prefix `--plugin--`, where `` is the value you pass to `addPicoCLIOptions`.
For example, passing `"example"` means every `@Option` name must start with `--plugin-example-`.
:::
### 5. Retrieve services and start
Use `start` to retrieve Besu services and begin runtime work.
Services that expose runtime data (such as events, metrics, and world state) only become available at `start`.
Learn more about [when services are available](plugin-lifecycle.md#service-availability).
The following example retrieves [`BesuEvents`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BesuEvents.html):
```java title="ExamplePlugin.java"
@Override
public void start() {
serviceManager
.getService(BesuEvents.class)
.ifPresent(events -> {
// Subscribe to block, transaction, or sync events.
});
}
```
### 6. Clean up in stop
Use `stop` to remove event subscriptions and release any resources your plugin holds.
Besu calls `stop` during shutdown and when disabling individual plugins.
```java title="ExamplePlugin.java"
@Override
public void stop() {
// Remove event subscriptions and release resources.
}
```
### 7. Build and deploy the plugin
The Gradle plugin provides a `distZip` task that packages your plugin into a ZIP file containing only
the plugin JAR and any extra dependencies not already provided by Besu.
Build the distribution:
```bash
./gradlew distZip
```
Create a `plugins` directory at the root of your Besu installation if it doesn't already exist.
Then unzip the archive into it.
The `-j` flag flattens the ZIP so all JARs land directly in `plugins/`:
```bash
unzip -j build/distributions/example.zip -d /path/to/besu/plugins/
```
:::tip
If you installed Besu using Homebrew or docker, see [Deploy a plugin](../how-to/deploy-a-plugin.md).
:::
Start Besu.
It loads all JARs found in the `plugins` directory automatically.
To load only specific plugins, use
[`--plugins`](../../public-networks/reference/options.md#plugins).
## Next steps
- Learn about the [plugin lifecycle](plugin-lifecycle.md).
- Integrate different [services](/plugins/services) into your plugin.
- See example [open source plugins](../reference/resources.md).
---
## Configure a plugin
You can perform configuration-related tasks: add CLI options, read Besu configuration values, validate configuration at startup, and reload configuration at runtime.
## Prerequisites
[Set up a plugin project](set-up-a-plugin.md).
## Add plugin CLI options
Use the `register` method to add plugin-specific options to the Besu command line.
Retrieve the [`PicoCLIOptions`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/PicoCLIOptions.html) service and pass an options object to `addPicoCLIOptions`.
The options object is a plain class (or `this`) whose fields carry [PicoCLI](https://picocli.info/) `@Option` annotations.
```java
public class ExamplePlugin implements BesuPlugin {
@Option(names = "--plugin-example-enabled", description = "Enable the example plugin feature.")
private boolean enabled = false;
@Override
public void register(final ServiceManager serviceManager) {
this.serviceManager = serviceManager;
serviceManager
.getService(PicoCLIOptions.class)
.ifPresent(cli -> cli.addPicoCLIOptions("example", this));
}
...
}
```
:::warning Important
Plugin CLI option names must use the prefix `--plugin--`, where `` is the value you pass to `addPicoCLIOptions`.
For example, passing `"example"` means every `@Option` name must start with `--plugin-example-`.
:::
Once registered, plugin options are automatically accepted through the Besu TOML configuration
file and as environment variables in addition to the CLI option, using the standard Besu naming
conventions.
## Read Besu configuration
Use [`BesuConfiguration`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BesuConfiguration.html) when your plugin needs selected Besu configuration values.
The service is available from `register` onward.
```java
@Override
public void register(final ServiceManager serviceManager) {
serviceManager
.getService(BesuConfiguration.class)
.ifPresent(config -> {
// Use config values, for example config.getDataPath().
});
}
```
Available values include:
- Configured RPC HTTP host, port, and timeout.
- Data path and storage path.
- Database format.
- Minimum gas price.
- Data storage configuration.
Treat `BesuConfiguration` as optional and use only the values your plugin needs.
## Validate plugin configuration
Validate plugin configuration at startup, before the plugin begins runtime work.
If the plugin can't run with the supplied configuration, throw an exception with an actionable
message so the operator knows what to fix.
```java
@Override
public void start() {
if (enabled && targetUrl == null) {
throw new IllegalStateException(
"plugin-example-url is required when --plugin-example-enabled is true");
}
// Proceed with startup.
}
```
## Reload plugin configuration
Implement `reloadConfiguration` when your plugin can apply updated configuration values without
restarting Besu.
```java
@Override
public CompletableFuture reloadConfiguration() {
// Reload plugin-owned configuration here.
return CompletableFuture.completedFuture(null);
}
```
Besu calls this method through the
[`plugins_reloadPluginConfig`](../../public-networks/reference/api/plugins.md#plugins_reloadpluginconfig)
JSON-RPC method.
The method belongs to the `PLUGINS` API group, which is disabled by default.
Enable it with [`--rpc-http-api`](../../public-networks/reference/options.md#rpc-http-api) or
[`--rpc-ws-api`](../../public-networks/reference/options.md#rpc-ws-api).
Calling `plugins_reloadPluginConfig` without parameters reloads all plugins.
Supplying a plugin name reloads only that plugin.
Besu matches the name against the value returned by `BesuPlugin.getName`.
Only reload values your plugin can apply safely while Besu is running.
Leave startup-only settings unchanged until the next restart, and document them as non-reloadable.
---
## Deploy a plugin
Build your plugin distribution and deploy it to a running Besu installation.
## Prerequisites
- A completed Besu plugin.
See how to [set up a plugin project](set-up-a-plugin.md).
- A [Besu installation](../../public-networks/get-started/install/index.md).
## Steps
### 1. Build the distribution
Run the `distZip` task provided by the [Gradle plugin](https://github.com/Consensys/besu-plugin-gradle-plugin)
to package your plugin:
```bash
./gradlew distZip
```
The output archive at `build/distributions/.zip` contains only your plugin JAR and
any extra runtime dependencies that Besu does not already provide.
JARs already in Besu's `lib` directory are excluded from the ZIP.
:::tip
If your plugin has no extra dependencies, the ZIP contains a single JAR.
:::
To inspect the contents of the archive before deploying:
```bash
unzip -l build/distributions/.zip
```
### 2. Deploy to Besu
The method for deploying your plugin depends on how you installed Besu.
#### Standard installation
Create a `plugins` directory at the root of your Besu installation if it doesn't already exist,
then unzip the archive into it.
The `-j` flag flattens the ZIP so all JARs land directly in `plugins/`:
```bash
unzip -j build/distributions/.zip -d /path/to/besu/plugins/
```
Start Besu.
By default, Besu loads all JARs found in the `plugins` directory automatically.
To load only specific plugins, pass a comma-separated list to
[`--plugins`](../../public-networks/reference/options.md#plugins).
#### Homebrew
The installation lives in the Homebrew Cellar (for example,
`/opt/homebrew/Cellar/besu/`, which `brew --prefix besu` resolves to).
By default, Besu looks for plugins in a `plugins` directory there, but Homebrew replaces the entire
Cellar directory on `brew upgrade`, which removes any plugins you add.
Instead, keep your plugins in a stable location outside the Cellar and point Besu at it using the
`besu.plugins.dir` system property via `BESU_OPTS`:
```bash
mkdir -p ~/besu/plugins
unzip -j build/distributions/.zip -d ~/besu/plugins/
export BESU_OPTS="-Dbesu.plugins.dir=$HOME/besu/plugins"
besu [options]
```
#### Docker
The Besu Docker image doesn't include a `plugins` directory.
Use a bind mount to inject your plugin JARs into the container at `/opt/besu/plugins`:
```bash
# Unzip the distribution into a local directory.
unzip -j build/distributions/.zip -d /host/path/to/plugins/
# Mount that directory when starting the container.
docker run \
-v /host/path/to/plugins:/opt/besu/plugins \
hyperledger/besu:latest
```
To use a different path inside the container, override the plugins directory using the
`besu.plugins.dir` system property via `BESU_OPTS`:
```bash
docker run \
-e BESU_OPTS="-Dbesu.plugins.dir=/data/plugins" \
-v /host/path/to/plugins:/data/plugins \
hyperledger/besu:latest
```
### 3. Verify startup
Check the Besu startup logs to confirm your plugin was detected and registered.
Besu logs a plugin registration summary that lists registered plugins and any plugins that
were detected but skipped.
Use [`--plugins-verification-mode`](../../public-networks/reference/options.md#plugins-verification-mode)
to control how Besu handles plugin verification failures:
- `NONE` (default) logs a warning and continues.
- `FULL` logs an error and stops Besu.
## Next steps
[Troubleshoot](troubleshoot.md) common issues.
---
## Set up a plugin project
Configure the build for a Besu plugin project, implement the `BesuPlugin` interface,
and register the plugin so Besu can discover it at startup.
## Prerequisites
- Java 25+.
You can install Java using `brew install openjdk@25` or manually install the
[Java JDK](https://www.oracle.com/java/technologies/downloads).
- [Gradle](https://gradle.org/install/).
## Steps
### 1. Configure your build
Besu provides a [Gradle plugin](https://github.com/Consensys/besu-plugin-gradle-plugin) to simplify
the plugin developer experience, enabling you to bootstrap a new plugin project easily.
The plugin:
- Adds the Maven repositories required to fetch Besu dependencies.
- Pre-populates the compile classpath with everything Besu provides, using the Besu BOM and an
artifact catalog.
- Produces a slim distribution ZIP that excludes JARs already on Besu's classpath.
In a new plugin project, apply the Gradle plugin (`net.consensys.besu-plugin-distribution`), and set the Besu version you want to compile your plugin against:
```groovy title="build.gradle"
plugins {
id 'net.consensys.besu-plugin-distribution' version '0.2.1'
}
besuPlugin {
besuVersion = '26.6.0'
}
```
:::note
The Gradle plugin resolves the matching Besu API JARs as compile-time dependencies, so your plugin builds against that version's API surface.
:::
#### Multi-module projects
In a multi-module project, apply `net.consensys.besu-plugin-library` to modules that are shared
libraries rather than plugins themselves.
Apply `net.consensys.besu-plugin-distribution` only to modules that directly expose `BesuPlugin`
implementations.
```groovy title="library/build.gradle"
plugins {
id 'net.consensys.besu-plugin-library' version '0.2.1'
}
```
Library modules are excluded from the plugin distribution ZIP.
#### Declare extra dependencies
Only declare dependencies that Besu does not already provide.
The Gradle plugin pre-populates the classpath from the Besu BOM and artifact catalog, so most
Besu-related libraries are already available without an explicit declaration.
:::warning
Bundling a JAR that Besu already provides causes classloading conflicts at runtime and may prevent
your plugin from loading.
:::
#### Configure the build manually
If you prefer not to use the Gradle plugin, add `besu-plugin-api` to your build, matching the
Besu version you are targeting:
```groovy title="build.gradle"
dependencies {
compileOnly 'org.hyperledger.besu:besu-plugin-api:26.6.0'
}
```
Use `compileOnly` because `besu-plugin-api` is provided by Besu at runtime and must not be
bundled in your JAR.
You are responsible for managing all other Besu dependencies and configuring the packaging
task to produce a slim distribution.
### 2. Generate the Gradle wrapper
Generate the [Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html) so the
project builds with a consistent Gradle version.
This creates the `gradlew` script used to [build and deploy the plugin](deploy-a-plugin.md):
```bash
gradle wrapper
```
### 3. Implement the plugin class
Create a class that implements [`BesuPlugin`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/BesuPlugin.html).
The three required methods are `register`, `start`, and `stop`.
Besu calls `register(ServiceManager)` early in startup.
[`ServiceManager`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/ServiceManager.html) is the interface through which your plugin accesses all Besu services.
This is the only time it is provided, so store it in a field for later use.
The `getName` method is optional; it defaults to the fully qualified class name, but overriding it with
a short string gives your plugin a readable identifier.
```java title="ExamplePlugin.java"
package example;
public class ExamplePlugin implements BesuPlugin {
private ServiceManager serviceManager;
@Override
public String getName() {
return "example";
}
@Override
public void register(final ServiceManager serviceManager) {
this.serviceManager = serviceManager;
}
@Override
public void start() {}
@Override
public void stop() {}
}
```
### 4. Register the plugin for discovery
Besu discovers plugin classes using Java's `ServiceLoader`.
Register your plugin by including a service provider entry for `BesuPlugin`.
You can generate the entry using Google's `@AutoService` annotation processor:
```java title="ExamplePlugin.java"
@AutoService(BesuPlugin.class)
public class ExamplePlugin implements BesuPlugin { ... }
```
The annotation processor generates the `META-INF/services` entry at compile time.
#### Create a service file manually
If you prefer not to use the annotation processor, you can manually create the following file under `src/main/resources`:
```text
META-INF/services/org.hyperledger.besu.plugin.BesuPlugin
```
The file must contain the fully qualified class name of each `BesuPlugin` implementation, one
per line:
```text
example.ExamplePlugin
```
## Next steps
- Learn about the [plugin lifecycle](../get-started/plugin-lifecycle.md).
- Integrate [events and metrics](../services/events-and-metrics.md), [custom RPC endpoints](../services/custom-rpc-endpoints.md),
and other plugin services.
- When you're ready to ship, [build and deploy the plugin](deploy-a-plugin.md).
- [Troubleshoot](troubleshoot.md) common issues.
---
## Test a plugin
Test your plugin against the same lifecycle boundaries Besu uses: lifecycle callbacks, service
retrieval, runtime effects, and shutdown cleanup.
## Prerequisites
A completed Besu plugin.
See how to [set up a plugin project](set-up-a-plugin.md).
## Unit test lifecycle code
Use [`ServiceManager.SimpleServiceManager`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/ServiceManager.html) to unit test code that retrieves Plugin API services.
Add only the services the test needs, then call the lifecycle method under test.
```java
class ExamplePluginTest {
@Test
void register_storesServiceManager() {
var serviceManager = new ServiceManager.SimpleServiceManager();
var plugin = new ExamplePlugin();
plugin.register(serviceManager);
// Assert that the plugin stored the ServiceManager and registered any extension points.
}
@Test
void register_handlesMissingOptionalService() {
// Empty ServiceManager — the plugin must not throw when optional services are absent.
var serviceManager = new ServiceManager.SimpleServiceManager();
var plugin = new ExamplePlugin();
assertDoesNotThrow(() -> plugin.register(serviceManager));
}
}
```
Test that the plugin:
- Stores `ServiceManager` in `register`.
- Handles missing optional services without throwing.
- Registers early extension points in `register`.
- Starts runtime work in `start`.
- Removes listeners and stops background work in `stop`.
## Test feature behavior
Choose tests that match the plugin feature:
- For custom RPC endpoints, verify the registered namespace, function name, parameters, and return
value.
- For events, verify that listeners are registered in `start` and removed in `stop`.
- For metrics, verify that metric categories and handles are created as expected.
- For configuration, verify valid values, invalid values, and reloadable values.
- For transaction pool, storage, permissioning, or tracing plugins, test the service integration
points your plugin registers.
## Run the plugin with Besu
Add at least one startup test that runs Besu with the packaged plugin JAR.
This catches service provider registration, dependency packaging, plugin verification, and
lifecycle timing issues that unit tests can miss.
## Next steps
- [Deploy the plugin](deploy-a-plugin.md) to a Besu installation.
- [Troubleshoot](troubleshoot.md) common issues.
---
## Troubleshoot
Troubleshoot common plugin development issues.
## Plugin does not load
Check that:
- The plugin JAR is in Besu's `plugins` directory.
- The JAR contains a `META-INF/services/org.hyperledger.besu.plugin.BesuPlugin` entry.
- The service provider entry contains the fully qualified plugin implementation class name.
- The plugin class is available in the JAR.
- If you use `--plugins`, the value matches the plugin implementation class simple name.
## Service is missing
[`ServiceManager.getService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/ServiceManager.html) returns `Optional` because services can be unavailable.
A service might be missing because:
- The service is not available in the current lifecycle phase.
- The Besu version does not include the service.
- The current Besu configuration does not provide the service.
Handle missing services explicitly.
Only fail startup when the missing service is required for a user-requested plugin feature.
## RPC method returns `Method not found`
For custom RPC endpoints, check that:
- The plugin registers the endpoint in `register`.
- The namespace and function name are alphanumeric.
- The JSON-RPC API list enables the plugin namespace with `--rpc-http-api` or `--rpc-ws-api`.
Besu exposes plugin RPC methods as `_`.
## Plugin loads but has no effect
Check [lifecycle timing](../get-started/plugin-lifecycle.md):
- Register CLI options and RPC endpoints in `register`.
- Start listeners, metrics, and background work in `start`.
- Remove listeners and stop background work in `stop`.
---
## Besu plugins
Besu plugins are Java extensions that add custom functionality to Besu without changing Besu source code.
Plugins are built using the [Plugin API](pathname:///plugins/reference/plugin-api/index.html), which provides
services for interacting with Besu.
Using these services, plugins can query Besu state, configure behavior, extend or replace parts of Besu, and listen
for events such as block imports and transaction pool changes.
You can create your own plugin to build app-specific chains, integrate Besu with enterprise systems,
observe blockchain activity, analyze transactions, support Layer 2 networks, or add debugging and
operational tooling.
Get started with the [quickstart](get-started/quickstart.md), or explore the
[plugin lifecycle](get-started/plugin-lifecycle.md) and [plugin services](/plugins/services).
## Architecture
The following diagram illustrates some of the services exposed by the Plugin API.

If you have questions about creating or using Besu plugins, ask on the **besu** channel on
[Discord](https://discord.gg/hyperledger).
---
## Resources
See the following open source Besu plugins:
- [Besu RocksDB storage plugin](https://github.com/besu-eth/besu/tree/main/plugins/rocksdb)
- [Linea sequencer plugins](https://github.com/Consensys/linea-monorepo/tree/main/linea-besu/plugins/linea-sequencer)
- [Linea state recovery plugin](https://github.com/Consensys/linea-monorepo/tree/main/linea-besu/plugins/state-recovery)
- [Linea tracer plugin](https://github.com/Consensys/linea-monorepo/tree/main/tracer)
- [Besu-Shomei plugin](https://github.com/Consensys/besu-shomei-plugin)
- [Besu HSM plugin](https://github.com/besu-eth/besu-hsm-plugin)
## Get support
If you have questions about creating or using Besu plugins, ask on the **besu** channel on
[Discord](https://discord.gg/hyperledger).
---
## Chain state and simulation
Use chain state and simulation services to inspect blocks, receipts, transactions, world state,
or simulated execution results.
## Read blockchain data
[`BlockchainService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BlockchainService.html) exposes methods to retrieve blocks, block headers, receipts, transactions, the
chain head, safe and finalized blocks, chain ID, base fee information, and hard fork IDs.
It also includes methods for storing blocks and setting safe or finalized block hashes.
Use this service for plugins that need chain metadata or historical block data.
For example, use `BlockchainService` to expose chain head data from another plugin feature such as
a custom RPC endpoint or metric:
```java
@Override
public void start() {
serviceManager
.getService(BlockchainService.class)
.ifPresent(
blockchain -> {
Hash chainHeadHash = blockchain.getChainHeadHash();
long chainHeadNumber = blockchain.getChainHeadHeader().getNumber();
Optional chainId = blockchain.getChainId();
});
}
```
## Read world state
[`WorldStateService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/WorldStateService.html) exposes the current `WorldView` and, when available, a `WorldView` for a block
hash.
Use this service for plugins that need account or storage state through Besu's world state view.
For example, retrieve the current world state view:
```java
@Override
public void start() {
serviceManager
.getService(WorldStateService.class)
.ifPresent(worldState -> {
WorldView currentWorldView = worldState.getWorldView();
});
}
```
## Simulate execution
[`TransactionSimulationService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/TransactionSimulationService.html) simulates transactions and can create a pending block header for simulation.
[`BlockSimulationService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BlockSimulationService.html) simulates blocks and includes a method to simulate and persist world state.
Use simulation services for plugins that need to evaluate transaction or block execution without
submitting a normal transaction through JSON-RPC.
For example, use `TransactionSimulationService` to create a pending block header for transaction
simulation:
```java
@Override
public void start() {
serviceManager
.getService(TransactionSimulationService.class)
.ifPresent(
simulation -> {
ProcessableBlockHeader pendingHeader = simulation.simulatePendingBlockHeader();
});
}
```
If the plugin already has the transaction, state overrides, block overrides, and tracer it needs, it
can call the simulation methods directly:
```java
Optional result =
simulation.simulate(
transaction,
Optional.empty(),
blockHash,
operationTracer,
EnumSet.noneOf(TransactionSimulationService.SimulationParameters.class));
```
For block simulation, pass the block number, transactions, block overrides, and state overrides:
```java
PluginBlockSimulationResult result =
blockSimulation.simulate(blockNumber, transactions, blockOverrides, stateOverrides);
```
## Read sync status
[`SynchronizationService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/sync/SynchronizationService.html) exposes sync status methods such as `isInitialSyncPhaseDone`,
`getSyncStatus`, `isInSync`, and `getBestPeerChainHead`.
It also exposes advanced methods that can start or stop synchronization, set
the chain head, fire forkchoice events, and disable the world state trie.
Use the chain-control methods only for specialized plugins that intentionally manage sync or chain
head behavior.
For ordinary observability, read sync status without changing synchronization behavior:
```java
@Override
public void start() {
serviceManager
.getService(SynchronizationService.class)
.ifPresent(
sync -> {
boolean initialSyncDone = sync.isInitialSyncPhaseDone();
boolean inSync = sync.isInSync();
Optional status = sync.getSyncStatus();
Optional bestPeerChainHead = sync.getBestPeerChainHead();
});
}
```
---
## Consensus and validator queries
Use consensus query services to inspect validator information on proof of authority (PoA) networks.
[`PoaQueryService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/query/PoaQueryService.html) exposes:
- Validators for the latest block.
- The proposer of a block.
- The local signer address.
[`BftQueryService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/query/BftQueryService.html) extends `PoaQueryService` for BFT-style PoA networks and exposes:
- The round number from a block header.
- Signers from a block header.
- The consensus mechanism name.
Handle these services as optional.
They might not be available for every network configuration.
For example, expose the latest PoA validator count as a metric or RPC result:
```java
@Override
public void start() {
serviceManager
.getService(PoaQueryService.class)
.ifPresent(
poa -> {
int validatorCount = poa.getValidatorsForLatestBlock().size();
Address localSigner = poa.getLocalSignerAddress();
});
}
```
For BFT-specific metadata, combine `BftQueryService` with a block header:
```java
@Override
public void start() {
serviceManager
.getService(BftQueryService.class)
.ifPresent(
bft -> {
String consensusName = bft.getConsensusMechanismName();
int round = bft.getRoundNumberFrom(blockHeader);
Collection signers = bft.getSignersFrom(blockHeader);
});
}
```
---
## Custom RPC endpoints
Use [`RpcEndpointService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/RpcEndpointService.html) to register plugin functions as custom JSON-RPC methods.
## Register an endpoint
Register endpoints in `register(ServiceManager)`.
The Plugin API requires endpoint registration during `register`, before Besu configures RPC endpoints.
Besu does not call the handler before `start`.
```java
@Override
public void register(final ServiceManager serviceManager) {
this.serviceManager = serviceManager;
serviceManager
.getService(RpcEndpointService.class)
.ifPresent(
rpc ->
rpc.registerRPCEndpoint(
"example",
"status",
request -> Map.of("status", "ok")));
}
```
Besu exposes the method as `_`.
In this example, the JSON-RPC method is `example_status`.
## Parameters and return values
`RpcEndpointService` passes a [`PluginRpcRequest`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/rpc/PluginRpcRequest.html) to the handler.
The request parameters are exposed as strings.
Complex input objects are not supported by the plugin RPC request interface.
The handler can return a Java object, primitive, or array.
Besu serializes the return value to JSON.
If the handler throws an exception, Besu returns an internal error.
For example, a handler can read string parameters from `PluginRpcRequest.getParams`:
```java
@Override
public void register(final ServiceManager context) {
this.serviceManager = context;
serviceManager
.getService(RpcEndpointService.class)
.ifPresent(
rpc ->
rpc.registerRPCEndpoint(
"example",
"echo",
request -> {
Object[] params = request.getParams();
return Map.of("message", params.length == 0 ? "" : params[0].toString());
}));
}
```
## Enable the namespace
When you register a custom endpoint, you must also add the plugin namespace
to [`--rpc-http-api`](../../public-networks/reference/options.md#rpc-http-api) or
[`--rpc-ws-api`](../../public-networks/reference/options.md#rpc-ws-api) when starting Besu.
The namespace is matched case-insensitively, but uppercase is the convention.
For example, to enable the `example` namespace:
```bash
besu --rpc-http-enabled --rpc-http-api=ETH,NET,WEB3,EXAMPLE
```
---
## Events and metrics
Observe Besu activity using events, and expose plugin state through Besu's metrics system.
## Events
[`BesuEvents`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BesuEvents.html) lets plugins observe the following events:
- Block propagation.
- Block additions.
- Block reorganizations.
- Initial sync completion and restart.
- Transaction additions and drops.
- Sync status changes.
- Log emissions filtered by address and topics.
- Bad blocks.
Register event listeners in `start` and remove them in `stop`.
```java
private long listenerId;
@Override
public void start() {
serviceManager
.getService(BesuEvents.class)
.ifPresent(events -> listenerId = events.addBlockAddedListener(context -> {}));
}
@Override
public void stop() {
serviceManager
.getService(BesuEvents.class)
.ifPresent(events -> events.removeBlockAddedListener(listenerId));
}
```
Events are useful for plugins that forward Besu activity to external systems, collect
operational data, or react to chain activity.
## Metrics
Use [`MetricCategoryRegistry`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/metrics/MetricCategoryRegistry.html) to add a metric category, and use [`MetricsSystem`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/MetricsSystem.html) to create counters,
gauges, timers, histograms, summaries, and cache collectors.
`MetricsSystem` also exposes enabled metric categories, so plugins can check whether their category
is enabled before doing extra metrics work.
For example, register a plugin metric category during startup, then create a counter when metrics
are available:
```java
private static final MetricCategory EXAMPLE_CATEGORY =
new MetricCategory() {
@Override
public String getName() {
return "EXAMPLE";
}
@Override
public Optional getApplicationPrefix() {
return Optional.empty();
}
};
@Override
public void register(final ServiceManager serviceManager) {
this.serviceManager = serviceManager;
serviceManager
.getService(MetricCategoryRegistry.class)
.ifPresent(registry -> registry.addMetricCategory(EXAMPLE_CATEGORY));
}
@Override
public void start() {
serviceManager
.getService(MetricsSystem.class)
.ifPresent(
metrics -> {
Counter blocksSeen =
metrics.createCounter(EXAMPLE_CATEGORY, "blocks_seen", "Blocks seen by plugin");
blocksSeen.inc();
});
}
```
---
## Execution tracing and debugging
Use tracing services when a plugin needs execution traces or block-import tracing hooks.
[`TraceService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/TraceService.html) exposes methods to:
- Trace a block by block number.
- Trace a block by block hash.
- Trace execution with an operation tracer.
[`BlockImportTracerProvider`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BlockImportTracerProvider.html) lets a plugin provide a [`BlockAwareOperationTracer`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/tracer/BlockAwareOperationTracer.html) for a block header
during block import.
Tracing plugins commonly use operation tracers to inspect EVM execution, collect debugging data, or
produce trace output for external tools.
For example, trace a block by number with a plugin-provided tracer:
```java
@Override
public void start() {
serviceManager
.getService(TraceService.class)
.ifPresent(
traceService -> {
BlockTraceResult result =
traceService.traceBlock(blockNumber, blockAwareOperationTracer);
});
}
```
To participate in block import tracing, implement `BlockImportTracerProvider` and register it with
Besu in `start` using `addService`:
```java
public class ExampleImportTracerProvider implements BlockImportTracerProvider {
@Override
public BlockAwareOperationTracer getBlockImportTracer(final BlockHeader blockHeader) {
return blockAwareOperationTracer;
}
}
@Override
public void start() {
serviceManager.addService(BlockImportTracerProvider.class, new ExampleImportTracerProvider());
}
```
Known issue: BFT networks invoke the tracer twice per block
On QBFT and IBFT 2.0 networks, Besu processes each block twice: once during the validation phase
(before voting) and once during the commit phase (when importing the agreed block).
Each pass calls `getBlockImportTracer(header)`, creating a fresh, independent tracer instance.
Both tracer instances receive `traceEndTransaction` for every transaction in the block.
This means that on BFT networks, your plugin will see each transaction twice per block.
The two tracer instances have no shared state, so per-tracer deduplication (for example, a `Set`
field on the tracer) does not help; the duplicate comes from a separate tracer object.
Deduplicate at a shared data layer keyed by both block hash and transaction hash.
On proof of stake networks, each block is processed once and the tracer fires once per transaction.
---
## Permissioning and peers
Use permissioning and peer services to influence network access or interact with peer connections.
## Permissioning
[`PermissioningService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/PermissioningService.html) lets plugins register providers for:
- Node connection permissioning - Restrict node access to known participants only.
- Transaction permissioning - Restrict transaction processing based on transaction properties.
- Node message permissioning - Propagate different types of devP2P messages to particular nodes.
For example, this can be used to prevent pending transactions from being forwarded to other nodes.
For example, register a node connection permissioning provider:
```java
@Override
public void register(final ServiceManager context) {
this.serviceManager = context;
serviceManager
.getService(PermissioningService.class)
.ifPresent(
permissioning ->
permissioning.registerNodePermissioningProvider(nodeConnectionProvider));
}
```
The plugin supplies the provider implementation.
## Peers
[`P2PService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/p2p/P2PService.html) exposes methods to:
- Enable or disable discovery.
- Get peer counts and peer connections.
- Subscribe to peer connect and disconnect events.
- Subscribe to messages for a capability.
- Send messages to peers.
- Disconnect peers.
Use `P2PService` for plugins that need peer visibility or direct peer interactions.
For example, read the current peer count and subscribe to connection events:
```java
@Override
public void start() {
serviceManager
.getService(P2PService.class)
.ifPresent(
p2p -> {
int peerCount = p2p.getPeerCount();
p2p.subscribeConnect(connection -> {});
p2p.subscribeDisconnect((connection, reason, initiatedByPeer) -> {});
});
}
```
---
## Security module
Use [`SecurityModuleService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/SecurityModuleService.html) to register a named security module.
The service exposes:
- `register(name, securityModuleSupplier)` to register a security module supplier.
- `getByName(name)` to retrieve a registered security module supplier.
Security module plugins are useful when node key operations must be delegated to a custom
implementation, such as an HSM-backed implementation.
For example, register a custom security module supplier:
```java
@Override
public void register(final ServiceManager context) {
this.serviceManager = context;
serviceManager
.getService(SecurityModuleService.class)
.ifPresent(
securityModules -> securityModules.register("example-hsm", () -> securityModule));
}
```
The plugin supplies the [`SecurityModule`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/securitymodule/SecurityModule.html) implementation.
---
## Transaction pool, selection, and validation
Use transaction pool services to inspect pending transactions, control
transaction pool availability, influence transaction selection, or add validation rules.
## Observe pending transactions
[`TransactionPoolService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/transactionpool/TransactionPoolService.html) exposes methods to:
- Disable or enable the transaction pool.
- Check whether the transaction pool is enabled.
- Retrieve pending transactions.
For event-based observation, [`BesuEvents`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BesuEvents.html) exposes transaction added and transaction dropped
listeners.
For example, inspect pending transaction count:
```java
@Override
public void start() {
serviceManager
.getService(TransactionPoolService.class)
.ifPresent(
transactionPool -> {
boolean enabled = transactionPool.isTransactionPoolEnabled();
int pendingCount = transactionPool.getPendingTransactions().size();
});
}
```
For event-based observation, register transaction listeners:
```java
@Override
public void start() {
serviceManager
.getService(BesuEvents.class)
.ifPresent(
events -> {
long addedListenerId = events.addTransactionAddedListener(transaction -> {});
long droppedListenerId =
events.addTransactionDroppedListener((transaction, reason) -> {});
});
}
```
## Influence selection
[`TransactionSelectionService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/TransactionSelectionService.html) exposes methods to create a plugin transaction selector, select
pending transactions, and register a plugin transaction selector factory.
Use this service when the plugin needs to participate in transaction selection.
For example, register a selector factory:
```java
@Override
public void register(final ServiceManager context) {
this.serviceManager = context;
serviceManager
.getService(TransactionSelectionService.class)
.ifPresent(
selection ->
selection.registerPluginTransactionSelectorFactory(transactionSelectorFactory));
}
```
The plugin supplies the [`PluginTransactionSelectorFactory`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/txselection/PluginTransactionSelectorFactory.html) implementation.
## Validate transactions
[`TransactionPoolValidatorService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/TransactionPoolValidatorService.html) exposes methods to create a plugin transaction pool validator and
register a plugin transaction validator factory.
[`TransactionValidatorService`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/TransactionValidatorService.html) exposes a method to register a transaction validation rule.
Use these services when a plugin needs custom validation behavior.
For example, register a transaction validation rule:
```java
@Override
public void register(final ServiceManager context) {
this.serviceManager = context;
serviceManager
.getService(TransactionValidatorService.class)
.ifPresent(
validator ->
validator.registerTransactionValidatorRule(
transaction -> Optional.empty()));
}
```
Return an empty `Optional` when the transaction is valid, or an `Optional` containing a reason when
the plugin rejects the transaction.
For transaction pool validation, register a validator factory:
```java
@Override
public void register(final ServiceManager context) {
this.serviceManager = context;
serviceManager
.getService(TransactionPoolValidatorService.class)
.ifPresent(
validator ->
validator.registerPluginTransactionValidatorFactory(
transactionPoolValidatorFactory));
}
```
The plugin supplies the [`PluginTransactionPoolValidatorFactory`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/txvalidator/PluginTransactionPoolValidatorFactory.html) implementation.
---
## Detect privately built transactions
In this tutorial, you'll build a complete Besu plugin from scratch, deploy it to a node, and watch it report live results.
The plugin watches the transactions your node sees gossiped in the public mempool, compares them to the transactions that
arrive in each new block, and reports the difference.
A transaction that appears in a block but was never seen in the mempool was likely built privately, for example by a
maximal extractable value (MEV) builder that bypasses the public mempool.
:::note
This is a heuristic, not proof.
A transaction can be missing from your node's view of the mempool for other reasons, such as your node starting recently,
peering differences, or propagation timing.
The signal is most meaningful once your node is fully synced and following the chain head.
:::
## Prerequisites
- Java 25+.
You can install Java using `brew install openjdk@25` or manually install the
[Java JDK](https://www.oracle.com/java/technologies/downloads).
- [Gradle](https://gradle.org/install/).
- A [Besu installation](../../public-networks/get-started/install/index.md).
- A consensus client, for example [Teku](https://docs.teku.consensys.net/), to run alongside Besu.
## Steps
### 1. Set up your project
A Besu plugin is a standalone Java project.
Create a new directory for it:
```bash
mkdir -p tx-detection-plugin/src/main/java/txdetection
cd tx-detection-plugin
```
By the end of the tutorial, your project will have the following structure:
```text
tx-detection-plugin/
├── build.gradle
├── settings.gradle
└── src/
└── main/
└── java/
└── txdetection/
└── TxDetectionPlugin.java
```
### 2. Configure the build
Besu provides a [Gradle plugin](https://github.com/Consensys/besu-plugin-gradle-plugin) to simplify
the plugin developer experience.
It automatically adds and manages dependencies, and packages the plugin artifacts when you
distribute the project.
In the root of your project, create `build.gradle`.
Apply the latest version of the [Gradle plugin](https://github.com/Consensys/besu-plugin-gradle-plugin)
(`net.consensys.besu-plugin-distribution`) and set the Besu version you want to compile your plugin against:
```groovy title="build.gradle"
plugins {
id 'net.consensys.besu-plugin-distribution' version '0.2.1'
}
besuPlugin {
besuVersion = '26.6.0'
}
```
Create `settings.gradle` to name the project.
The name determines the distribution ZIP file name:
```groovy title="settings.gradle"
rootProject.name = 'tx-detection-plugin'
```
Generate the [Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html) so the
project builds with a consistent Gradle version:
```bash
gradle wrapper
```
### 3. Create the plugin skeleton
Every plugin implements the [`BesuPlugin`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/BesuPlugin.html)
interface, which has three required methods: `register`, `start`, and `stop`.
Create `src/main/java/txdetection/TxDetectionPlugin.java` with the following skeleton:
```java title="TxDetectionPlugin.java"
package txdetection;
@AutoService(BesuPlugin.class)
public class TxDetectionPlugin implements BesuPlugin {
private static final Logger LOG = LoggerFactory.getLogger(TxDetectionPlugin.class);
private static final String PLUGIN_NAME = "tx-detection";
private ServiceManager serviceManager;
@Override
public String getName() {
return PLUGIN_NAME;
}
@Override
public void register(final ServiceManager serviceManager) {
// Store the ServiceManager and register early extension points.
this.serviceManager = serviceManager;
}
@Override
public void start() {
// Retrieve runtime services and begin work.
}
@Override
public void stop() {
// Remove listeners and release resources.
}
}
```
The `@AutoService(BesuPlugin.class)` annotation generates the service provider entry that Besu's `ServiceLoader`
uses to discover your plugin at startup.
Besu calls `register(ServiceManager)` once, early in startup, and passes the
[`ServiceManager`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/ServiceManager.html)
you use to access all Besu services.
Store it in a field for later use.
### 4. Track the mempool
Add a `Set` that records the hash of every transaction your node sees in the
mempool.
A busy node sees many transactions; use a bounded structure so memory usage stays constant.
The following uses a fixed-size `LinkedHashMap` that evicts the oldest entry once it reaches its capacity,
wrapped to make it thread-safe because Besu fires events from multiple threads:
```java title="TxDetectionPlugin.java"
// highlight-start
// highlight-end
@AutoService(BesuPlugin.class)
public class TxDetectionPlugin
implements BesuPlugin,
// highlight-next-line
BesuEvents.TransactionAddedListener {
private static final Logger LOG = LoggerFactory.getLogger(TxDetectionPlugin.class);
private static final String PLUGIN_NAME = "tx-detection";
// highlight-next-line
private static final int MAX_TRACKED_TRANSACTIONS = 100_000;
private ServiceManager serviceManager;
// highlight-start
// Bounded, thread-safe set of transaction hashes seen in the mempool.
private final Set mempoolHashes =
Collections.synchronizedSet(
Collections.newSetFromMap(
new LinkedHashMap<>() {
@Override
protected boolean removeEldestEntry(final Map.Entry eldest) {
return size() > MAX_TRACKED_TRANSACTIONS;
}
}));
@Override
public void onTransactionAdded(final Transaction transaction) {
mempoolHashes.add(transaction.getHash());
}
// highlight-end
}
```
Implementing [`BesuEvents.TransactionAddedListener`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BesuEvents.html)
lets the plugin receive a callback every time a transaction is added to the node.
### 5. Inspect new blocks
Add the block listener that detects unseen transactions.
For each new block that advances the chain head, count the transactions whose hash the plugin never recorded
from the mempool:
```java title="TxDetectionPlugin.java"
// highlight-next-line
@AutoService(BesuPlugin.class)
public class TxDetectionPlugin
implements BesuPlugin,
BesuEvents.TransactionAddedListener,
// highlight-next-line
BesuEvents.BlockAddedListener {
// ... fields and other methods ...
// highlight-start
// Number of unseen transactions in the most recent block.
private volatile long detectedTxLastBlock;
@Override
public void onBlockAdded(final AddedBlockContext blockContext) {
// Only consider blocks that advance the canonical chain head.
if (blockContext.getEventType() != AddedBlockContext.EventType.HEAD_ADVANCED) {
return;
}
long unseen =
blockContext.getBlockBody().getTransactions().stream()
.map(Transaction::getHash)
.filter(hash -> !mempoolHashes.contains(hash))
.count();
detectedTxLastBlock = unseen;
if (unseen > 0) {
LOG.info(
"Block {} contained {} transaction(s) not seen in the mempool",
blockContext.getBlockHeader().getNumber(),
unseen);
}
}
// highlight-end
}
```
Filtering on `HEAD_ADVANCED` avoids double-counting transactions from forks and reorganizations.
### 6. Register a metric category
Logging is useful, but metrics let you track the results over time.
Register a metric category during `register`.
[`MetricCategoryRegistry`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/metrics/MetricCategoryRegistry.html)
must be used in `register`:
```java title="TxDetectionPlugin.java"
// highlight-start
// highlight-end
public class TxDetectionPlugin
implements BesuPlugin,
BesuEvents.TransactionAddedListener,
BesuEvents.BlockAddedListener {
// highlight-start
// The category that groups this plugin's metrics.
private final MetricCategory metricCategory =
new MetricCategory() {
@Override
public String getName() {
return "tx_detection";
}
@Override
public Optional getApplicationPrefix() {
return Optional.empty();
}
};
// highlight-end
@Override
public void register(final ServiceManager serviceManager) {
this.serviceManager = serviceManager;
// highlight-start
serviceManager
.getService(MetricCategoryRegistry.class)
.ifPresent(registry -> registry.addMetricCategory(metricCategory));
// highlight-end
}
}
```
### 7. Create metrics and subscribe to events
In `start`, create the metrics and subscribe to the events.
These runtime services only become available at `start`.
Use [`MetricsSystem`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/MetricsSystem.html) to
create a counter for the running total and a gauge for the most recent block, then use
[`BesuEvents`](pathname:///plugins/reference/plugin-api/org/hyperledger/besu/plugin/services/BesuEvents.html) to register
both listeners.
Store the listener IDs in fields, so you can remove them in `stop`:
```java title="TxDetectionPlugin.java"
// highlight-start
// highlight-end
public class TxDetectionPlugin
implements BesuPlugin,
BesuEvents.TransactionAddedListener,
BesuEvents.BlockAddedListener {
// highlight-start
private long txListenerId;
private long blockListenerId;
private Counter detectedTxTotal;
// highlight-end
@Override
public void start() {
// highlight-start
serviceManager
.getService(MetricsSystem.class)
.ifPresent(
metrics -> {
detectedTxTotal =
metrics.createCounter(
metricCategory,
"total_detected",
"Total transactions imported in blocks but never seen in the mempool");
metrics.createLongGauge(
metricCategory,
"last_block",
"Transactions in the most recent block never seen in the mempool",
() -> detectedTxLastBlock);
});
serviceManager
.getService(BesuEvents.class)
.ifPresent(
events -> {
txListenerId = events.addTransactionAddedListener(this);
blockListenerId = events.addBlockAddedListener(this);
});
LOG.info("Transaction detection plugin started");
// highlight-end
}
@Override
public void stop() {
// highlight-start
serviceManager
.getService(BesuEvents.class)
.ifPresent(
events -> {
events.removeTransactionAddedListener(txListenerId);
events.removeBlockAddedListener(blockListenerId);
});
LOG.info("Transaction detection plugin stopped");
// highlight-end
}
}
```
Next, update `onBlockAdded` to increment the counter when it finds unseen transactions.
Add the highlighted lines inside the existing `if (unseen > 0)` block:
```java title="TxDetectionPlugin.java"
if (unseen > 0) {
// highlight-start
if (detectedTxTotal != null) {
detectedTxTotal.inc(unseen);
}
// highlight-end
LOG.info(
"Block {} contained {} transaction(s) not seen in the mempool",
blockContext.getBlockHeader().getNumber(),
unseen);
}
```
### 8. Review the complete plugin
Your finished `TxDetectionPlugin.java` should look like this:
```java title="TxDetectionPlugin.java"
package txdetection;
@AutoService(BesuPlugin.class)
public class TxDetectionPlugin
implements BesuPlugin,
BesuEvents.TransactionAddedListener,
BesuEvents.BlockAddedListener {
private static final Logger LOG = LoggerFactory.getLogger(TxDetectionPlugin.class);
private static final String PLUGIN_NAME = "tx-detection";
private static final int MAX_TRACKED_TRANSACTIONS = 100_000;
private ServiceManager serviceManager;
private long txListenerId;
private long blockListenerId;
private Counter detectedTxTotal;
private volatile long detectedTxLastBlock;
// Bounded, thread-safe set of transaction hashes seen in the mempool.
private final Set mempoolHashes =
Collections.synchronizedSet(
Collections.newSetFromMap(
new LinkedHashMap<>() {
@Override
protected boolean removeEldestEntry(final Map.Entry eldest) {
return size() > MAX_TRACKED_TRANSACTIONS;
}
}));
private final MetricCategory metricCategory =
new MetricCategory() {
@Override
public String getName() {
return "tx_detection";
}
@Override
public Optional getApplicationPrefix() {
return Optional.empty();
}
};
@Override
public String getName() {
return PLUGIN_NAME;
}
@Override
public void register(final ServiceManager serviceManager) {
this.serviceManager = serviceManager;
serviceManager
.getService(MetricCategoryRegistry.class)
.ifPresent(registry -> registry.addMetricCategory(metricCategory));
}
@Override
public void start() {
serviceManager
.getService(MetricsSystem.class)
.ifPresent(
metrics -> {
detectedTxTotal =
metrics.createCounter(
metricCategory,
"total_detected",
"Total transactions imported in blocks but never seen in the mempool");
metrics.createLongGauge(
metricCategory,
"last_block",
"Transactions in the most recent block never seen in the mempool",
() -> detectedTxLastBlock);
});
serviceManager
.getService(BesuEvents.class)
.ifPresent(
events -> {
txListenerId = events.addTransactionAddedListener(this);
blockListenerId = events.addBlockAddedListener(this);
});
LOG.info("Transaction detection plugin started");
}
@Override
public void stop() {
serviceManager
.getService(BesuEvents.class)
.ifPresent(
events -> {
events.removeTransactionAddedListener(txListenerId);
events.removeBlockAddedListener(blockListenerId);
});
LOG.info("Transaction detection plugin stopped");
}
@Override
public void onTransactionAdded(final Transaction transaction) {
mempoolHashes.add(transaction.getHash());
}
@Override
public void onBlockAdded(final AddedBlockContext blockContext) {
if (blockContext.getEventType() != AddedBlockContext.EventType.HEAD_ADVANCED) {
return;
}
long unseen =
blockContext.getBlockBody().getTransactions().stream()
.map(Transaction::getHash)
.filter(hash -> !mempoolHashes.contains(hash))
.count();
detectedTxLastBlock = unseen;
if (unseen > 0) {
if (detectedTxTotal != null) {
detectedTxTotal.inc(unseen);
}
LOG.info(
"Block {} contained {} transaction(s) not seen in the mempool",
blockContext.getBlockHeader().getNumber(),
unseen);
}
}
}
```
### 9. Build the plugin
From the project root, run the `distZip` task:
```bash
./gradlew distZip
```
The build produces `build/distributions/tx-detection-plugin.zip`, which contains your plugin JAR.
Because the plugin has no extra dependencies, the ZIP contains a single JAR.
Inspect the archive to confirm:
```bash
unzip -l build/distributions/tx-detection-plugin.zip
```
### 10. Deploy the plugin to Besu
Create a `plugins` directory at the root of your Besu installation if it doesn't already exist, then unzip the archive into it.
The `-j` option flattens the ZIP so the JAR lands directly in `plugins/`:
```bash
mkdir -p /path/to/besu/plugins
unzip -j build/distributions/tx-detection-plugin.zip -d /path/to/besu/plugins/
```
If you installed Besu using Homebrew or docker, see [Deploy a plugin](../how-to/deploy-a-plugin.md).
### 11. Run Besu with the plugin
The plugin relies on mempool gossip and block import events, so it needs a node following a live network.
This tutorial runs it on the Hoodi testnet, which syncs quickly and still surfaces transactions that never appeared in
your node's public mempool.
Run Besu as an execution client on Hoodi alongside a consensus client.
Start Besu with metrics enabled and the plugin's metric category included.
The [`--metrics-category`](../../public-networks/reference/options.md#metrics-category) option replaces
the default set of categories, so list the `TX_DETECTION` category to expose the plugin's metrics:
```bash
besu \
--network=hoodi \
--engine-rpc-enabled \
--engine-jwt-secret= \
--engine-host-allowlist="*" \
--metrics-enabled=true \
--metrics-host=127.0.0.1 \
--metrics-port=9545 \
--metrics-category=TX_DETECTION
```
Then start your consensus client.
For full setup instructions, including generating the shared JWT secret and starting the consensus client, see how to
[connect to a testnet](../../public-networks/get-started/connect/testnet.md) or follow the
[Besu and Teku testnet tutorial](../../public-networks/tutorials/besu-teku-testnet.md).
### 12. Verify the plugin is running
Check the Besu startup logs to confirm the plugin was detected and started.
You should see your start message:
```text
Transaction detection plugin started
```
Once the node is synced and following the chain head, the plugin logs each block that contains
transactions it never saw in the mempool:
```text
Block 1234567 contained 8 transaction(s) not seen in the mempool
```
You can paste the block number into a block explorer to inspect the block and its transactions, and
confirm whether any were submitted directly to a builder rather than the public mempool.
:::note
During initial sync, before your node receives mempool gossip, almost every block transaction
appears unseen.
Wait until the node is fully synced for accurate results.
:::
### 13. Query the metrics
Besu exposes metrics in Prometheus format on the metrics port.
Query the endpoint and filter for the plugin's category:
```bash
curl -s http://localhost:9545/metrics | grep tx_detection
```
You should see the plugin's counter and gauge, for example:
```text
# HELP tx_detection_total_detected Total transactions imported in blocks but never seen in the mempool
# TYPE tx_detection_total_detected counter
tx_detection_total_detected 152.0
# HELP tx_detection_last_block Transactions in the most recent block never seen in the mempool
# TYPE tx_detection_last_block gauge
tx_detection_last_block 8.0
```
:::note
The exact Prometheus metric names and any suffixes depend on the Besu version and metrics backend.
Use the `tx_detection` filter to find the current names in your output.
:::
You now have a working Besu plugin that detects and reports potentially privately built transactions.
## Next steps
- Learn more about [events and metrics](../services/events-and-metrics.md).
- Explore other [plugin services](/plugins/services).