Skip to content

vtxo+oor: multi-parent lineage gate + OOR-received registration (C7) - #819

Closed
ellemouton wants to merge 2 commits into
c6-round-canonicality-gatefrom
c7-oor-canonicality-gate
Closed

vtxo+oor: multi-parent lineage gate + OOR-received registration (C7)#819
ellemouton wants to merge 2 commits into
c6-round-canonicality-gatefrom
c7-oor-canonicality-gate

Conversation

@ellemouton

Copy link
Copy Markdown
Member

C7 — OOR-received VTXO multi-parent lineage governance

Part of the reorg-safety epic (lightninglabs/darepo#454). Stacked on C6 (#818).
Unlocks acceptance F4/F5 (OOR-received VTXO reorg → limbo → usable / ancestor
conflict → unavailable).

C7a — gate the full multi-parent lineage (vtxo)

The C5 admission gate read only a candidate's direct commitment txid, leaving
cross-commitment OOR VTXOs (which descend from more than one batch) ungoverned
by their ancestor batches. lineageCommitmentTxids now collects the direct
commitment txid plus every distinct Descriptor.Ancestry[].CommitmentTxID
(deduped, zero-skipped), and LineageBlocked takes the worst state across all
of them — so a multi-input OOR VTXO is excluded from selection if ANY
contributing batch is reorged out or conflict-invalidated. Completes the
multi-parent follow-up C5 left open.

C7b — register received lineage at OOR receive (oor)

The receiver did not participate in the ancestor rounds, so its manager has no
record of those batches and the gate would stay permissive. At OOR
materialization the session actor now registers every commitment batch in the
received VTXOs' lineage with the BatchCanonicalityManager (best-effort,
post-commit, gated behind an optional SessionActorConfig.BatchCanonicality
ref — None = dormant). The batch-output pkScript comes from each ancestry
fragment's tree root (BatchOutput), so confirmation/reorg detection works on
script-filtering light-client receivers (Esplora/Neutrino).

ConsumedInputs are intentionally empty (the receiver doesn't hold the ancestor
commitment txs' inputs at this seam): a reorg-out of an ancestor batch is still
detected via its confirmation watch and marks the VTXO limbo (F4); per-input
double-spend watches and per-fragment CSV delta are documented follow-ups.

Activation (darepod) — deferred

Like C5/C6, the gate ships dormant. Constructing/starting the canonicality
manager and threading the store/ref to the vtxo + round + oor actors is the
shared integration step (ties #795 + #796 + C6/C7/C8) and needs the daemon
harness to validate.

Tests

Unit tests: lineageCommitmentTxids (dedup/zero-skip/direct-only) and a
multi-parent selection case; OOR lineage registration (distinct/shared
ancestors with dependents, dormant no-op, incomplete-fragment skip). F4/F5 land
as client systests in the acceptance pass.

🤖 Generated with Claude Code

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements full multi-parent ancestry gating for OOR-received VTXOs, ensuring that a VTXO is excluded from selection if any of its ancestor commitment batches are reorged-out or invalidated. It introduces lineage registration in the session actor and updates the VTXO manager to gate on the complete lineage. The review feedback highlights two potential nil pointer dereference risks: one in registerLineageBatches when iterating over descriptors that could be nil, and another in lineageCommitmentTxids where a defensive nil check would improve robustness.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +806 to +807
for _, desc := range descs {
for i := range desc.Ancestry {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The slice descs can contain nil elements (as handled in queueVTXOsReceived via if desc == nil { continue }). If a nil descriptor is present, referencing desc.Ancestry will cause a nil pointer dereference panic. We should add a nil check for desc before accessing its fields.

	for _, desc := range descs {
		if desc == nil {
			continue
		}
		for i := range desc.Ancestry {

Comment thread vtxo/manager.go
Comment on lines +1174 to +1175
func lineageCommitmentTxids(desc *Descriptor) []chainhash.Hash {
seen := make(map[chainhash.Hash]struct{}, len(desc.Ancestry)+1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To make lineageCommitmentTxids more robust and prevent potential nil pointer dereference panics if called with a nil descriptor elsewhere, we should add a defensive nil check at the beginning of the function.

func lineageCommitmentTxids(desc *Descriptor) []chainhash.Hash {
	if desc == nil {
		return nil
	}
	seen := make(map[chainhash.Hash]struct{}, len(desc.Ancestry)+1)

@ellemouton
ellemouton force-pushed the c6-round-canonicality-gate branch from 232a141 to a630201 Compare June 29, 2026 20:10
@ellemouton
ellemouton force-pushed the c7-oor-canonicality-gate branch from 73e1427 to 1872076 Compare June 29, 2026 20:10
@ellemouton
ellemouton force-pushed the c6-round-canonicality-gate branch from a630201 to 7f8df41 Compare July 1, 2026 16:16
@ellemouton
ellemouton force-pushed the c7-oor-canonicality-gate branch from 1872076 to c2c0fa1 Compare July 1, 2026 16:16
@levmi levmi added oor P1 Priority 1 — high reorg safety Fund-safety: stuck, lost, or mis-counted funds vtxo labels Jul 6, 2026
Squashed for the btcd v2 port. The round registers its round-born
batch + consumed inputs with the canonicality manager, and gates
pre-commitment progression on consumed-input canonicality (finality
gate kept as interim safety).
@ellemouton
ellemouton force-pushed the c6-round-canonicality-gate branch from 7f8df41 to b317f3c Compare July 8, 2026 21:09
@ellemouton
ellemouton force-pushed the c7-oor-canonicality-gate branch from c2c0fa1 to 5d77198 Compare July 8, 2026 21:11
Squashed for the btcd v2 port. OOR registers every batch parent in the
received-VTXO proof lineage with the canonicality manager, and the
VTXO gate combines availability across all ancestry parents
(worst-state AND) for multi-parent OOR VTXOs.
@ellemouton

Copy link
Copy Markdown
Member Author

Superseded by #896 as part of condensing the reorg-safety client stack (epic lightninglabs/darepo#454) from 12 PRs into 3. The commits are carried over unchanged; see #896. Branch retained as a backup.

@ellemouton ellemouton closed this Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

oor P1 Priority 1 — high reorg safety Fund-safety: stuck, lost, or mis-counted funds vtxo

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants