Skip to main content

Manage Validators

This guide covers adding, removing, and monitoring validators in a running QBFT/IBFT 2.0 Besu network.

How Validator Voting Works

In QBFT and IBFT 2.0, validator changes happen through on-chain voting:

  1. An existing validator proposes to add or remove a validator
  2. Other validators vote on the proposal
  3. When the proposal reaches a majority (>50% of current validators), the change takes effect at the next epoch boundary

No downtime is required. The network continues producing blocks during the voting process.

View Current Validators

Via JSON-RPC

curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "qbft_getValidatorsByBlockNumber",
"params": ["latest"],
"id": 1
}'

Response:

{
"jsonrpc": "2.0",
"id": 1,
"result": [
"0xaa36a7d6fb3e7f6ff89a4ecef5e27d28b37b74e3",
"0xbb36a7d6fb3e7f6ff89a4ecef5e27d28b37b74e4",
"0xcc36a7d6fb3e7f6ff89a4ecef5e27d28b37b74e5",
"0xdd36a7d6fb3e7f6ff89a4ecef5e27d28b37b74e6"
]
}

Via ChainLaunch API

curl http://localhost:8100/api/v1/networks/{networkId}/validators | jq

Add a Validator

Step 1: Create the Node

First, create a new Besu node and wait for it to sync with the network.

Step 2: Propose the Addition

Each existing validator must vote to add the new validator. Connect to each validator's RPC endpoint:

# Vote from validator 1
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "qbft_proposeValidatorVote",
"params": ["0xnew_validator_address", true],
"id": 1
}'

# Vote from validator 2
curl -X POST http://localhost:8546 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "qbft_proposeValidatorVote",
"params": ["0xnew_validator_address", true],
"id": 1
}'

Step 3: Verify

Once a majority of validators have voted, the new validator is added at the next epoch:

curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "qbft_getValidatorsByBlockNumber",
"params": ["latest"],
"id": 1
}'

Remove a Validator

Same process, but with false as the vote:

curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "qbft_proposeValidatorVote",
"params": ["0xvalidator_to_remove", false],
"id": 1
}'
warning

Never remove so many validators that fewer than 2f + 1 remain, where f is the Byzantine fault tolerance. For example, if you have 4 validators (tolerates 1 fault), do not remove 2 validators at once.

Check Pending Votes

curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "qbft_getPendingVotes",
"params": [],
"id": 1
}'

Discard a Vote

To cancel a pending vote:

curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "qbft_discardValidatorVote",
"params": ["0xvalidator_address"],
"id": 1
}'

Validator Fault Tolerance

ValidatorsByzantine Fault ToleranceCan lose
411 node
511 node
722 nodes
1033 nodes

Formula: f = floor((n - 1) / 3) where n is the number of validators.

Monitoring Validator Health

Key metrics to watch:

# Check if a validator is producing blocks
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "qbft_getSignerMetrics",
"params": [],
"id": 1
}'

This returns the number of blocks proposed and sealed by each validator, helping identify underperforming nodes.

Next Steps