Skip to content

Running-head fork choice: heaviest-ParentWeight + periodic re-quorum (not boot-only) #79

Description

@Reiers

Problem

The boot-time anchor runs a strong defense (5-of-N independent-source quorum on the F3-finalized tipset, see chain/bootstrap), but it runs once at install / boot. Past the anchor, the running head is followed over gossipsub by net/blockingest, which advances head on height-fence + parent-linkage only — no re-quorum, no weight comparison.

This is the gap zenground0 (FilOz) raised in the fil-curio-dev thread (2026-06-30): an attacker who eclipses the gossip peer table can feed parent-linked, height-advancing blocks and walk a node onto a valid-but-non-canonical fork on the unfinalized tip. Content addressing does not catch it — the attacker's blocks hash fine, they're just not the canonical chain.

Proposed fix (pure-Go, no ffi, no one-binary-constraint impact)

  1. Heaviest-ParentWeight fork choice on the running head. Replace the bare "height advanced" head-advance rule in net/blockingest with Filecoin's actual fork-choice rule: only adopt a competing head if it has strictly greater ParentWeight. The weight logic already exists in chain/anchorverify (boot path) — lift/extend it to the live head. ParentWeight is a header field, so this needs no proof verification, no ffi.
  2. Periodic re-quorum of the live head. Re-run the multi-source agreement check (chain/bootstrap quorum) against the running head on a cadence (not just at boot), so the live head must keep clearing N-independent-source agreement. An attacker then has to eclipse the gossip mesh and simultaneously control ≥quorum of the independent sources.

What this does NOT do

Does not close the unfinalized-tip fork problem against a powerful adversary with real storage power genuinely splitting consensus. That is a finality problem; the answer is F3 (separate, network-layer). This issue is strictly about raising the cost of the cheap peer-table eclipse without touching Lantern's no-CGo / no-ffi / one-binary laws.

Acceptance

  • net/blockingest adopts a competing head only on strictly-greater ParentWeight (with parent-linkage + height still enforced)
  • Live head periodically re-verified against multi-source quorum; loud warn + no-adopt on disagreement
  • Unit tests: competing-fork-with-lower-weight rejected; higher-weight adopted; quorum-disagreement on live head warns and holds

Context: fil-curio-dev thread w/ zenground0, 2026-06-30. Related: #76, security-anchor design in chain/anchorverify.

Metadata

Metadata

Assignees

No one assigned

    Labels

    architectureTrust model / swarm designp1High prioritysecuritySecurity finding or hardening

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions