Custom consensus mechanism development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Custom consensus mechanism development
Complex
from 2 weeks to 3 months
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1217
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1046
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Developing a Custom Consensus Mechanism

Most projects that come with a request to "develop your own consensus" don't actually need a custom consensus. They need an application-specific chain with modified parameters: different block time, different transaction inclusion rules, custom mempool. This is solved via Cosmos SDK or OP Stack without writing a new consensus protocol. True custom consensus is 1–2 years of work by a team of experienced distributed systems engineers and formal verification of correctness. This is important to understand before starting technical discussion.

When Custom Consensus is Actually Needed

Legitimate cases: specialized network with non-standard performance requirements (> 100k TPS, deterministic finality < 100ms), consortium networks with custom validator rules, research/academic projects, experimental mechanisms (VDF-based randomness, threshold signatures as consensus).

In most cases it's simpler to take an existing algorithm and adapt it. Let's examine the architectural choice space.

Taxonomy of Consensus Protocols

Classical BFT: pBFT and Derivatives

pBFT (Practical Byzantine Fault Tolerance, Castro & Liskov, 1999) — first practical BFT algorithm. O(n²) messages, works with < n/3 Byzantine nodes. In pure form doesn't scale past ~20 nodes due to communication overhead.

Modern derivatives:

  • HotStuff (used in LibraBFT/DiemBFT/Jolteon): linear communication complexity O(n), leader scheme with pipelining. Facebook/Meta used for Diem.
  • Tendermint/CometBFT: round-based, deterministic finality per block, used in Cosmos SDK. Two phases: prevote and precommit. Requires > 2/3 voting power for finality.
  • PBFT with threshold signatures: replace n² communication with aggregation via BLS threshold signatures — each validator signs with BLS key, aggregator collects threshold signatures into one.

Nakamoto Consensus and Derivatives

Nakamoto PoW — probabilistic finality, fork choice rule (longest chain / most work). Never final, but practically irreversible after sufficient confirmations. Simplicity is the main advantage.

GHOST protocol (Greedy Heaviest-Observed Subtree): fork choice considers uncle blocks, not just main chain. Used in Ethereum (Gasper — combination of GHOST + Casper FFG).

Proof-of-Stake variants: in PoS "computational work" is replaced with stake. Validator selection via VRF (Verifiable Random Function) — Algorand, Cardano Ouroboros.

DAG-Based Consensus

Hashgraph (Hedera): events organized in DAG, virtual voting without messages. Deterministic algorithm from DAG structure computes consensus timestamp and order.

Narwhal/Bullshark (Sui): Narwhal — DAG-based mempool with certified availability (each block certified by 2f+1 signatures). Bullshark — interprets DAG for ordering. Separation of data dissemination and ordering.

Mysticeti (new Sui consensus): removes leader from critical path, reduces latency.

Implementation: Example HotStuff-Inspired Protocol

Let's examine key components when implementing BFT consensus in Go:

Data Structures

type Block struct {
    Height     uint64
    ParentHash [32]byte
    Txns       []Transaction
    QC         *QuorumCertificate // proof of previous block
    Timestamp  int64
    ProposerID NodeID
}

type QuorumCertificate struct {
    BlockHash  [32]byte
    Height     uint64
    Signatures []BLSSignature  // threshold aggregated signature
    Signers    []NodeID
}

type Vote struct {
    BlockHash [32]byte
    Height    uint64
    Round     uint32
    VoterID   NodeID
    Signature BLSSignature
}

Three Phases of HotStuff

HotStuff organizes consensus in three phases (prepare, pre-commit, commit) with pipelining — while block k passes commit, block k+1 passes pre-commit, block k+2 is in prepare:

type HotStuffNode struct {
    id          NodeID
    height      uint64
    lockedQC    *QuorumCertificate  // locked at pre-commit phase
    preparedQC  *QuorumCertificate  // prepared at prepare phase
    privateKey  bls.PrivateKey
    validators  ValidatorSet
}

