Documentation
¶
Overview ¶
Package ecfinality implements the FRC-0089 EC finality calculator (#96).
The calculator computes an upper bound on the probability that a confirmed tipset could be reorganized out of the canonical chain by an adversarial fork, using OBSERVED chain data (block counts per epoch). Under healthy network conditions (~5 blocks/epoch), the 2^-30 finality guarantee (roughly one-in-a-billion chance of reorg) is typically achieved within ~30 epochs (~15 minutes), compared to the static 900-epoch (~7.5 hour) EC finality assumption which is based on worst-case conditions.
Why Lantern wants this: F3 gives BLS-verified finality certificates, but where F3 finality is not available at the tip (or not live on a network), the fallback is the static 900-epoch worst case. FRC-0089 gives a principled, locally-computed finality depth with no external trust: it quantifies how deep a tip-range eclipse could plausibly reorg us. It feeds the head-trust story (#100), retention pruning depth (#92), and the v2 "finalized"/"safe" selector semantics (#99: finalized = max(ec-finalized, F3-finalized)).
This is a port of lotus chain/ecfinality (itself a Go port of the FRC-0089 Python reference), adapted to Lantern's header store. The math is kept verbatim so the lotus/Python test vectors apply unchanged.
Reference: https://github.com/filecoin-project/FIPs/blob/master/FRCs/frc-0089.md Python reference: https://github.com/consensus-shipyard/ec-finality-calculator
Index ¶
Constants ¶
const ( // BisectLow and BisectHigh define the search range for the bisect // algorithm that finds the epoch depth at which the finality guarantee // is met. A low bound of 3 avoids evaluating trivially shallow depths; // a high bound of 450 accommodates degraded chains that take longer to // finalize. BisectLow = 3 BisectHigh = 450 // DefaultBlocksPerEpoch is the Filecoin expected block production rate // (mainnet and calibration both target 5). DefaultBlocksPerEpoch = 5.0 // DefaultByzantineFraction is the standard Filecoin security assumption // for adversarial mining power. DefaultByzantineFraction = 0.3 // DefaultSafetyExponent is the target reorg probability as a power of 2. // 2^-30 (~one-in-a-billion) is the standard Filecoin finality guarantee. DefaultSafetyExponent = -30 )
const MinWindow = 30
MinWindow is the minimum number of epochs of observed history required before the calculator reports a threshold at all. Below this the L distribution has too little data to be meaningful, so Status reports depth -1 (not computable) rather than an over-confident number. 30 epochs (~15 min of history) is the depth at which a healthy chain typically meets 2^-30 in the first place.
Variables ¶
This section is empty.
Functions ¶
func CalcValidatorProb ¶
func CalcValidatorProb(chain []int, finality int, blocksPerEpoch float64, byzantineFraction float64, currentEpoch int, targetEpoch int) float64
CalcValidatorProb computes the upper-bound probability that a confirmed tipset could be reorganized out of the canonical chain. Verbatim port of the FRC-0089 reference (finality_calc_validator.py) via lotus.
Parameters:
- chain: block counts per epoch (index 0 = earliest epoch; null rounds appear as 0 entries)
- finality: lookback depth for the L distribution (900 on mainnet)
- blocksPerEpoch: expected blocks per epoch (5 for mainnet)
- byzantineFraction: upper bound on adversarial power fraction (e.g. 0.3)
- currentEpoch: index into chain for the current epoch
- targetEpoch: index into chain for the epoch being evaluated
func FindThresholdDepth ¶
func FindThresholdDepth(chain []int, finality int, blocksPerEpoch float64, byzantineFraction float64, guarantee float64) int
FindThresholdDepth performs a bisect search to find the shallowest depth at which the reorg probability drops below the given guarantee. Returns -1 if the guarantee is not met within the search range.
Types ¶
type Cache ¶
type Cache struct {
// contains filtered or unexported fields
}
Cache computes the FRC-0089 threshold for the current head and caches the result, recomputing only when the head changes. Computation is on-demand (dashboard/stats pulls), NOT on every head change: the cost is dominated by the Skellam PMF loops, so an idle node pays nothing. Safe for concurrent use.
func NewCache ¶
func NewCache(src HeaderSource, finality int) *Cache
NewCache builds a Cache over the given header source. finality is the lookback depth for the L distribution (900 for both mainnet and calibration).
type HeaderSource ¶
type HeaderSource interface {
Head() *ltypes.TipSet
GetTipSet(tsk ltypes.TipSetKey) (*ltypes.TipSet, error)
}
HeaderSource is the minimal store surface the cache walks. Lantern's chain/header/store.Store satisfies it.
type Status ¶
type Status struct {
// ThresholdDepth is the shallowest epoch depth at which the reorg
// probability drops below 2^-30. -1 when not met or not computable
// (degraded chain, or observed window < MinWindow).
ThresholdDepth int
// FinalizedEpoch is head.Height() - ThresholdDepth, or -1 when
// ThresholdDepth is -1.
FinalizedEpoch abi.ChainEpoch
// HeadEpoch is the head height the computation ran against.
HeadEpoch abi.ChainEpoch
// WindowEpochs is how many epochs of observed history the calculator
// actually had (honesty signal: a freshly-booted node has only its
// anchor depth until #91/#92 give it a deeper tail).
WindowEpochs int
}
Status is the resolved EC finality state for a given head.
Directories
¶
| Path | Synopsis |
|---|---|
|
tools
|
|
|
refgen
command
refgen regenerates the reference reorg-probability vectors used by TestCalcValidatorProb_PythonReference against the calculator's current implementation on the CPU it runs on.
|
refgen regenerates the reference reorg-probability vectors used by TestCalcValidatorProb_PythonReference against the calculator's current implementation on the CPU it runs on. |