Skip to content

feat(#96): FRC-0089 EC finality calculator (observed-data finality)#105

Merged
Reiers merged 1 commit into
mainfrom
feat/96-ecfinality
Jul 1, 2026
Merged

feat(#96): FRC-0089 EC finality calculator (observed-data finality)#105
Reiers merged 1 commit into
mainfrom
feat/96-ecfinality

Conversation

@Reiers

@Reiers Reiers commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Port of lotus chain/ecfinality with the math verbatim: all Python-reference test vectors pass unchanged.

What

Verification

  • Reference vectors (905-epoch Python-generated chain, depths 5-100) exact-match.
  • Cache tests: healthy window, shallow-window honesty, null-round counting, recompute-only-on-head-change, no-head error.
  • build/vet/gofmt clean; cmd/lantern + chain tests green. (pkg/daemon suite locally blocked by the live dev daemon holding :1234, known environmental flake; CI is the clean check.)

New dep: github.com/rvagg/go-skellam-pmf v0.0.2 (pure Go, tiny, same as lotus).

Closes #96.

…ithout F3

Port of lotus chain/ecfinality (itself a Go port of the FRC-0089 Python
reference). Math kept verbatim so the lotus/Python test vectors apply
unchanged - all reference vectors pass.

What it gives Lantern: an upper bound on reorg probability computed from
OBSERVED block counts per epoch, with no external trust. Healthy chain
(~5 blk/epoch) meets 2^-30 around depth ~30 (~15 min) instead of the
static worst-case 900 epochs. This quantifies how deep a tip-range
eclipse could plausibly reorg us (head-trust epic #100), and becomes the
retention-depth input for #92 and the ec-finalized half of the v2
'finalized'/'safe' selector semantics (#99).

Lantern adaptations (cache.go, new):
- HeaderSource interface over chain/header/store (Head + GetTipSet)
- Windowed-store aware: the walk stops gracefully where history runs
  out; Status reports the achieved WindowEpochs, and a window below
  MinWindow (30 epochs) reports 'not computable' (-1) instead of an
  over-confident number. Nodes with a deeper tail (#91) converge to the
  exact reference behavior.
- On-demand + cached per head tipset: an idle node pays nothing; the
  dashboard poll is the only thing that pays the Skellam cost.

Wiring:
- cmd/lantern: dashboard dev page gets an 'EC finality (FRC-0089)' card
  (threshold depth / ec-finalized epoch / observed window / recomputes)
  plus the previously-invisible held_uncorrob / held_diverged /
  rejected_lighter ingestor counters.
- pkg/daemon: Daemon.ECFinality() accessor for embedded consumers.
- TRUST-MODEL.md 2.7: computed bound, not a proof; F3 precedence;
  finalized = max(ec, f3).

New dep: github.com/rvagg/go-skellam-pmf v0.0.2 (tiny, pure Go, same
dep lotus uses).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lift FRC-0089 EC finality calculator (lotus chain/ecfinality): observed-data finality without F3

1 participant