Skip to content

Commit 0997ca3

Browse files
committed
supplyverifier: extract pre-commits from issuance leaves
Ensure issuance leaves fetched with the supply commitment during sync pull are also processed for pre-commits. Previously, only separately retrieved leaves were handled, which could cause missing pre-commit data and reduce verification completeness.
1 parent d1eb253 commit 0997ca3

File tree

4 files changed

+125
-14
lines changed

4 files changed

+125
-14
lines changed

universe/supplycommit/env.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,25 @@ func NewPreCommitFromProof(issuanceProof proof.Proof,
416416
}, nil
417417
}
418418

419+
// NewPreCommitFromMintEvent extracts and returns the supply pre-commitment
420+
// from the given mint event.
421+
func NewPreCommitFromMintEvent(issuanceEntry NewMintEvent,
422+
delegationKey btcec.PublicKey) (PreCommitment, error) {
423+
424+
var zero PreCommitment
425+
426+
issuanceLeaf := issuanceEntry.IssuanceProof
427+
428+
var issuanceProof proof.Proof
429+
err := issuanceProof.Decode(bytes.NewReader(issuanceLeaf.RawProof))
430+
if err != nil {
431+
return zero, fmt.Errorf("unable to decode issuance proof: %w",
432+
err)
433+
}
434+
435+
return NewPreCommitFromProof(issuanceProof, delegationKey)
436+
}
437+
419438
// TxIn returns the transaction input that corresponds to the pre-commitment.
420439
func (p *PreCommitment) TxIn() *wire.TxIn {
421440
return &wire.TxIn{

universe/supplyverifier/manager.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -551,13 +551,12 @@ func (m *Manager) InsertSupplyCommit(ctx context.Context,
551551
commitment.CommitPoint().String())
552552

553553
// Fetch all known unspent pre-commitment outputs for the asset group.
554-
unspentPreCommits, err :=
555-
m.cfg.SupplyCommitView.UnspentPrecommits(
556-
ctx, assetSpec, false,
557-
).Unpack()
554+
preCommits, err := FetchPreCommits(ctx,
555+
m.cfg.AssetLookup, m.cfg.SupplyCommitView, assetSpec,
556+
commitment, leaves.IssuanceLeafEntries,
557+
)
558558
if err != nil {
559-
return fmt.Errorf("unable to fetch unspent pre-commitments: %w",
560-
err)
559+
return fmt.Errorf("unable to fetch pre-commitments: %w", err)
561560
}
562561

563562
// First, we verify the supply commitment to ensure it is valid and
@@ -578,15 +577,15 @@ func (m *Manager) InsertSupplyCommit(ctx context.Context,
578577
}
579578

580579
err = verifier.VerifyCommit(
581-
ctx, assetSpec, commitment, leaves, unspentPreCommits,
580+
ctx, assetSpec, commitment, leaves, preCommits,
582581
)
583582
if err != nil {
584583
return fmt.Errorf("supply commitment verification failed: %w",
585584
err)
586585
}
587586

588587
return m.cfg.SupplyCommitView.InsertSupplyCommit(
589-
ctx, assetSpec, commitment, leaves, unspentPreCommits,
588+
ctx, assetSpec, commitment, leaves, preCommits,
590589
)
591590
}
592591

universe/supplyverifier/transitions.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,11 @@ func (s *SyncVerifyState) ProcessEvent(event Event,
204204

205205
// Fetch all known unspent pre-commitment outputs for the asset
206206
// group.
207-
unspentPreCommits, err :=
208-
env.SupplyCommitView.UnspentPrecommits(
209-
ctx, env.AssetSpec, false,
210-
).Unpack()
207+
mintEvents := supplyCommit.SupplyLeaves.IssuanceLeafEntries
208+
preCommits, err := FetchPreCommits(
209+
ctx, env.AssetLookup, env.SupplyCommitView,
210+
env.AssetSpec, supplyCommit.RootCommitment, mintEvents,
211+
)
211212
if err != nil {
212213
return nil, fmt.Errorf("unable to fetch unspent "+
213214
"pre-commitments: %w", err)
@@ -231,7 +232,7 @@ func (s *SyncVerifyState) ProcessEvent(event Event,
231232

232233
err = verifier.VerifyCommit(
233234
ctx, env.AssetSpec, supplyCommit.RootCommitment,
234-
supplyCommit.SupplyLeaves, unspentPreCommits,
235+
supplyCommit.SupplyLeaves, preCommits,
235236
)
236237
if err != nil {
237238
return nil, fmt.Errorf("unable to verify supply "+
@@ -243,7 +244,7 @@ func (s *SyncVerifyState) ProcessEvent(event Event,
243244
// Store the verified commitment.
244245
err = env.SupplyCommitView.InsertSupplyCommit(
245246
ctx, env.AssetSpec, supplyCommit.RootCommitment,
246-
supplyCommit.SupplyLeaves, unspentPreCommits,
247+
supplyCommit.SupplyLeaves, preCommits,
247248
)
248249
if err != nil {
249250
return nil, fmt.Errorf("unable to store supply "+

universe/supplyverifier/util.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/btcsuite/btcd/btcec/v2"
88
"github.com/lightninglabs/taproot-assets/asset"
9+
"github.com/lightninglabs/taproot-assets/fn"
910
"github.com/lightninglabs/taproot-assets/universe/supplycommit"
1011
)
1112

@@ -33,3 +34,94 @@ func FetchDelegationKey(ctx context.Context,
3334

3435
return delegationKey, nil
3536
}
37+
38+
// FetchPreCommits returns all pre-commitment outputs expected to be spent by
39+
// the anchoring transaction of the specified supply commitment.
40+
func FetchPreCommits(ctx context.Context,
41+
assetLookup supplycommit.AssetLookup, supplyCommitView SupplyCommitView,
42+
assetSpec asset.Specifier, supplyCommit supplycommit.RootCommitment,
43+
mintEvents []supplycommit.NewMintEvent) ([]supplycommit.PreCommitment,
44+
error) {
45+
46+
// Get supply commit block height. This will be used to filter out any
47+
// pre-commitments that are above the supply commitment height.
48+
chainCommit, err := supplyCommit.CommitmentBlock.UnwrapOrErr(
49+
fmt.Errorf("commitment block missing"),
50+
)
51+
if err != nil {
52+
return nil, fmt.Errorf("unable to extract supply commitment "+
53+
"chain block: %w", err)
54+
}
55+
supplyCommitBlockHeight := chainCommit.Height
56+
57+
// Fetch all known unspent pre-commitment outputs for the asset
58+
// group.
59+
preCommits, err := supplyCommitView.UnspentPrecommits(
60+
ctx, assetSpec, false,
61+
).Unpack()
62+
if err != nil {
63+
return nil, fmt.Errorf("unable to fetch unspent "+
64+
"pre-commitments: %w", err)
65+
}
66+
67+
// Filter out any pre-commitments that are above the supply commitment
68+
// height. These can't be spent by the current supply commitment.
69+
filteredPreCommits := make(
70+
[]supplycommit.PreCommitment, 0, len(preCommits),
71+
)
72+
for _, pc := range preCommits {
73+
if pc.BlockHeight <= supplyCommitBlockHeight {
74+
filteredPreCommits = append(filteredPreCommits, pc)
75+
}
76+
}
77+
preCommits = filteredPreCommits
78+
79+
// If there are no mint events, then we can return early here because
80+
// there won't be any new pre-commitments to consider.
81+
if len(mintEvents) == 0 {
82+
return preCommits, nil
83+
}
84+
85+
// We'll need the delegation key to extract any new pre-commitments from
86+
// the mint events.
87+
delegationKey, err := FetchDelegationKey(
88+
ctx, assetLookup, assetSpec,
89+
)
90+
if err != nil {
91+
return nil, fmt.Errorf("unable to fetch delegation key: %w",
92+
err)
93+
}
94+
95+
// Create a set of outpoints from all known pre-commits. This will be
96+
// used to prevent duplicates when adding new pre-commits from the mint
97+
// events.
98+
preCommitOutPoints := fn.NewSet(fn.Map(
99+
preCommits, func(preCommit supplycommit.PreCommitment) string {
100+
return preCommit.OutPoint().String()
101+
},
102+
)...)
103+
104+
// Collect pre-commitments from the mint events that we haven't already
105+
// seen.
106+
for idx := range mintEvents {
107+
mintEvent := mintEvents[idx]
108+
109+
preCommit, err := supplycommit.NewPreCommitFromMintEvent(
110+
mintEvent, delegationKey,
111+
)
112+
if err != nil {
113+
return nil, fmt.Errorf("unable to extract "+
114+
"pre-commitment from mint event: %w", err)
115+
}
116+
117+
// If we already have this pre-commitment, then skip it.
118+
op := preCommit.OutPoint()
119+
if preCommitOutPoints.Contains(op.String()) {
120+
continue
121+
}
122+
123+
preCommits = append(preCommits, preCommit)
124+
}
125+
126+
return preCommits, nil
127+
}

0 commit comments

Comments
 (0)