Skip to content

Commit 8eb6c53

Browse files
authored
Merge pull request #1093 from lightninglabs/proof-sync
[universe]: fix proof sync for large asset minting batches
2 parents e893dee + df214e0 commit 8eb6c53

File tree

2 files changed

+81
-20
lines changed

2 files changed

+81
-20
lines changed

universe/base.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,13 @@ func (a *Archive) verifyIssuanceProof(ctx context.Context, id Identifier,
349349
a.cfg.MerkleVerifier, a.cfg.GroupVerifier, lookup,
350350
)
351351
if err != nil {
352-
return nil, fmt.Errorf("unable to verify proof: %w", err)
352+
var skBytes []byte
353+
if key.ScriptKey != nil {
354+
skBytes = key.ScriptKey.PubKey.SerializeCompressed()
355+
}
356+
return nil, fmt.Errorf("unable to verify proof (%v, "+
357+
"outpoint=%v, scriptKey=%x): %w", id.StringForLog(),
358+
key.OutPoint.String(), skBytes, err)
353359
}
354360

355361
newAsset := assetSnapshot.Asset
@@ -403,10 +409,10 @@ func (a *Archive) UpsertProofLeafBatch(ctx context.Context,
403409
log.Infof("Verifying %d new proofs for insertion into Universe",
404410
len(items))
405411

406-
// Issuances that also create an asset group, group anchors, must be
407-
// verified and stored before any issuances that may be reissuances into
408-
// the same asset group. This is required for proper verification of
409-
// reissuances, which may be in this batch.
412+
// Issuance proofs that also create an asset group (a.k.a. group
413+
// anchors) must be verified and stored before any issuance proofs that
414+
// may be re-issuances into the same asset group. This is required for
415+
// proper verification of re-issuances, which may be in this batch.
410416
var anchorItems []*Item
411417
nonAnchorItems := make([]*Item, 0, len(items))
412418
assetProofs := make(map[LeafKey]*proof.Proof)
@@ -476,7 +482,8 @@ func (a *Archive) UpsertProofLeafBatch(ctx context.Context,
476482
}
477483

478484
assetSnapshot, err := a.verifyIssuanceProof(
479-
ctx, i.ID, i.Key, assetProof, prevAssets,
485+
ctx, i.ID, i.Key, assetProof,
486+
prevAssets,
480487
)
481488
if err != nil {
482489
return err
@@ -488,8 +495,8 @@ func (a *Archive) UpsertProofLeafBatch(ctx context.Context,
488495
},
489496
)
490497
if err != nil {
491-
return fmt.Errorf("unable to verify issuance proofs: "+
492-
"%w", err)
498+
return fmt.Errorf("unable to batch verify issuance "+
499+
"proofs: %w", err)
493500
}
494501

495502
return nil

universe/syncer.go

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -272,21 +272,10 @@ func (s *SimpleSyncer) syncRoot(ctx context.Context, remoteRoot Root,
272272
// local registrar as they're fetched.
273273
var (
274274
fetchedLeaves = make(chan *Item, len(keysToFetch))
275-
newLeafProofs []*Leaf
275+
newLeafProofs = make([]*Leaf, 0, len(keysToFetch))
276276
batchSyncEG errgroup.Group
277277
)
278278

279-
// We use an error group to simply the error handling of a goroutine.
280-
// This goroutine will handle reading in batches of new leaves to
281-
// insert into the DB. We'll fee the output of the goroutines below
282-
// into the input fetchedLeaves channel.
283-
batchSyncEG.Go(func() error {
284-
newLeafProofs, err = s.batchStreamNewItems(
285-
ctx, uniID, fetchedLeaves, len(keysToFetch),
286-
)
287-
return err
288-
})
289-
290279
// If this is a transfer tree, then we'll use these channels to sort
291280
// the contents before sending to the batch writer.
292281
isIssuanceTree := remoteRoot.ID.ProofType == ProofTypeIssuance
@@ -319,6 +308,37 @@ func (s *SimpleSyncer) syncRoot(ctx context.Context, remoteRoot Root,
319308
// Otherwise, we'll another step to the pipeline below
320309
// for sorting.
321310
if isIssuanceTree {
311+
// If this is an issuance proof _AND_ it has a
312+
// group key reveal, then we'll need to import
313+
// it right away. Otherwise, all other issuance
314+
// proofs in the batch might fail, as they might
315+
// reference the group key in this proof's
316+
// group key reveal.
317+
reg := s.cfg.LocalRegistrar
318+
if hasGroupKeyReveal(leafProof.Leaf.RawProof) {
319+
log.Debugf("UniverseRoot(%v): "+
320+
"Inserting new group key "+
321+
"reveal leaf", uniID.String())
322+
_, err = reg.UpsertProofLeaf(
323+
ctx, uniID, key, leafProof.Leaf,
324+
)
325+
if err != nil {
326+
return fmt.Errorf("unable to "+
327+
"register group "+
328+
"anchor proof: %w", err)
329+
}
330+
331+
// Track this manually inserted proof in
332+
// the result.
333+
newLeafProofs = append(
334+
newLeafProofs, leafProof.Leaf,
335+
)
336+
337+
// No need to batch this further, we've
338+
// already inserted it.
339+
return nil
340+
}
341+
322342
fetchedLeaves <- &Item{
323343
ID: uniID,
324344
Key: key,
@@ -338,6 +358,23 @@ func (s *SimpleSyncer) syncRoot(ctx context.Context, remoteRoot Root,
338358
return err
339359
}
340360

361+
// We use an error group to simply the error handling of a goroutine.
362+
// This goroutine will handle reading in batches of new leaves to
363+
// insert into the DB. We'll fee the output of the goroutines below
364+
// into the input fetchedLeaves channel.
365+
batchSyncEG.Go(func() error {
366+
insertedProofs, err := s.batchStreamNewItems(
367+
ctx, uniID, fetchedLeaves, len(keysToFetch),
368+
)
369+
if err != nil {
370+
return err
371+
}
372+
373+
newLeafProofs = append(newLeafProofs, insertedProofs...)
374+
375+
return nil
376+
})
377+
341378
// If this is a transfer tree, then we'll collect all the items as we
342379
// need to sort them to ensure we can validate them in dep order.
343380
if !isIssuanceTree {
@@ -395,6 +432,23 @@ func (s *SimpleSyncer) syncRoot(ctx context.Context, remoteRoot Root,
395432
return nil
396433
}
397434

435+
// hasGroupKeyReveal determines whether a proof has a group key reveal. This is
436+
// used to determine whether we should insert the proof right away, or batch it
437+
// with other proofs.
438+
func hasGroupKeyReveal(rawProof []byte) bool {
439+
// We'll decode the proof to determine if it's a group key reveal.
440+
var dummyProof proof.Proof
441+
record := proof.GroupKeyRevealRecord(&dummyProof.GroupKeyReveal)
442+
443+
proofReader := bytes.NewReader(rawProof)
444+
err := proof.SparseDecode(proofReader, record)
445+
if err != nil {
446+
return false
447+
}
448+
449+
return dummyProof.GroupKeyReveal != nil
450+
}
451+
398452
// batchStreamNewItems streams the set of new items to the local registrar in
399453
// batches and returns the new leaf proofs.
400454
func (s *SimpleSyncer) batchStreamNewItems(ctx context.Context,

0 commit comments

Comments
 (0)