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:
- An existing validator proposes to add or remove a validator
- Other validators vote on the proposal
- 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
}'
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
| Validators | Byzantine Fault Tolerance | Can lose |
|---|---|---|
| 4 | 1 | 1 node |
| 5 | 1 | 1 node |
| 7 | 2 | 2 nodes |
| 10 | 3 | 3 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
- Create Besu Nodes for adding new nodes to the network
- Create a Besu Network for genesis configuration
- Configure Monitoring for Prometheus-based alerting