vtxo+oor: multi-parent lineage gate + OOR-received registration (C7) - #819
vtxo+oor: multi-parent lineage gate + OOR-received registration (C7)#819ellemouton wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
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.
| for _, desc := range descs { | ||
| for i := range desc.Ancestry { |
There was a problem hiding this comment.
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 {| func lineageCommitmentTxids(desc *Descriptor) []chainhash.Hash { | ||
| seen := make(map[chainhash.Hash]struct{}, len(desc.Ancestry)+1) |
There was a problem hiding this comment.
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)232a141 to
a630201
Compare
73e1427 to
1872076
Compare
a630201 to
7f8df41
Compare
1872076 to
c2c0fa1
Compare
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).
7f8df41 to
b317f3c
Compare
c2c0fa1 to
5d77198
Compare
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.
b317f3c to
28576e7
Compare
5d77198 to
6579e95
Compare
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.
lineageCommitmentTxidsnow collects the directcommitment txid plus every distinct
Descriptor.Ancestry[].CommitmentTxID(deduped, zero-skipped), and
LineageBlockedtakes the worst state across allof 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.BatchCanonicalityref —
None= dormant). The batch-output pkScript comes from each ancestryfragment's tree root (
BatchOutput), so confirmation/reorg detection works onscript-filtering light-client receivers (Esplora/Neutrino).
ConsumedInputsare intentionally empty (the receiver doesn't hold the ancestorcommitment 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 amulti-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