Skip to content

Commit 778df91

Browse files
committed
tapdb: update all trees to specify a block height for a universe leaf
1 parent 64bd97b commit 778df91

File tree

7 files changed

+114
-26
lines changed

7 files changed

+114
-26
lines changed

tapdb/burn_tree.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,17 @@ func insertBurnsInternal(ctx context.Context, db BaseUniverseStore,
117117
IsBurn: true,
118118
}
119119

120+
var blockHeight lfn.Option[uint32]
121+
height := burnLeaf.BurnProof.BlockHeight
122+
if height > 0 {
123+
blockHeight = lfn.Some(height)
124+
}
125+
120126
// Call the generic upsert function for the burn sub-tree to
121127
// update DB records. MetaReveal is nil for burns.
122128
_, err = universeUpsertProofLeaf(
123129
ctx, db, subNs, supplycommit.BurnTreeType.String(),
124-
groupKey, leafKey, leaf, nil,
130+
groupKey, leafKey, leaf, nil, blockHeight,
125131
)
126132
if err != nil {
127133
return nil, fmt.Errorf("unable to upsert burn "+

tapdb/ignore_tree.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,21 @@ func addTuplesInternal(ctx context.Context, db BaseUniverseStore,
113113
"universe root: %w", err)
114114
}
115115

116+
var blockHeight lfn.Option[uint32]
117+
height := tup.IgnoreTuple.Val.BlockHeight
118+
if height > 0 {
119+
blockHeight = lfn.Some(height)
120+
}
121+
122+
sqlBlockHeight := lfn.MapOptionZ(
123+
blockHeight, func(num uint32) sql.NullInt32 {
124+
return sql.NullInt32{
125+
Int32: int32(num),
126+
Valid: true,
127+
}
128+
},
129+
)
130+
116131
scriptKey := ignoreTup.ScriptKey
117132
err = db.UpsertUniverseLeaf(ctx, UpsertUniverseLeaf{
118133
AssetGenesisID: assetGenID,
@@ -121,6 +136,7 @@ func addTuplesInternal(ctx context.Context, db BaseUniverseStore,
121136
LeafNodeKey: smtKey[:],
122137
LeafNodeNamespace: namespace,
123138
MintingPoint: ignorePointBytes,
139+
BlockHeight: sqlBlockHeight,
124140
})
125141
if err != nil {
126142
return nil, fmt.Errorf("failed to upsert ignore "+

tapdb/multiverse.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -776,11 +776,16 @@ func (b *MultiverseStore) UpsertProofLeaf(ctx context.Context,
776776

777777
execTxFunc := func(dbTx BaseMultiverseStore) error {
778778
// Register issuance in the asset (group) specific universe
779-
// tree.
780-
var err error
779+
// tree. We don't need to decode the whole proof, we just
780+
// need the block height.
781+
blockHeight, err := SparseDecodeBlockHeight(leaf.RawProof)
782+
if err != nil {
783+
return err
784+
}
785+
781786
uniProof, err = universeUpsertProofLeaf(
782787
ctx, dbTx, id.String(), id.ProofType.String(),
783-
id.GroupKey, key, leaf, metaReveal,
788+
id.GroupKey, key, leaf, metaReveal, blockHeight,
784789
)
785790
if err != nil {
786791
return fmt.Errorf("failed universe upsert: %w", err)
@@ -847,13 +852,22 @@ func (b *MultiverseStore) UpsertProofLeafBatch(ctx context.Context,
847852
for idx := range items {
848853
item := items[idx]
849854

855+
// We don't need to decode the whole proof, we
856+
// just need the block height.
857+
blockHeight, err := SparseDecodeBlockHeight(
858+
item.Leaf.RawProof,
859+
)
860+
if err != nil {
861+
return err
862+
}
863+
850864
// Upsert into the specific universe tree to
851865
// start with.
852866
uniProof, err := universeUpsertProofLeaf(
853867
ctx, store, item.ID.String(),
854868
item.ID.ProofType.String(),
855869
item.ID.GroupKey, item.Key, item.Leaf,
856-
item.MetaReveal,
870+
item.MetaReveal, blockHeight,
857871
)
858872
if err != nil {
859873
return fmt.Errorf("failed universe "+

tapdb/sqlc/queries/universe.sql

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,18 @@ WHERE namespace_root = @namespace_root;
3838

3939
-- name: UpsertUniverseLeaf :exec
4040
INSERT INTO universe_leaves (
41-
asset_genesis_id, script_key_bytes, universe_root_id, leaf_node_key,
42-
leaf_node_namespace, minting_point
41+
asset_genesis_id, script_key_bytes, universe_root_id, leaf_node_key,
42+
leaf_node_namespace, minting_point, block_height
4343
) VALUES (
4444
@asset_genesis_id, @script_key_bytes, @universe_root_id, @leaf_node_key,
45-
@leaf_node_namespace, @minting_point
45+
@leaf_node_namespace, @minting_point, @block_height
4646
) ON CONFLICT (minting_point, script_key_bytes, leaf_node_namespace)
47-
-- This is a NOP, minting_point and script_key_bytes are the unique fields
48-
-- that caused the conflict.
47+
-- Update the block_height on conflict. The minting_point, script_key_bytes,
48+
-- and leaf_node_namespace remain unchanged as they form the unique constraint.
4949
DO UPDATE SET minting_point = EXCLUDED.minting_point,
5050
script_key_bytes = EXCLUDED.script_key_bytes,
51-
leaf_node_namespace = EXCLUDED.leaf_node_namespace;
51+
leaf_node_namespace = EXCLUDED.leaf_node_namespace,
52+
block_height = EXCLUDED.block_height;
5253

5354
-- name: DeleteUniverseLeaves :exec
5455
DELETE FROM universe_leaves

tapdb/sqlc/universe.sql.go

Lines changed: 11 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tapdb/supply_tree.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ func (s *SupplyTreeStore) FetchRootSupplyTree(ctx context.Context,
274274
// NOTE: This function must be called within a database transaction.
275275
func registerMintSupplyInternal(ctx context.Context, dbTx BaseUniverseStore,
276276
assetSpec asset.Specifier, key universe.LeafKey, leaf *universe.Leaf,
277-
metaReveal *proof.MetaReveal) (*universe.Proof, error) {
277+
metaReveal *proof.MetaReveal,
278+
blockHeight lfn.Option[uint32]) (*universe.Proof, error) {
278279

279280
groupKey, err := assetSpec.UnwrapGroupKeyOrErr()
280281
if err != nil {
@@ -286,7 +287,7 @@ func registerMintSupplyInternal(ctx context.Context, dbTx BaseUniverseStore,
286287
// Upsert the leaf into the mint supply sub-tree SMT and DB.
287288
mintSupplyProof, err := universeUpsertProofLeaf(
288289
ctx, dbTx, subNs, supplycommit.MintTreeType.String(), groupKey,
289-
key, leaf, metaReveal,
290+
key, leaf, metaReveal, blockHeight,
290291
)
291292
if err != nil {
292293
return nil, fmt.Errorf("failed mint supply universe "+
@@ -312,15 +313,21 @@ func (s *SupplyTreeStore) RegisterMintSupply(ctx context.Context,
312313

313314
var (
314315
writeTx BaseUniverseStoreOptions
315-
err error
316316
mintSupplyProof *universe.Proof
317317
newRootSupplyRoot mssmt.Node
318318
)
319319
dbErr := s.db.ExecTx(ctx, &writeTx, func(dbTx BaseUniverseStore) error {
320+
// We don't need to decode the whole proof, we just need the
321+
// block height.
322+
blockHeight, err := SparseDecodeBlockHeight(leaf.RawProof)
323+
if err != nil {
324+
return err
325+
}
326+
320327
// Upsert the leaf into the mint supply sub-tree SMT and DB
321328
// first.
322329
mintSupplyProof, err = registerMintSupplyInternal(
323-
ctx, dbTx, spec, key, leaf, nil,
330+
ctx, dbTx, spec, key, leaf, nil, blockHeight,
324331
)
325332
if err != nil {
326333
return fmt.Errorf("failed mint supply universe "+
@@ -395,9 +402,15 @@ func applySupplyUpdatesInternal(ctx context.Context, dbTx BaseUniverseStore,
395402
"type: %T", update)
396403
}
397404

405+
var blockHeight lfn.Option[uint32]
406+
height := mintEvent.BlockHeight()
407+
if height > 0 {
408+
blockHeight = lfn.Some(height)
409+
}
410+
398411
mintProof, err := registerMintSupplyInternal(
399412
ctx, dbTx, spec, mintEvent.LeafKey,
400-
&mintEvent.IssuanceProof, nil,
413+
&mintEvent.IssuanceProof, nil, blockHeight,
401414
)
402415
if err != nil {
403416
return nil, fmt.Errorf("failed to register "+

tapdb/universe.go

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ type (
5858

5959
// UpsertUniverseSupplyLeaf is used to upsert a universe supply leaf.
6060
UpsertUniverseSupplyLeaf = sqlc.UpsertUniverseSupplyLeafParams
61+
62+
// QuerySupplyLeavesByHeightParams is used to query for supply leaves
63+
// by height.
64+
QuerySupplyLeavesByHeightParams = sqlc.QuerySupplyLeavesByHeightParams
6165
)
6266

6367
// BaseUniverseStore is the main interface for the Taproot Asset universe store.
@@ -128,6 +132,12 @@ type BaseUniverseStore interface {
128132
// supply tree for a given asset.
129133
UpsertUniverseSupplyRoot(ctx context.Context,
130134
arg UpsertUniverseSupplyRoot) (int64, error)
135+
136+
// QuerySupplyLeavesByHeight is used to query for supply leaves by
137+
// height.
138+
QuerySupplyLeavesByHeight(ctx context.Context,
139+
arg QuerySupplyLeavesByHeightParams) (
140+
[]sqlc.QuerySupplyLeavesByHeightRow, error)
131141
}
132142

133143
// getUniverseTreeSum retrieves the sum of a universe tree specified by its
@@ -570,9 +580,17 @@ func (b *BaseUniverseTree) UpsertProofLeaf(ctx context.Context,
570580
)
571581
dbErr := b.db.ExecTx(ctx, &writeTx, func(dbTx BaseUniverseStore) error {
572582
namespace := b.id.String()
583+
584+
// We don't need to decode the whole proof, we just need the
585+
// block height.
586+
blockHeight, err := SparseDecodeBlockHeight(leaf.RawProof)
587+
if err != nil {
588+
return err
589+
}
590+
573591
issuanceProof, err := universeUpsertProofLeaf(
574592
ctx, dbTx, namespace, b.id.ProofType.String(),
575-
b.id.GroupKey, key, leaf, metaReveal,
593+
b.id.GroupKey, key, leaf, metaReveal, blockHeight,
576594
)
577595
if err != nil {
578596
return fmt.Errorf("failed universe upsert: %w", err)
@@ -701,8 +719,8 @@ func upsertMultiverseLeafEntry(ctx context.Context, dbTx BaseUniverseStore,
701719
// broader DB updates.
702720
func universeUpsertProofLeaf(ctx context.Context, dbTx BaseUniverseStore,
703721
namespace string, proofTypeStr string, groupKey *btcec.PublicKey,
704-
key universe.LeafKey, leaf *universe.Leaf,
705-
metaReveal *proof.MetaReveal) (*universe.Proof, error) {
722+
key universe.LeafKey, leaf *universe.Leaf, metaReveal *proof.MetaReveal,
723+
blockHeight lfn.Option[uint32]) (*universe.Proof, error) {
706724

707725
// With the tree store created, we'll now obtain byte representation of
708726
// the minting key, as that'll be the key in the SMT itself.
@@ -773,6 +791,21 @@ func universeUpsertProofLeaf(ctx context.Context, dbTx BaseUniverseStore,
773791
return nil, err
774792
}
775793

794+
// If the block height isn't specified, then we'll attempt to extract it
795+
// from the proof itself.
796+
if blockHeight.IsNone() && leafProof.BlockHeight > 0 {
797+
blockHeight = lfn.Some(leafProof.BlockHeight)
798+
}
799+
800+
sqlBlockHeight := lfn.MapOptionZ(
801+
blockHeight, func(num uint32) sql.NullInt32 {
802+
return sql.NullInt32{
803+
Int32: int32(num),
804+
Valid: true,
805+
}
806+
},
807+
)
808+
776809
scriptKey := key.LeafScriptKey()
777810
scriptKeyBytes := schnorr.SerializePubKey(scriptKey.PubKey)
778811
err = dbTx.UpsertUniverseLeaf(ctx, UpsertUniverseLeaf{
@@ -782,6 +815,7 @@ func universeUpsertProofLeaf(ctx context.Context, dbTx BaseUniverseStore,
782815
LeafNodeKey: smtKey[:],
783816
LeafNodeNamespace: namespace,
784817
MintingPoint: mintingPointBytes,
818+
BlockHeight: sqlBlockHeight,
785819
})
786820
if err != nil {
787821
return nil, err

0 commit comments

Comments
 (0)