Skip to content

Commit 4259ec3

Browse files
committed
tapdb: update all trees to specify a block height for a universe leaf
1 parent 4073831 commit 4259ec3

File tree

7 files changed

+119
-23
lines changed

7 files changed

+119
-23
lines changed

tapdb/burn_tree.go

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

119+
var blockHeight lfn.Option[uint32]
120+
height := burnLeaf.BurnProof.BlockHeight
121+
if height > 0 {
122+
blockHeight = lfn.Some(height)
123+
}
124+
119125
// Call the generic upsert function for the burn sub-tree to
120126
// update DB records. MetaReveal is nil for burns.
121127
_, err = universeUpsertProofLeaf(
122128
ctx, db, subNs, supplycommit.BurnTreeType.String(),
123-
groupKey, leafKey, leaf, nil,
129+
groupKey, leafKey, leaf, nil, blockHeight,
124130
)
125131
if err != nil {
126132
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: 5 additions & 4 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)
4747
-- This is a NOP, minting_point and script_key_bytes are the unique fields
4848
-- that caused the conflict.
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: 9 additions & 5 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: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
package tapdb
22

33
import (
4+
"bytes"
45
"context"
6+
"database/sql"
57
"encoding/hex"
8+
"errors"
69
"fmt"
710

811
"github.com/btcsuite/btcd/btcec/v2"
912
"github.com/lightninglabs/taproot-assets/asset"
1013
"github.com/lightninglabs/taproot-assets/mssmt"
1114
"github.com/lightninglabs/taproot-assets/proof"
15+
"github.com/lightninglabs/taproot-assets/tapdb/sqlc"
1216
"github.com/lightninglabs/taproot-assets/universe"
1317
"github.com/lightninglabs/taproot-assets/universe/supplycommit"
1418

@@ -274,18 +278,19 @@ func (s *SupplyTreeStore) FetchRootSupplyTree(ctx context.Context,
274278
// NOTE: This function must be called within a database transaction.
275279
func registerMintSupplyInternal(ctx context.Context, dbTx BaseUniverseStore,
276280
assetSpec asset.Specifier, key universe.LeafKey, leaf *universe.Leaf,
277-
metaReveal *proof.MetaReveal) (*universe.Proof, error) {
281+
metaReveal *proof.MetaReveal, blockHeight lfn.Option[uint32]) (*universe.Proof,
282+
error) {
278283

279284
groupKey, err := assetSpec.UnwrapGroupKeyOrErr()
280285
if err != nil {
281-
return nil, fmt.Errorf("group key must be specified for mint supply: %w", err)
286+
return nil, fmt.Errorf("group key must be specified for mint supply: %w", err) //nolint:lll
282287
}
283288
subNs := subTreeNamespace(groupKey, supplycommit.MintTreeType)
284289

285290
// Upsert the leaf into the mint supply sub-tree SMT and DB.
286291
mintSupplyProof, err := universeUpsertProofLeaf(
287292
ctx, dbTx, subNs, supplycommit.MintTreeType.String(), groupKey,
288-
key, leaf, metaReveal,
293+
key, leaf, metaReveal, blockHeight,
289294
)
290295
if err != nil {
291296
return nil, fmt.Errorf("failed mint supply universe "+
@@ -311,15 +316,21 @@ func (s *SupplyTreeStore) RegisterMintSupply(ctx context.Context,
311316

312317
var (
313318
writeTx BaseUniverseStoreOptions
314-
err error
315319
mintSupplyProof *universe.Proof
316320
newRootSupplyRoot mssmt.Node
317321
)
318322
dbErr := s.db.ExecTx(ctx, &writeTx, func(dbTx BaseUniverseStore) error {
323+
// We don't need to decode the whole proof, we just need the
324+
// block height.
325+
blockHeight, err := SparseDecodeBlockHeight(leaf.RawProof)
326+
if err != nil {
327+
return err
328+
}
329+
319330
// Upsert the leaf into the mint supply sub-tree SMT and DB
320331
// first.
321332
mintSupplyProof, err = registerMintSupplyInternal(
322-
ctx, dbTx, spec, key, leaf, nil,
333+
ctx, dbTx, spec, key, leaf, nil, blockHeight,
323334
)
324335
if err != nil {
325336
return fmt.Errorf("failed mint supply universe "+
@@ -393,9 +404,15 @@ func applySupplyUpdatesInternal(ctx context.Context, dbTx BaseUniverseStore,
393404
"type: %T", update)
394405
}
395406

407+
var blockHeight lfn.Option[uint32]
408+
height := mintEvent.BlockHeight()
409+
if height > 0 {
410+
blockHeight = lfn.Some(height)
411+
}
412+
396413
mintProof, err := registerMintSupplyInternal(
397414
ctx, dbTx, spec, mintEvent.LeafKey,
398-
&mintEvent.IssuanceProof, nil,
415+
&mintEvent.IssuanceProof, nil, blockHeight,
399416
)
400417
if err != nil {
401418
return nil, fmt.Errorf("failed to register "+
@@ -584,3 +601,4 @@ func (s *SupplyTreeStore) ApplySupplyUpdates(ctx context.Context,
584601

585602
return finalRoot, nil
586603
}
604+

tapdb/universe.go

Lines changed: 40 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
// specifierToIdentifier converts an asset.Specifier into a universe.Identifier
@@ -595,9 +605,17 @@ func (b *BaseUniverseTree) UpsertProofLeaf(ctx context.Context,
595605
)
596606
dbErr := b.db.ExecTx(ctx, &writeTx, func(dbTx BaseUniverseStore) error {
597607
namespace := b.id.String()
608+
609+
// We don't need to decode the whole proof, we just need the
610+
// block height.
611+
blockHeight, err := SparseDecodeBlockHeight(leaf.RawProof)
612+
if err != nil {
613+
return err
614+
}
615+
598616
issuanceProof, err := universeUpsertProofLeaf(
599-
ctx, dbTx, namespace, b.id.ProofType.String(),
600-
b.id.GroupKey, key, leaf, metaReveal,
617+
ctx, dbTx, namespace, b.id.ProofType.String(), b.id.GroupKey,
618+
key, leaf, metaReveal, blockHeight,
601619
)
602620
if err != nil {
603621
return fmt.Errorf("failed universe upsert: %w", err)
@@ -727,7 +745,8 @@ func upsertMultiverseLeafEntry(ctx context.Context, dbTx BaseUniverseStore,
727745
func universeUpsertProofLeaf(ctx context.Context, dbTx BaseUniverseStore,
728746
namespace string, proofTypeStr string, groupKey *btcec.PublicKey,
729747
key universe.LeafKey, leaf *universe.Leaf,
730-
metaReveal *proof.MetaReveal) (*universe.Proof, error) {
748+
metaReveal *proof.MetaReveal, blockHeight lfn.Option[uint32]) (*universe.Proof,
749+
error) {
731750

732751
// With the tree store created, we'll now obtain byte representation of
733752
// the minting key, as that'll be the key in the SMT itself.
@@ -798,6 +817,23 @@ func universeUpsertProofLeaf(ctx context.Context, dbTx BaseUniverseStore,
798817
return nil, err
799818
}
800819

820+
// If the block height isn't specified, then we'll attempt to extract it
821+
// from the proof itself.
822+
if blockHeight.IsNone() {
823+
if leafProof.BlockHeight > 0 {
824+
blockHeight = lfn.Some(leafProof.BlockHeight)
825+
}
826+
}
827+
828+
sqlBlockHeight := lfn.MapOptionZ(
829+
blockHeight, func(num uint32) sql.NullInt32 {
830+
return sql.NullInt32{
831+
Int32: int32(num),
832+
Valid: true,
833+
}
834+
},
835+
)
836+
801837
scriptKey := key.LeafScriptKey()
802838
scriptKeyBytes := schnorr.SerializePubKey(scriptKey.PubKey)
803839
err = dbTx.UpsertUniverseLeaf(ctx, UpsertUniverseLeaf{
@@ -807,6 +843,7 @@ func universeUpsertProofLeaf(ctx context.Context, dbTx BaseUniverseStore,
807843
LeafNodeKey: smtKey[:],
808844
LeafNodeNamespace: namespace,
809845
MintingPoint: mintingPointBytes,
846+
BlockHeight: sqlBlockHeight,
810847
})
811848
if err != nil {
812849
return nil, err

0 commit comments

Comments
 (0)