Skip to main content

Overview

The Fenines consensus layer implements a Hybrid Proof-of-Authority (PoA) mechanism named Fenine, which combines deterministic block production with smart contract-governed validator selection. This architecture decouples consensus validation from validator governance, enabling dynamic validator sets without protocol-level modifications.
Consensus Type: Proof-of-Authority (PoA)
Signature Algorithm: ECDSA (secp256k1)
Block Time: 3 seconds (Tblock=3sT_{\text{block}} = 3s)
Epoch Length: 200 blocks (Eperiod=200E_{\text{period}} = 200)

Consensus Engine Architecture

Core Components

The Fenine consensus engine consists of four primary modules:

Mathematical Foundation

1. In-Turn Block Production

Validators produce blocks in a deterministic round-robin schedule defined by: Signer(Bn)=V[nmodV]\text{Signer}(B_n) = \mathcal{V}\left[n \bmod |\mathcal{V}|\right] where:
  • BnB_n = Block at height nn
  • V\mathcal{V} = Ordered validator set from FenineSystem contract
  • V|\mathcal{V}| = Cardinality of active validators (1V1011 \leq |\mathcal{V}| \leq 101)

2. Difficulty Assignment

Block difficulty encodes the in-turn status: Difficulty(Bn)={2if Signer(Bn)=Expected(Bn)1otherwise (out-of-turn)\text{Difficulty}(B_n) = \begin{cases} 2 & \text{if } \text{Signer}(B_n) = \text{Expected}(B_n) \\ 1 & \text{otherwise (out-of-turn)} \end{cases}
Difficulty serves as a tie-breaker during chain reorganizations, not a computational puzzle. Fenine uses signature verification, not hash-based mining.

3. Signature Verification

Each block header contains an ECDSA signature in the extraData field: ExtraData=Vanity32Signature65\text{ExtraData} = \text{Vanity}_{32} \| \text{Signature}_{65} Signature verification ensures: Verify(σ,Hblock,PubKeysigner)={trueif σ=Sign(Hblock,PrivKeysigner)falseotherwise\text{Verify}(\sigma, H_{\text{block}}, \text{PubKey}_{\text{signer}}) = \begin{cases} \text{true} & \text{if } \sigma = \text{Sign}(H_{\text{block}}, \text{PrivKey}_{\text{signer}}) \\ \text{false} & \text{otherwise} \end{cases} where:
  • σ\sigma = 65-byte ECDSA signature (R, S, V)
  • HblockH_{\text{block}} = Keccak256 hash of block header (excluding signature)

Block Production Protocol

Timing Model

Block production follows strict timing constraints to prevent network partitioning: Tseal=Tparent+Delay(position)T_{\text{seal}} = T_{\text{parent}} + \text{Delay}(\text{position}) where: Delay(position)={Tblockif in-turnTblock+Tblock2if out-of-turn\text{Delay}(\text{position}) = \begin{cases} T_{\text{block}} & \text{if in-turn} \\ T_{\text{block}} + \frac{T_{\text{block}}}{2} & \text{if out-of-turn} \end{cases}

Seal Algorithm

1

Header Preparation

2

Hash Computation

Compute block hash without signature:Hunsigned=Keccak256(RLP(header[:97]))H_{\text{unsigned}} = \text{Keccak256}(\text{RLP}(\text{header}[:97]))
3

Signature Generation

Sign the hash using validator’s private key:
4

Signature Embedding

Replace placeholder with actual signature:

Anti-Split-Brain Protection

To prevent simultaneous node startup from creating chain splits, Fenine implements a random delay: ΔTstartupU(0,Tblock)\Delta T_{\text{startup}} \sim \mathcal{U}(0, T_{\text{block}}) This ensures statistical convergence to a single canonical chain within: Tconvergence=O(logn)T_{\text{convergence}} = \mathcal{O}(\log n) blocks, where n=Vn = |\mathcal{V}|.

Snapshot System

Snapshot Data Structure

Snapshots cache validator sets to avoid repeated contract reads:

Snapshot Evolution

Snapshots evolve through the chain via the apply() function: Sn+1=apply(Sn,Bn+1)\mathcal{S}_{n+1} = \text{apply}(\mathcal{S}_n, B_{n+1}) where: apply(S,B)={loadFromContract(B)if BmodEperiod=0SSigner(B)otherwise\text{apply}(\mathcal{S}, B) = \begin{cases} \text{loadFromContract}(B) & \text{if } B \bmod E_{\text{period}} = 0 \\ \mathcal{S} \cup \\{\text{Signer}(B)\\} & \text{otherwise} \end{cases}

Snapshot Persistence

Snapshots are persisted to disk at checkpoint intervals to enable fast sync: Checkpoint(n)    nmod1024=0\text{Checkpoint}(n) \iff n \bmod 1024 = 0 Database key schema:

LRU Caching Strategy

In-memory caching follows a dual-LRU architecture: Cache hit rate analysis: Phit=1(VCcapacity)kP_{\text{hit}} = 1 - \left(\frac{|\mathcal{V}|}{C_{\text{capacity}}}\right)^k For V=101|\mathcal{V}| = 101 and C=128C = 128, hit rate exceeds 99% for k>2k > 2 lookbacks.

System Transaction Mechanism

Epoch Boundary Protocol

At every epoch block (nmod200=0n \bmod 200 = 0), three system transactions execute atomically:
1

updateValidatorCandidates()

Purpose: Refresh active validator set from contract stateFunction Selector: 0x3c1cc290Effect: Synchronizes Vconsensus\mathcal{V}_{\text{consensus}} with Vcontract\mathcal{V}_{\text{contract}}Vn+1FenineSystem.activeValidatorSet\mathcal{V}_{n+1} \leftarrow \text{FenineSystem.activeValidatorSet}
2

distributeBlockReward(uint256)

Purpose: Distribute epoch rewards to validatorsFunction Selector: 0x9a2e5597Reward Calculation:Ωepoch=Rblock×Eperiod=1×200=200 FEN\Omega_{\text{epoch}} = R_{\text{block}} \times E_{\text{period}} = 1 \times 200 = 200 \text{ FEN}Distribution:distribute(Ω)={splitAmongValidators(Ω,V)if V>0sendToTreasury(Ω)if V=0\text{distribute}(\Omega) = \begin{cases} \text{splitAmongValidators}(\Omega, \mathcal{V}) & \text{if } |\mathcal{V}| > 0 \\ \text{sendToTreasury}(\Omega) & \text{if } |\mathcal{V}| = 0 \end{cases}
3

syncRewardState()

Purpose: Activate pending reward changesFunction Selector: 0x4d73a62aState Transition:RactiveRpending at epoch EactivationR_{\text{active}} \leftarrow R_{\text{pending}} \text{ at epoch } E_{\text{activation}}

System Transaction Properties

System transactions have special characteristics:
Validator EOAs should maintain zero balance to prevent accidental user transactions. System TXs are exempt from balance checks.

Header Verification Rules

Comprehensive Verification

The verifyHeader() function enforces 12 consensus rules:
Huncle=?Keccak256(RLP([]))H_{\text{uncle}} \stackrel{?}{=} \text{Keccak256}(\text{RLP}([]))
Coinbase=?EcRecover(σ,Hblock)\text{Coinbase} \stackrel{?}{=} \text{EcRecover}(\sigma, H_{\text{block}})
Tn>Tn1T_n > T_{n-1}
TnTn1+TblockT_n \geq T_{n-1} + T_{\text{block}}
Nonce must be 0x0000000000000000 (no voting in Fenine).
ExtraData32+65=97 bytes|\text{ExtraData}| \geq 32 + 65 = 97 \text{ bytes}
Must be zero (no PoW mining).
Dn={2if in-turn1if out-of-turnD_n = \begin{cases} 2 & \text{if in-turn} \\ 1 & \text{if out-of-turn} \end{cases}
ECDSA signature must be valid.
Signer(Bn)Vn\text{Signer}(B_n) \in \mathcal{V}_n
Prevents spam by enforcing minimum gap:BcurrentBlast_signedV2+1B_{\text{current}} - B_{\text{last\_signed}} \geq \left\lfloor \frac{|\mathcal{V}|}{2} \right\rfloor + 1
Gas limit may only change by ±1/1024 per block:GnGn1<Gn11024\left| G_{n} - G_{n-1} \right| < \frac{G_{n-1}}{1024}

Block Difficulty Calculation

CalcDifficulty Algorithm

In-Turn Status Determination

InTurn(n,s)    V[nmodV]=s\text{InTurn}(n, s) \iff \mathcal{V}\left[n \bmod |\mathcal{V}|\right] = s where:
  • nn = Block number
  • ss = Signer address
  • V\mathcal{V} = Sorted validator set (lexicographic order)

Lexicographic Ordering

Validators are sorted by address to ensure determinism:

Finality Semantics

Probabilistic Finality

Fenine provides probabilistic finality based on confirmation depth: Pfinality(k)=1(12)kP_{\text{finality}}(k) = 1 - \left(\frac{1}{2}\right)^k where kk is the number of confirmations.
Recommended Confirmations:
  • Small transactions: 3 blocks (9s)
  • Medium value: 6 blocks (18s)
  • High value: 12 blocks (36s)

Economic Finality

For transactions exceeding VtxV_{\text{tx}}, required confirmations: ksafe=log2(VtxVstake)k_{\text{safe}} = \left\lceil \log_2\left(\frac{V_{\text{tx}}}{V_{\text{stake}}}\right) \right\rceil where VstakeV_{\text{stake}} is the minimum validator stake (10,000 FEN).

Chain Reorganization Handling

Fork Choice Rule

During competing chains, selection follows: Chaincanonical=argmaxCleftBCD(B),  Cright\text{Chain}_{\text{canonical}} = \arg\max_{\mathcal{C}} \\left\\{ \sum_{B \in \mathcal{C}} D(B), \; |\mathcal{C}| \\right\\} where:
  1. Prefer chain with higher cumulative difficulty
  2. Tie-break by chain length
  3. Tie-break by lexicographically smallest block hash

Reorg Protection

Maximum reorganization depth is bounded by: Reorgmax=min(128,Eperiod)\text{Reorg}_{\text{max}} = \min(128, E_{\text{period}}) Beyond 128 blocks, snapshots are checkpointed and considered immutable.

Performance Metrics

Block Production Latency

End-to-end block production time decomposition: Ttotal=Texec+Tseal+TpropagateT_{\text{total}} = T_{\text{exec}} + T_{\text{seal}} + T_{\text{propagate}} Typical values:

Throughput Characteristics

Theoretical limits: TPStransfer=30,000,00021,000×3476 TPSTPSERC20=30,000,00065,000×3154 TPSTPSswap=30,000,000150,000×367 TPS\begin{align*} \text{TPS}_{\text{transfer}} &= \frac{30,000,000}{21,000 \times 3} \approx 476 \text{ TPS} \\ \text{TPS}_{\text{ERC20}} &= \frac{30,000,000}{65,000 \times 3} \approx 154 \text{ TPS} \\ \text{TPS}_{\text{swap}} &= \frac{30,000,000}{150,000 \times 3} \approx 67 \text{ TPS} \end{align*}

Consensus Safety Guarantees

Byzantine Fault Tolerance

Safety threshold: f<n2f < \frac{n}{2} where:
  • ff = Number of Byzantine validators
  • nn = Total active validators

Liveness Guarantee

Chain progresses if: Vhonest1|\mathcal{V}_{\text{honest}}| \geq 1 Even a single honest validator ensures liveness (though centralization risk).

Censorship Resistance

Transaction inclusion probability after kk blocks: Pinclusion(k)=1(fn)kP_{\text{inclusion}}(k) = 1 - \left(\frac{f}{n}\right)^k For f/n=0.3f/n = 0.3 (30% adversarial):
  • k=1k=1: 70% chance
  • k=3k=3: 97.3% chance
  • k=5k=5: 99.76% chance

System Contracts

FenineSystem contract specification

FPoS Economics

Validator selection and rewards

Security Model

Attack vectors and mitigations

Network Parameters

Configurable consensus constants