A high-performance Byzantine Fault Tolerant (BFT) consensus implementation based on QBFT, built on top of Reth. This implementation includes a native ETH-wrapping ERC20 contract and comprehensive testing infrastructure.
- QBFT Consensus: Standards-compliant QBFT implementation with RLPx peer-to-peer networking
- Reth Integration: Built on Reth for high-performance block execution
- Native ERC20: QBFTErc20 contract that wraps native ETH balances
- Dynamic Validators: Add/remove validators through smart contract interactions
- Comprehensive Testing: Automated testnet with transaction load testing and contract verification
- Rust 1.93 or later (with nightly for formatting)
- Git
- Make
- Linux or macOS (Windows via WSL)
- Clone the repository:
git clone https://github.com/raylsnetwork/rbft.git
cd rbft- Build the project:
cargo build --releaseStart a 4-node testnet with a single command:
make testnet_startThis will:
- Generate validator keys and genesis configuration
- Start 4 validator nodes (HTTP ports 8545-8548)
- Deploy the QBFTValidatorSet contract
- Begin producing blocks every 500ms
The nodes will log to ~/.rbft/testnet/logs/ and store data in ~/.rbft/testnet/db/.
A follower node connects to an existing validator network, receives blocks, and keeps a
full copy of the chain. It does not participate in consensus (no --validator-key), so it
can be added to or removed from the network at any time without affecting liveness.
Before running a follower you need:
- A running RBFT testnet (e.g. started with
make testnet_start) - The
genesis.jsonandnodes.csvfrom the testnet assets directory (default:~/.rbft/testnet/assets/)
Extract the validator enode URLs from nodes.csv (column 5):
ENODES=$(awk -F',' 'NR>1{printf "%s%s",sep,$5; sep=","}' ~/.rbft/testnet/assets/nodes.csv)Then start the follower:
target/release/rbft-node node \
--chain ~/.rbft/testnet/assets/genesis.json \
--datadir /tmp/rbft-follower \
--port 12345 \
--authrpc.port 8651 \
--http --http.port 8600 \
--disable-discovery \
--trusted-peers "$ENODES"Key flags:
--chain— path to the sharedgenesis.json(must match the running network)--datadir— a fresh directory for the follower's database; must not be shared with a validator--port— P2P listen port; pick one that does not conflict with the validator nodes (default validator ports start at 30303)--authrpc.port— engine API port; also must not conflict (validator default: 8551+)--disable-discovery— prevents unwanted discv4/discv5 discovery; peers are supplied explicitly via--trusted-peers--trusted-peers— comma-separated enode URLs of the validators to connect to--validator-keyis intentionally omitted — its absence is what makes this a follower
To add a new validator to a running testnet you need a validator key (for signing QBFT messages), a P2P secret key (for RLPx networking), and the enode URL derived from it.
1. Generate keys
target/release/rbft-utils validator keygen --ip <YOUR_IP> --port 30305This prints JSON with all four values:
{
"validator_address": "0xABCD...",
"validator_private_key": "0x1234...",
"p2p_secret_key": "abcd...",
"enode": "enode://<pubkey>@<YOUR_IP>:30305"
}Save the keys and capture the enode:
echo "0x1234..." > validator-key-new.txt
echo "abcd..." > p2p-secret-key-new.txt
ENODE="enode://<pubkey>@<YOUR_IP>:30305"2. Start the node
target/release/rbft-node node \
--chain ~/.rbft/testnet/assets/genesis.json \
--datadir /tmp/rbft-new-validator \
--port 30305 \
--authrpc.port 8652 \
--http --http.port 8601 \
--disable-discovery \
--p2p-secret-key p2p-secret-key-new.txt \
--validator-key validator-key-new.txt \
--trusted-peers "$ENODES" # enodes of existing validators3. Register the validator in the contract
The admin key is taken from the RBFT_ADMIN_KEY environment variable, which must match
the key used when the genesis was generated. For a fresh local testnet started without
setting RBFT_ADMIN_KEY, the default is 0x000...0001:
target/release/rbft-utils validator add \
--validator-address 0xABCD... \
--enode "$ENODE" \
--rpc-url http://localhost:8545If RBFT_ADMIN_KEY is not set, pass it explicitly:
target/release/rbft-utils validator add \
--admin-key <ADMIN_PRIVATE_KEY> \
--validator-address 0xABCD... \
--enode "$ENODE" \
--rpc-url http://localhost:8545The new validator becomes active at the next epoch boundary.
Cast is a useful tool for interacting with the blockchain:
curl -L https://foundry.paradigm.xyz | bash
foundryupVerify installation:
cast --versionThe testnet command will show the block heights of the nodes in the validator set and should increase at a rate of around two blocks a second.
Switch to another terminal to interact with the chain via commands.
Using cast
cast bnUsing curl:
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'For local testing, provide a dev-only key via environment variable:
export RBFT_ADMIN_KEY=0x<dev-private-key>To derive the corresponding address:
cast wallet address --private-key "$RBFT_ADMIN_KEY"Send ETH using cast:
cast send 0x1234567890123456789012345678901234567890 \
--value 1ether \
--private-key "$RBFT_ADMIN_KEY" \
--rpc-url http://localhost:8545cast balance 0x<address-derived-from-RBFT_ADMIN_KEY>Or with curl:
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": ["0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf", "latest"],
"id": 1
}'Run make help to see all available commands:
testnet_start- Start a local testnet (default: 4 nodes)testnet_load_test- Start testnet with transaction load testing and auto-exittest-erc20-contract- Test ERC20 contract (funds, mints, verifies balanceOf)genesis- Generate a genesis filevalidator_status- Display QBFTValidatorSet contract statusadd-validator- Add a test validator to the contract
Manages the validator set with features:
- Add/remove validators (admin only)
- Query active validators
- Epoch-based validator set updates
Contract address: 0x0000000000000000000000000000000000001001
cargo testmake testnet_load_testThis starts a testnet with automated transaction generation and exits after reaching a target block height.
make test-erc20-contractThis runs automated tests that:
- Fund the ERC20 contract
- Mint tokens to a test address
- Verify
balanceOf()matches native balance - Exit with success/failure status
- Rust formatting is enforced with
cargo +nightly fmt(100 column width viarustfmt.toml) - CI runs
scripts/check_line_length.pyto cap code/config lines at 100 characters - Pre-commit hooks available for local validation:
pip install pre-commit pre-commit install
┌─────────────────┐
│ RPC Interface │ (HTTP on ports 8545+)
└────────┬────────┘
│
┌────────▼────────┐
│ Reth Engine │ (Block execution, state management)
└────────┬────────┘
│
┌────────▼────────┐
│ RBFT Consensus │ (QBFT protocol, validator rotation)
└────────┬────────┘
│
┌────────▼────────┐
│ RLPx Network │ (P2P messaging between validators)
└─────────────────┘
Configure the testnet with environment variables:
RBFT_NUM_NODES- Number of validators (default: 4)RBFT_EXIT_AFTER_BLOCK- Exit testnet after reaching this blockRBFT_TEST_ERC20- Enable ERC20 contract testing at block 10RBFT_RUN_MEGATX- Run transaction load generatorRBFT_ADD_AT_BLOCKS- Add validators at specific blocks (e.g., "10,20,30")RBFT_REGISTRY- Container registry for Docker images (required formake docker-push)
Example:
RBFT_NUM_NODES=7 RBFT_EXIT_AFTER_BLOCK=100 make testnet_startWe welcome contributions! Please see CONTRIBUTING.md for guidelines on:
- Code style and formatting
- Testing requirements
- Pull request process
- Development workflow
This project is licensed under the Apache License, Version 2.0. See LICENSE.md for details.
This project incorporates or derives from the following third-party works:
| Dependency | License | Copyright |
|---|---|---|
| reth | Apache-2.0 OR MIT | Copyright (c) 2022–2024 Paradigm |
| OpenZeppelin Contracts | MIT | Copyright (c) 2016–2024 OpenZeppelin |
Full license texts for these dependencies are available in their respective
repositories or in the target/forge_dependencies/ directory.
- IBFT Paper — The Istanbul BFT Consensus Algorithm
- QBFT Formal Specification (ConsenSys)
- Monitoring Setup
- Open an issue on GitHub
- Read the documentation
Note: This is a development build. Do not use in production without thorough security auditing.