Skip to content

Commit 7136f13

Browse files
committed
tapdb: add SupplySyncerStore
Add a store used by the syncer to persist synced supply commit leaves, as well as syncer state (e.g., the latest synced block height for a given asset group).
1 parent 245a77b commit 7136f13

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

tapdb/supply_syncer.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package tapdb
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/lightninglabs/taproot-assets/asset"
8+
"github.com/lightninglabs/taproot-assets/tapdb/sqlc"
9+
"github.com/lightninglabs/taproot-assets/universe/supplycommit"
10+
)
11+
12+
// SupplySyncerStore implements the persistent storage for supply syncing
13+
// operations. It provides methods to store supply updates without requiring
14+
// a supply commitment transition.
15+
type SupplySyncerStore struct {
16+
db BatchedUniverseTree
17+
}
18+
19+
// NewSupplySyncerStore creates a new supply syncer DB store handle.
20+
func NewSupplySyncerStore(db BatchedUniverseTree) *SupplySyncerStore {
21+
return &SupplySyncerStore{
22+
db: db,
23+
}
24+
}
25+
26+
// UpsertSupplyLeaves stores a batch of supply update events to the database
27+
// without requiring a supply commitment transition. It reuses the internal
28+
// supply update logic from SupplyTreeStore.
29+
func (s *SupplySyncerStore) UpsertSupplyLeaves(ctx context.Context,
30+
spec asset.Specifier,
31+
updates []supplycommit.SupplyUpdateEvent) error {
32+
33+
// If no updates were provided, return early without error.
34+
if len(updates) == 0 {
35+
return nil
36+
}
37+
38+
// Find the highest block height from all the supply update events.
39+
var maxBlockHeight uint32
40+
for _, update := range updates {
41+
if height := update.BlockHeight(); height > maxBlockHeight {
42+
maxBlockHeight = height
43+
}
44+
}
45+
46+
// All updates must have a valid block height.
47+
if maxBlockHeight == 0 {
48+
return fmt.Errorf("all supply updates must have a valid " +
49+
"block height greater than 0")
50+
}
51+
52+
// Extract the group key for logging.
53+
groupKey, err := spec.UnwrapGroupKeyOrErr()
54+
if err != nil {
55+
return fmt.Errorf("group key must be specified for supply "+
56+
"syncer: %w", err)
57+
}
58+
59+
var writeTx BaseUniverseStoreOptions
60+
return s.db.ExecTx(ctx, &writeTx, func(dbTx BaseUniverseStore) error {
61+
// Reuse the internal supply update logic which handles all
62+
// the complex sub-tree and root tree updates within the
63+
// transaction.
64+
_, err := applySupplyUpdatesInternal(ctx, dbTx, spec, updates)
65+
if err != nil {
66+
return err
67+
}
68+
69+
// Log the latest synced block height for this asset group.
70+
groupKeyBytes := groupKey.SerializeCompressed()
71+
err = dbTx.UpsertSupplySyncerLog(
72+
ctx, sqlc.UpsertSupplySyncerLogParams{
73+
GroupKey: groupKeyBytes,
74+
LatestSyncBlockHeight: int32(maxBlockHeight),
75+
},
76+
)
77+
if err != nil {
78+
return fmt.Errorf("failed to log synced block "+
79+
"height: %w", err)
80+
}
81+
82+
return nil
83+
})
84+
}

0 commit comments

Comments
 (0)