Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ help:
@echo " fmt - Format code"
@echo " clippy - Run clippy lints"
@echo " clean - Clean build artifacts"
@echo " book - Build the user documentation (mdbook)"
@echo ""
@echo "Environment Variables:"
@echo ""
Expand Down Expand Up @@ -329,6 +330,10 @@ clippy:
clean:
$(CARGO) clean

.PHONY: book
book:
mdbook build book

# Dafny commands
dafny-translate:
@echo "Translating Dafny specification to Rust..."
Expand Down
11 changes: 11 additions & 0 deletions book/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[book]
authors = ["Rayls Network"]
language = "en"
src = "src"
title = "RBFT User Guide"

[build]
build-dir = "../target/book"

[output.html]
git-repository-url = "https://github.com/raylsnetwork/rbft"
39 changes: 39 additions & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Summary

[Introduction](./introduction.md)

# Getting Started

- [Prerequisites](./getting-started/prerequisites.md)
- [Installation](./getting-started/installation.md)

# Running a Chain

- [Local Testnet](./running/local-testnet.md)
- [Follower Nodes](./running/follower-nodes.md)
- [Validator Management](./running/validator-management.md)
- [Docker Deployment](./running/docker.md)
- [Kubernetes Deployment](./running/kubernetes.md)

# Deploying Contracts

- [Using Cast (Foundry)](./contracts/cast.md)
- [QBFTValidatorSet Contract](./contracts/validator-set.md)
- [Deploying Your Own Contracts](./contracts/deploying.md)

# Interacting with the Chain

- [Sending Transactions](./interacting/transactions.md)
- [ERC20 Tokens](./interacting/erc20.md)
- [Load Testing](./interacting/load-testing.md)

# Operations

- [Configuration Reference](./operations/configuration.md)
- [Monitoring and Logs](./operations/monitoring.md)
- [Troubleshooting](./operations/troubleshooting.md)

# Architecture

- [Overview](./architecture/overview.md)
- [QBFT Consensus](./architecture/qbft.md)
89 changes: 89 additions & 0 deletions book/src/architecture/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Architecture Overview

RBFT is built as a layered system on top of Reth, the Rust Ethereum client.

```
┌─────────────────┐
│ RPC Interface │ HTTP JSON-RPC (ports 8545+)
└────────┬────────┘
┌────────▼────────┐
│ Reth Engine │ EVM execution, state management, transaction pool
└────────┬────────┘
┌────────▼────────┐
│ RBFT Consensus │ QBFT protocol, proposer rotation, validator management
└────────┬────────┘
┌────────▼────────┐
│ RLPx Network │ P2P messaging between validators and followers
└─────────────────┘
```

## Crate structure

### `rbft` (core library)

The consensus protocol implementation with no Reth dependencies. Contains:

- QBFT state machine (`NodeState`)
- Message types (Proposal, Prepare, Commit, RoundChange, NewBlock)
- Block validation and proposer election
- Round change and timeout logic

This crate is designed to be testable in isolation using an in-memory
`NodeSwarm` simulation.

### `rbft-node` (binary)

Integrates the core library with Reth:

- Custom consensus engine (`RbftConsensus`)
- RLPx protocol handler for QBFT messages
- Block building and execution via Reth
- P2P connection management

### `rbft-utils` (binary)

Operator tooling:

- Genesis generation (compiles and deploys QBFTValidatorSet contract)
- Testnet orchestration (start/stop/monitor nodes)
- Validator management (add/remove/status via contract calls)
- Log analysis (logjam)

### `rbft-megatx` (binary)

Transaction load generator for stress testing.

### `rbft-validator-inspector` (binary)

Terminal UI for real-time validator monitoring.

## Node types

| Type | Has validator key | Participates in consensus | Produces blocks |
|---|---|---|---|
| Validator (proposer) | Yes | Yes | Yes (when elected) |
| Validator (non-proposer) | Yes | Yes | No |
| Follower | No | No | No |

## Data flow

1. Transactions arrive via JSON-RPC
2. The current proposer builds a block and broadcasts a `Proposal`
3. Validators verify and send `Prepare` messages
4. On quorum of prepares, validators send `Commit` messages
5. On quorum of commits, the block is finalized
6. A `NewBlock` message is broadcast so followers can update

## Fault tolerance

With `n` validators, RBFT tolerates `f = (n-1) / 3` Byzantine faults.
The quorum size is `(2n - 1) / 3 + 1`.

| Validators | Max faults | Quorum |
|---|---|---|
| 4 | 1 | 3 |
| 7 | 2 | 5 |
| 10 | 3 | 7 |
83 changes: 83 additions & 0 deletions book/src/architecture/qbft.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# QBFT Consensus

RBFT implements the QBFT (Quorum Byzantine Fault Tolerant) consensus protocol,
a practical BFT algorithm designed for permissioned blockchain networks.

## References

