Skip to content

Commit 69072b5

Browse files
committed
universe: add MultiverseRoot method to archive
1 parent 94a371a commit 69072b5

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

universe/base.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/davecgh/go-spew/spew"
1313
"github.com/lightninglabs/taproot-assets/asset"
1414
"github.com/lightninglabs/taproot-assets/fn"
15+
"github.com/lightninglabs/taproot-assets/mssmt"
1516
"github.com/lightninglabs/taproot-assets/proof"
1617
)
1718

@@ -134,6 +135,69 @@ func (a *Archive) RootNodes(ctx context.Context,
134135
return a.cfg.Multiverse.RootNodes(ctx, q)
135136
}
136137

138+
// MultiverseRoot returns the root node of the multiverse for the specified
139+
// proof type. If the given list of universe IDs is non-empty, then the root
140+
// will be calculated just for those universes.
141+
func (a *Archive) MultiverseRoot(ctx context.Context, proofType ProofType,
142+
filterByIDs []Identifier) (mssmt.Node, error) {
143+
144+
log.Debugf("Fetching multiverse root for proof type: %v", proofType)
145+
146+
leaveIDs, err := a.cfg.Multiverse.FetchLeaves(ctx, nil, nil, proofType)
147+
if err != nil {
148+
return nil, fmt.Errorf("unable to fetch multiverse leaves: %w",
149+
err)
150+
}
151+
152+
// If a filter list is provided, then we'll only include the leaves
153+
// that are in the filter list.
154+
includeUniverse := func(id Identifier) bool {
155+
if len(filterByIDs) == 0 {
156+
return true
157+
}
158+
159+
for _, filterID := range filterByIDs {
160+
if id.IsEqual(filterID) {
161+
return true
162+
}
163+
}
164+
165+
return false
166+
}
167+
168+
memStore := mssmt.NewDefaultStore()
169+
tree := mssmt.NewCompactedTree(memStore)
170+
171+
for _, id := range leaveIDs {
172+
// Only include the universe if it's in the filter list (given
173+
// the filter list is non-empty).
174+
if !includeUniverse(id) {
175+
continue
176+
}
177+
178+
uniRoot, err := a.cfg.Multiverse.UniverseRootNode(ctx, id)
179+
if err != nil {
180+
return nil, fmt.Errorf("unable to fetch universe "+
181+
"root: %w", err)
182+
}
183+
184+
rootHash := uniRoot.NodeHash()
185+
rootSum := uniRoot.NodeSum()
186+
187+
if id.ProofType == ProofTypeIssuance {
188+
rootSum = 1
189+
}
190+
191+
uniLeaf := mssmt.NewLeafNode(rootHash[:], rootSum)
192+
_, err = tree.Insert(ctx, id.Bytes(), uniLeaf)
193+
if err != nil {
194+
return nil, fmt.Errorf("unable to insert leaf: %w", err)
195+
}
196+
}
197+
198+
return tree.Root(ctx)
199+
}
200+
137201
// UpsertProofLeaf attempts to upsert a proof for an asset issuance or transfer
138202
// event. This method will return an error if the passed proof is invalid. If
139203
// the leaf is already known, then no action is taken and the existing

universe/interface.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,24 @@ func (i *Identifier) StringForLog() string {
8484
i.String(), i.AssetID[:], groupKey, i.ProofType)
8585
}
8686

87+
// IsEqual returns true if the two identifiers are equal.
88+
func (i *Identifier) IsEqual(other Identifier) bool {
89+
if i == nil {
90+
return false
91+
}
92+
93+
groupKeysEqual := false
94+
if i.GroupKey == nil || other.GroupKey == nil {
95+
groupKeysEqual = i.GroupKey == other.GroupKey
96+
} else {
97+
groupKeysEqual = i.GroupKey.IsEqual(other.GroupKey)
98+
}
99+
100+
return i.AssetID == other.AssetID &&
101+
groupKeysEqual &&
102+
i.ProofType == other.ProofType
103+
}
104+
87105
// NewUniIDFromAsset creates a new universe ID from an asset.
88106
func NewUniIDFromAsset(a asset.Asset) Identifier {
89107
proofType := ProofTypeTransfer
@@ -393,6 +411,13 @@ type MultiverseArchive interface {
393411
// universe.
394412
UniverseLeafKeys(ctx context.Context,
395413
q UniverseLeafKeysQuery) ([]LeafKey, error)
414+
415+
// FetchLeaves returns the set of multiverse leaves for the given proof
416+
// type, asset ID, and group key. If both asset ID and group key is nil,
417+
// all leaves for the given proof type will be returned.
418+
FetchLeaves(ctx context.Context, assetID *asset.ID,
419+
groupKey *btcec.PublicKey,
420+
proofType ProofType) ([]Identifier, error)
396421
}
397422

398423
// Registrar is an interface that allows a caller to upsert a proof leaf in a

0 commit comments

Comments
 (0)