What is ConsBlock?
ConsBlock is an open-source BFT consensus framework for distributed systems. It gives your network persistent state, sub-second block finality, and fault-tolerant agreement — without the protocol complexity.
Whether you're building a DeFi protocol, an on-chain game, or an AI agent swarm, ConsBlock provides the coordination primitives you need in a developer-friendly SDK.
Sub-second Finality
BFT engine, <50ms block commit
Cryptographic State
Merkle-trie, signed, tamper-proof
Peer Discovery
libp2p, no bootstrapper needed
EVM Compatible
Drop-in for any EVM chain
The Vision
Traditional distributed systems bolt on consensus as an afterthought — fragile Raft implementations, hand-rolled leader election, or black-box third-party middleware you can't debug at 3am.
ConsBlock exists to change that. Our goal is a world where any developer can spin up a production-grade consensus network in minutes, not weeks.
Principles
- Developer-first — clean API, great error messages, TypeScript-native
- Pluggable — swap consensus engines without touching application code
- Observable — metrics, logs, and a dashboard included by default
- Open — Apache 2.0, forever free, community-driven
Core Concepts
Rounds & Phases
Each consensus round goes through 4 phases: PROPOSE → PREVOTE → PRECOMMIT → COMMIT. A round is
locked once ⅔ of validators pre-commit.
Validators
Validators are nodes that participate in voting. They hold ECDSA secp256k1 keypairs. Leader election uses VRF (Verifiable Random Function) for unpredictable, sybil-resistant proposer selection.
State Root
After every block, the state machine computes a Merkle Patricia Trie root. This root is included in the block header, making the entire state cryptographically verifiable at any point in history.
Finality
ConsBlock has deterministic finality — once committed, blocks cannot be reversed. No reorgs, no fork-choice rules, no probabilistic waiting.
Quick Start
Install ConsBlock CLI
npm install -g consblock
Initialize a new network
consblock init my-network cd my-network
Start your node
consblock node start
Network runs at http://localhost:8545 · Metrics at :9090/metrics
Propose a state transition
import { ConsBlock, BftEngine } from 'consblock' const node = await ConsBlock.create({ engine: new BftEngine({ quorum: 0.67 }), port: 8545, }) node.on('block:finalized', (block) => { console.log(`✓ Round ${block.round} finalized`) }) await node.propose({ data: { amount: 100 } })
Installation
CLI (recommended)
npm install -g consblock # or pnpm add -g consblock
SDK only
npm install consblock
Docker
docker compose up --build
Docker starts 3 validator nodes + Prometheus + Grafana dashboard.
Configuration
| Variable | Default | Description |
|---|---|---|
PORT |
8545 | JSON-RPC port |
P2P_PORT |
26656 | libp2p listen port |
CHAIN_ID |
1337 | Network chain ID |
BLOCK_TIME_MS |
500 | Target block time (ms) |
QUORUM |
0.67 | Fraction needed to commit |
MAX_VALIDATORS |
100 | Max validator set size |
LOG_LEVEL |
info | debug / info / warn / error |
METRICS_PORT |
9090 | Prometheus metrics port |
Architecture Overview
Client App ──(JSON-RPC)──► ConsBlock Node ◄──(libp2p)──► Peers
│
WebSocket Events ◄───┤
│
┌────────────┴────────────┐
▼ ▼
Consensus Engine State Machine
(BFT / Tendermint) (Merkle Trie)
│ │
┌──────┴──────┐ ┌─────┴─────┐
▼ ▼ ▼ ▼
Mempool GossipSub LevelDB Snapshots
Key Components
- Consensus Engine — pluggable BFT adapter (PBFT or Tendermint)
- State Machine — Merkle Patricia Trie backed by LevelDB
- P2P Layer — libp2p with NOISE encryption + GossipSub
- Mempool — pending transaction pool with priority ordering
- JSON-RPC — Ethereum-compatible HTTP + WebSocket server
BFT Consensus
ConsBlock's consensus algorithm is based on practical Byzantine Fault Tolerance (pBFT). It provides safety and liveness as long as <⅓ of validators are faulty.
Round Lifecycle
| Phase | Description |
|---|---|
PROPOSE |
VRF-elected leader broadcasts a new block |
PREVOTE |
Validators verify and cast prevotes |
PRECOMMIT |
On ⅔ prevotes, validators precommit the block |
COMMIT |
On ⅔ precommits, block is finalized and stored |
Timeouts
Each phase has a configurable timeout. On timeout, validators vote nil and the round advances.
View-change protocol detects Byzantine leaders and rotates to the next VRF candidate.
Cryptographic State
All application state is stored in a Merkle Patricia Trie — the same structure used by Ethereum. This means:
- Every key-value pair can be proven with a compact Merkle proof
- The entire state is summarized by a single 32-byte root hash
- State roots are included in every block header
- Historical states are accessible by block hash
State API
// Read state const value = await node.state.get('balance:0xabc') // Generate Merkle proof const proof = await node.state.prove('balance:0xabc') // Verify proof independently const valid = verifyProof(proof, stateRoot)
Peer Discovery
ConsBlock uses libp2p for all networking. Peer discovery is automatic via Kademlia DHT — no hardcoded bootstrap list required.
How it works
- On startup, the node announces itself to the DHT
- It finds nearby peers using Kademlia routing tables
- Block and vote propagation uses GossipSub for efficient fan-out
- All connections are encrypted with the NOISE protocol
- NAT traversal via hole-punching and relay nodes
Manual peer connect
consblock node join --peer /ip4/10.0.0.2/tcp/26656/p2p/QmPeer1...
Security & Infrastructure
Validator Identity
Validators sign all messages with ECDSA secp256k1 keypairs — the same curve as Ethereum accounts. All vote messages include the validator address, round number, and block hash.
Slashing
Double-voting (equivocation) is detected on-chain. Evidence is included in the next block and the offending validator's stake is slashed.
Rate Limiting
Proposal and vote endpoints are rate-limited per validator key. Configurable via
RATE_LIMIT_PROPOSALS and RATE_LIMIT_VOTES env vars.
Message Authentication
Node-to-node messages include HMAC-SHA256 signatures with sequence numbers to prevent replay attacks.
TypeScript SDK
npm install consblock
Available Methods
| Method | Description |
|---|---|
ConsBlock.create(config) |
Spin up or connect to a consensus node |
node.propose(tx) |
Submit a state transition for voting |
node.state.get(key) |
Read current state value |
node.state.prove(key) |
Generate Merkle inclusion proof |
node.peers() |
List connected validator peers |
node.status() |
Get current round and phase |
node.on(event, fn) |
Subscribe to consensus events |
node.stop() |
Gracefully disconnect from network |
Full Example
import { ConsBlock, BftEngine } from 'consblock' const node = await ConsBlock.create({ engine: new BftEngine({ quorum: 0.67 }), port: 8545, peers: ['peer1.consblock.xyz'], }) node.on('block:finalized', (block) => { console.log(`Round ${block.round} — ${block.hash}`) }) const receipt = await node.propose({ data: { transfer: '0xabc → 0xdef', amount: 100 }, })
REST API
Health
GET /health
{ "status": "ok", "block": 14823, "peers": 7 }
Consensus Status
GET /consensus/status
{
"round": 14823,
"phase": "PRECOMMIT",
"leader": "0xabc…",
"votes": { "prevote": 7, "precommit": 6 }
}
Submit Transaction
POST /consensus/propose
Content-Type: application/json
{ "data": { "transfer": "0xabc", "amount": 100 } }
Read State
GET /state/:key
{ "key": "balance:0xabc", "value": "1000", "root": "0x4f8a…" }
WebSocket
Connect to ws://localhost:8545/ws for real-time consensus events.
Subscribe
{ "type": "subscribe", "events": ["block:finalized", "peer:joined"] }
Event Types
| Event | Description |
|---|---|
block:proposed |
Leader broadcast a new block |
block:prevoted |
Quorum of prevotes collected |
block:precommitted |
Round locked |
block:finalized |
Block committed to chain |
peer:joined |
New validator appeared |
peer:left |
Validator went offline |
state:synced |
Node caught up after being offline |
Close Codes
| Code | Meaning |
|---|---|
| 4000 | Auth timeout |
| 4001 | Rate limit exceeded |
| 4002 | Invalid message format |
| 4003 | Server shutting down |
BFT Engine (default)
Classic pBFT. Best for small-to-medium validator sets (< 100 nodes). Provides deterministic finality in 2 network round-trips.
import { BftEngine } from 'consblock' const engine = new BftEngine({ quorum: 0.67, // ⅔ threshold timeout: 1000, // phase timeout ms maxValidators: 50 })
Tendermint Engine
Higher throughput for larger validator sets. Implements the Tendermint BFT algorithm with weighted proposer priority.
import { TendermintEngine } from 'consblock/engines' const engine = new TendermintEngine({ proposerPriority: 'weighted' })
Custom Adapter
Implement the ConsensusAdapter interface to plug in any consensus algorithm.
import { ConsensusAdapter } from 'consblock' class MyEngine implements ConsensusAdapter { async propose(block: Block) { /* broadcast */ } async vote(block: Block, phase: Phase) { /* sign + send */ } async finalize(block: Block) { /* commit to state */ } }