- [The Istanbul BFT Consensus Algorithm (IBFT paper)](https://arxiv.org/abs/2002.03613)
- [QBFT Formal Specification (ConsenSys)](https://github.com/ConsenSys/qbft-formal-spec-and-verification)

## Protocol overview

QBFT operates in rounds within each block height. Each round has a designated
proposer determined by round-robin rotation.

### Normal case (round 0)

1. **Block timeout** — the proposer waits for the block interval, then
broadcasts a `Proposal` containing the new block.
2. **Prepare** — validators verify the proposal and broadcast a `Prepare`
message.
3. **Commit** — once a validator receives a quorum of prepares, it broadcasts
a `Commit` message with a commit seal.
4. **Finalize** — once a quorum of commits is collected, the block is added
to the chain with the commit seals embedded in the header.
5. **NewBlock** — the committed block is broadcast so all nodes (including
followers) can update their chains.

### Round change

If the proposer fails to propose within the timeout, validators trigger a
round change:

1. Each validator sends a `RoundChange` message for the next round.
2. When a quorum of round changes is collected, the new round's proposer
creates a proposal with a justification (the round change messages).
3. The protocol continues from step 2 (prepare phase).

### Timeout schedule

Round timeouts grow exponentially to avoid thrashing:

```
timeout(r) = first_interval * growth_factor^r
```

Default values:

| Parameter | Default |
|---|---|
| `first_interval` | 1.0 s |
| `growth_factor` | 2.0 |
| `max_round` | 10 |

## Proposer election

The proposer for round 0 at a given height is the validator after the previous
block's proposer (wrapping around). For subsequent rounds, the index advances
by the round number:

```
round_zero_index = index_of(previous_proposer) + 1
proposer_index = (round_zero_index + round) % num_validators
```

At height 1, the first validator (index 0) proposes.

## Quorum and fault tolerance

For `n` validators:

- Maximum Byzantine faults tolerated: `f = (n-1) / 3`
- Quorum size: `q = (2n - 1) / 3 + 1`

The protocol guarantees safety (no conflicting blocks are finalized) as long as
at most `f` validators are faulty. It guarantees liveness as long as at least
`q` validators are honest and connected.

## Validator sets and epochs

The validator set can change dynamically through the QBFTValidatorSet contract.
Changes take effect at epoch boundaries (every `epochLength` blocks) to ensure
all validators agree on the set for a given block range.
67 changes: 67 additions & 0 deletions book/src/contracts/cast.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Using Cast (Foundry)

[Cast](https://book.getfoundry.sh/cast/) is a CLI tool from Foundry for
interacting with EVM-compatible chains. It is the recommended way to send
transactions and query state on an RBFT network.

## Installation

```bash
curl -L https://foundry.paradigm.xyz | bash
foundryup
```

Verify:

```bash
cast --version
```

## Common operations

All examples assume the default testnet RPC at `http://localhost:8545`.

### Check block height

```bash
cast bn
```

### Query an account balance

```bash
cast balance 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf
```

### Send ETH

```bash
cast send 0x1234567890123456789012345678901234567890 \
--value 1ether \
--private-key 0x<YOUR_KEY> \
--rpc-url http://localhost:8545
```

### Derive an address from a private key

```bash
cast wallet address --private-key 0x<YOUR_KEY>
```

### Call a contract (read-only)

```bash
cast call 0x0000000000000000000000000000000000001001 \
"getValidators()(address[])" \
--rpc-url http://localhost:8545
```

### Send a contract transaction

```bash
cast send 0x0000000000000000000000000000000000001001 \
"addValidator(address,string)" \
0xABCD... "enode://..." \
--private-key 0x<ADMIN_KEY> \
--rpc-url http://localhost:8545
```
68 changes: 68 additions & 0 deletions book/src/contracts/deploying.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Deploying Your Own Contracts

RBFT chains are fully EVM-compatible. Any contract that works on Ethereum can be
deployed to an RBFT network using standard tools.

## Using Foundry (forge)

Create a project and deploy:

```bash
forge init my-contract
cd my-contract

# Edit src/Counter.sol, then deploy:
forge create src/Counter.sol:Counter \
--rpc-url http://localhost:8545 \
--private-key 0x<YOUR_KEY>
```

## Using cast with raw bytecode

```bash
cast send --create <BYTECODE> \
--private-key 0x<YOUR_KEY> \
--rpc-url http://localhost:8545
```

## Using Hardhat

In `hardhat.config.js`:

```javascript
module.exports = {
networks: {
rbft: {
url: "http://localhost:8545",
accounts: ["0x<YOUR_PRIVATE_KEY>"]
}
}
};
```

Deploy:

```bash
npx hardhat run scripts/deploy.js --network rbft
```

## Getting test funds

On a default local testnet, the admin account
(`0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf`, derived from key `0x000...0001`)
is pre-funded with ETH. Transfer from it to fund your deployment account:

```bash
cast send 0x<YOUR_ADDRESS> \
--value 100ether \
--private-key 0x0000000000000000000000000000000000000000000000000000000000000001 \
--rpc-url http://localhost:8545
```

## Chain ID

The chain ID is set in `genesis.json`. Check it with:

```bash
cast chain-id --rpc-url http://localhost:8545
```
Loading
Loading