diff --git a/proof/verifier.go b/proof/verifier.go index c83cfce2f..314d5072c 100644 --- a/proof/verifier.go +++ b/proof/verifier.go @@ -6,6 +6,9 @@ import ( "fmt" "io" "runtime" + "sort" + "strconv" + "strings" "sync" "github.com/btcsuite/btcd/btcec/v2" @@ -178,10 +181,10 @@ func verifyTaprootProof(anchor *wire.MsgTx, proof *TaprootProof, ) return nil, fmt.Errorf("%w: derived_keys=%s, expected_key=%x, "+ - "output_index=%d, internal_key=%x, method=%s", + "output_index=%d, internal_key=%x, asset_id=%s, method=%s", commitment.ErrInvalidTaprootProof, keysForLog, expectedKey, proof.OutputIndex, proof.InternalKey.SerializeCompressed(), - method) + a.ID().String(), method) } // verifyInclusionProof verifies the InclusionProof is valid. @@ -373,9 +376,26 @@ func (p *Proof) verifyV0ExclusionProofs( // Correctly validated proofs are removed from the set. That means, if // there are any outputs left in the set, it means that there are // missing proofs for those outputs. - if len(p2trOutputs) > 0 { - return nil, fmt.Errorf("%w: missing exclusion proof(s)", - ErrInvalidCommitmentProof) + if len(p2trOutputs) != 0 { + // Collect and sort the missing output indexes for stable + // logging/errors. + indexes := make([]int, 0, len(p2trOutputs)) + for i := range p2trOutputs { + indexes = append(indexes, int(i)) + } + sort.Ints(indexes) + + // Format as "0, 3, 7". + parts := make([]string, len(indexes)) + for i, v := range indexes { + parts[i] = strconv.Itoa(v) + } + missing := strings.Join(parts, ", ") + + log.Errorf("Missing exclusion proofs for p2tr output "+ + "indexes: %s", missing) + return nil, fmt.Errorf("%w: missing exclusion proofs for "+ + "outputs", ErrInvalidCommitmentProof) } return commitVersions, nil diff --git a/tapgarden/caretaker.go b/tapgarden/caretaker.go index aaea11c3c..512af2245 100644 --- a/tapgarden/caretaker.go +++ b/tapgarden/caretaker.go @@ -1311,7 +1311,7 @@ func (b *BatchCaretaker) batchStreamUniverseItems(ctx context.Context, err := uni.UpsertProofLeafBatch(ctx, batch) if err != nil { return fmt.Errorf("unable to register "+ - "issuance batch: %w", err) + "proof leaf batch: %w", err) } log.Infof("Inserted %d new leaves (%d of %d) into "+ diff --git a/universe/archive.go b/universe/archive.go index 2e1835ad0..0e92a5607 100644 --- a/universe/archive.go +++ b/universe/archive.go @@ -428,8 +428,8 @@ func extractBatchDeps(batch []*Item) map[UniverseKey]*asset.Asset { func (a *Archive) UpsertProofLeafBatch(ctx context.Context, items []*Item) error { - log.Infof("Verifying %d new proofs for insertion into Universe", - len(items)) + log.InfoS(ctx, "Verifying new proofs for insertion into Universe", + "count", len(items)) // Issuance proofs that also create an asset group (a.k.a. group // anchors) must be verified and stored before any issuance proofs that @@ -529,12 +529,12 @@ func (a *Archive) UpsertProofLeafBatch(ctx context.Context, return err } - log.Infof("Inserting %d verified group anchor proofs into Universe", - len(anchorItems)) + log.InfoS(ctx, "Inserting verified group anchor proofs into Universe", + "count", len(anchorItems)) err = a.cfg.Multiverse.UpsertProofLeafBatch(ctx, anchorItems) if err != nil { - return fmt.Errorf("unable to register new group anchor "+ - "issuance proofs: %w", err) + return fmt.Errorf("upsert group anchor proof leaf batch "+ + "(count=%d): %w", len(anchorItems), err) } err = verifyBatch(nonAnchorItems) @@ -542,12 +542,12 @@ func (a *Archive) UpsertProofLeafBatch(ctx context.Context, return err } - log.Infof("Inserting %d verified proofs into Universe", - len(nonAnchorItems)) + log.InfoS(ctx, "Inserting verified proofs into Universe", + "count", len(nonAnchorItems)) err = a.cfg.Multiverse.UpsertProofLeafBatch(ctx, nonAnchorItems) if err != nil { - return fmt.Errorf("unable to register new issuance proofs: %w", - err) + return fmt.Errorf("upsert proof leaf batch (count=%d): %w", + len(nonAnchorItems), err) } // Log a sync event for the newly inserted leaf in the background as an