Consensus

Two-phase ORV finality — every block finalizes at ≥67% of delegated XE weight.


Every block reaches a finalized state via representative voting — not just blocks that fork. Each chain position (account + Previous hash) runs an election; a fork just means the election has more than one candidate.

Two-Phase Voting

PhaseVote kindBehaviour
1. ConvergeFinal = falseMutable. A representative votes for its preferred candidate (lowest hash among candidates it holds) and may re-vote as its preference shifts. Converge votes establish a leader; they never finalize anything.
2. FinalFinal = trueIrrevocable. Once a candidate has a visible ≥67% converge supermajority, the representative writes a write-once commit-lock for the position and casts a final vote for the locked hash. Only final votes finalize.

A block finalizes when representatives holding ≥67% of delegated XE weight have final-voted it:

blockWeight * 100 >= totalWeight * 67

Uses big.Int arithmetic. Deterministic preference: lexicographically lowest hash.

The commit-lock is never deleted — not on resolution, rollback, or restart — so a representative is structurally unable to final-vote two hashes at one position. Adversarial timing can delay finalization, never double it. The 67% quorum lock path additionally waits out a 3-second candidate-stability window after the last new candidate appears, so a transient supermajority on a higher-hash sibling cannot grab the lock.

Delegation

  • Voting weight is the delegated XE balance, in micro-XE. XUSD confers no weight: XUSD is mintable (faucet/bridge), and mintable supply must not mint consensus weight.
  • Weight snapshots frozen at conflict detection time
  • Persistent via DelegationStore interface
  • sync.RWMutex for concurrency

Dependency Gating

A representative withholds its own vote for a block whose dependencies are not yet finalized locally — its Previous, plus the cross-account Source for receives and lease lifecycle blocks. It still tallies incoming votes, so a lagging node never deadlocks an election.

The Finality Wall

  • Each account has a final_height watermark — the height of its highest finalized block. The ledger refuses to replace any block at or below it.
  • Spendable balance counts only finalized inflows; an account with nothing finalized has no spendable balance.

Fallback Resolution

If 67% is unreachable (non-voting reps inflate the total), then after 10 seconds only the lowest-hash final-voted candidate may finalize, and only if it holds a strict majority (>50%) of total delegated weight in final votes. Otherwise the node withholds rather than risk divergent finalization — since each representative is commit-locked to one hash per position, at most one candidate can ever hold a strict majority.

Conflict Detection

  • A conflict = two blocks with the same Previous hash (equivocation)
  • Max 10 block hashes per conflict
  • Conflicting blocks placed in staging
  • Conflict callback fires on detection and whenever a new sibling body is staged for an existing conflict; only gossip re-deliveries of an already-staged body are suppressed

Voting

  • Per-conflict mutex prevents double-voting
  • Vote buffering for votes arriving before local conflict detection (max 10 per conflict)
  • ±5 minute timestamp window
  • Vote wire format: 204 bytes (138 signing bytes + 2 length + 64 signature) — see Binary Encoding

Quorum Manager

  • Stale conflict sweep every 15 seconds
  • Block status: Pending (0), Finalized (1), Rejected (2)
  • Block swap mechanism for staged winners