func (n *HotStuffNode) onReceiveProposal(block *Block) {
    // Safety rule: accept only if block.QC >= n.lockedQC
    if block.QC.Height < n.lockedQC.Height {
        return // reject
    }
    
    // Liveness rule: accept if block.QC >= n.preparedQC
    // or block extends locked block
    if !n.safeNode(block) {
        return
    }
    
    vote := n.createVote(block)
    n.sendToLeader(vote)
}

func (n *HotStuffNode) safeNode(block *Block) bool {
    // Extends locked branch OR QC higher than lockedQC
    return block.QC.Height > n.lockedQC.Height || 
           n.extendsLockedBlock(block)
}

BLS Threshold Signatures

Signature aggregation via BLS12-381 curve — standard for modern BFT protocols. Threshold scheme (t of n): each validator signs with own key, aggregator collects t signatures and creates one aggregated signature, verifiable by one public key:

import "github.com/herumi/bls-eth-go-binary/bls"

func aggregateSignatures(sigs []bls.Sign) bls.Sign {
    var agg bls.Sign
    agg.Add(&sigs[0])
    for i := 1; i < len(sigs); i++ {
        agg.Add(&sigs[i])
    }
    return agg
}

func verifyQC(qc *QuorumCertificate, validators ValidatorSet) bool {
    pubkeys := make([]bls.PublicKey, len(qc.Signers))
    for i, id := range qc.Signers {
        pubkeys[i] = validators.GetPublicKey(id)
    }
    aggPubkey := bls.AggregatePubkeys(pubkeys)
    return qc.Signatures[0].VerifyHash(&aggPubkey, qc.BlockHash[:])
}

View Change: Handling Leader Failures

Liveness under Byzantine leader is the hardest aspect. In HotStuff, view change occurs on timeout:

func (n *HotStuffNode) onTimeout(view uint32) {
    // Broadcast timeout message with current lockedQC
    timeout := TimeoutMsg{
        View:     view,
        LockedQC: n.lockedQC,
        SenderID: n.id,
        Sig:      n.sign(view, n.lockedQC),
    }
    n.broadcast(timeout)
}

func (n *HotStuffNode) onReceiveTimeouts(timeouts []TimeoutMsg) {
    if len(timeouts) < n.validators.QuorumSize() {
        return
    }
    
    // New leader — node with highest view in round-robin or VRF
    newLeader := n.electLeader(timeouts[0].View + 1)
    
    if newLeader == n.id {
        // Select highest QC from timeout messages
        highQC := n.highestQC(timeouts)
        n.proposeBlock(highQC)
    }
}

Formal Verification

For production consensus protocol — formal verification of safety and liveness properties is mandatory. Tools:

TLA+ — formal specification language. Specify safety invariant: "two honest nodes cannot commit different blocks at the same height". TLC model checker verifies against all reachable states for n ≤ 5–7 nodes.

Ivy — language for distributed protocol verification. Hedera team used for Hashgraph. Coq/Lean — for proof assistant approach.

Without formal verification, custom consensus should not be used in production with real assets. Blockchain history is full of consensus bugs discovered years later (Ethereum Byzantium fork bugs, recent Cosmos SDK consensus vulnerabilities).

Network Layer: P2P Transport

Consensus messages require low-latency delivery. Protobuf serialization is mandatory (JSON is too slow for consensus-critical messages). Transport:

libp2p — de facto standard in Web3. GossipSub for broadcast, Direct streams for unicast. Used in Ethereum, Filecoin, Polkadot.

QUIC/gRPC — for more controlled P2P topologies (enterprise blockchain).

Stack and Timeline

Implementation language: Go (Tendermint, Ethereum CL) or Rust (Solana, NEAR, Polkadot substrate) — both have mature BLS libraries and p2p stacks.

Realistic stages:

  • Specification and formal model in TLA+: 4–6 weeks
  • Basic happy path implementation: 8–12 weeks
  • View change and Byzantine fault handling: 8–12 weeks
  • Testing (chaos testing, Byzantine fault injection): 8–12 weeks
  • Formal verification: 4–8 weeks
  • Security audit: 6–8 weeks

Total: 10–18 months to production-ready consensus. Adapting existing (CometBFT/HotStuff reference impl) with custom parameters — 3–6 months.