Skip to content

Commit 003f739

Browse files
committed
supplyverify: add SupplySyncer for syncing supply commit leaves
Introduce SupplySyncer to handle syncing of supply commit leaves from remote universe servers. The fetched leaves will be verified by the supply verifier, which will be included in a future commit.
1 parent 83c024f commit 003f739

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

universe/supplyverifier/syncer.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package supplyverifier
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/lightninglabs/taproot-assets/asset"
8+
"github.com/lightninglabs/taproot-assets/fn"
9+
"github.com/lightninglabs/taproot-assets/universe"
10+
"github.com/lightninglabs/taproot-assets/universe/supplycommit"
11+
)
12+
13+
// SupplyLeafFetcher is an interface that can be used to fetch information from
14+
// a Universe.
15+
type SupplyLeafFetcher interface {
16+
// FetchSupplyLeaves fetches the supply leaves for a specific asset
17+
// group within a specified block height range.
18+
FetchSupplyLeaves(ctx context.Context,
19+
assetSpec asset.Specifier, startBlockHeight,
20+
endBlockHeight fn.Option[uint32]) (supplycommit.SupplyLeaves,
21+
error)
22+
23+
// Close closes the fetcher and cleans up any resources.
24+
Close() error
25+
}
26+
27+
// SupplyLeafFetcherFactory is a function type that creates SupplyLeafFetcher
28+
// instances for a given universe server address.
29+
type SupplyLeafFetcherFactory func(
30+
serverAddr universe.ServerAddr) (SupplyLeafFetcher, error)
31+
32+
// SupplySyncerStore is an interface for storing synced leaves and state.
33+
type SupplySyncerStore interface {
34+
// UpsertSupplyLeaves stores a batch of supply update events to the
35+
// database without requiring a supply commitment transition.
36+
UpsertSupplyLeaves(ctx context.Context, spec asset.Specifier,
37+
updates []supplycommit.SupplyUpdateEvent) error
38+
}
39+
40+
// SupplySyncer is a struct that is responsible for retrieving supply leaves
41+
// from a universe.
42+
type SupplySyncer struct {
43+
// fetcherFactory is a factory function that creates SupplyLeafFetcher
44+
// instances for specific universe server addresses.
45+
fetcherFactory SupplyLeafFetcherFactory
46+
47+
// store is used to persist supply leaves to the local database.
48+
store SupplySyncerStore
49+
}
50+
51+
// NewSupplySyncer creates a new SupplySyncer with a factory function for
52+
// creating SupplyLeafFetcher instances and a store for persisting leaves.
53+
func NewSupplySyncer(factory SupplyLeafFetcherFactory,
54+
store SupplySyncerStore) *SupplySyncer {
55+
56+
return &SupplySyncer{
57+
fetcherFactory: factory,
58+
store: store,
59+
}
60+
}
61+
62+
// Sync retrieves all supply leaves from the specified universe server.
63+
func (s *SupplySyncer) Sync(ctx context.Context, serverAddr universe.ServerAddr,
64+
assetSpec asset.Specifier, startBlockHeight uint32) (
65+
supplycommit.SupplyLeaves, error) {
66+
67+
var zero supplycommit.SupplyLeaves
68+
69+
// Create a fetcher for the specific universe server address
70+
fetcher, err := s.fetcherFactory(serverAddr)
71+
if err != nil {
72+
return zero, fmt.Errorf("unable to create supply leaf "+
73+
"fetcher: %w", err)
74+
}
75+
76+
// Ensure the fetcher is properly closed when we're done
77+
defer func() {
78+
if closeErr := fetcher.Close(); closeErr != nil {
79+
log.Errorf("unable to close supply leaf fetcher: %v",
80+
closeErr)
81+
}
82+
}()
83+
84+
leaves, err := fetcher.FetchSupplyLeaves(
85+
ctx, assetSpec, fn.Some(startBlockHeight), fn.None[uint32](),
86+
)
87+
if err != nil {
88+
return zero, fmt.Errorf("unable to fetch supply leaves: %w",
89+
err)
90+
}
91+
92+
// Convert SupplyLeaves to SupplyUpdateEvents for storage.
93+
var updates []supplycommit.SupplyUpdateEvent
94+
95+
for i := range leaves.IssuanceLeafEntries {
96+
updates = append(updates, &leaves.IssuanceLeafEntries[i])
97+
}
98+
99+
for i := range leaves.BurnLeafEntries {
100+
updates = append(updates, &leaves.BurnLeafEntries[i])
101+
}
102+
103+
for i := range leaves.IgnoreLeafEntries {
104+
updates = append(updates, &leaves.IgnoreLeafEntries[i])
105+
}
106+
107+
// Store the updates to the local database (ignore the return value).
108+
err = s.store.UpsertSupplyLeaves(ctx, assetSpec, updates)
109+
if err != nil {
110+
return zero, fmt.Errorf("unable to store supply leaves: %w",
111+
err)
112+
}
113+
114+
return leaves, nil
115+
}

0 commit comments

Comments
 (0)