@@ -330,6 +330,45 @@ type OptionalSeedlingFields struct {
330330 GroupAnchorID sql.NullInt64
331331}
332332
333+ // upsertDelegationKey inserts the given delegation key descriptor into
334+ // the internal_keys SQL table and returns its ID.
335+ func upsertDelegationKey (ctx context.Context , q PendingAssetStore ,
336+ keyDescOpt fn.Option [keychain.KeyDescriptor ]) (sql.NullInt64 , error ) {
337+
338+ var zero sql.NullInt64
339+
340+ // If the delegation key is not set, we can return a zero value.
341+ if keyDescOpt .IsNone () {
342+ return zero , nil
343+ }
344+
345+ // Unwrap the key descriptor to get the actual key.
346+ keyDesc , err := keyDescOpt .UnwrapOrErr (
347+ fmt .Errorf ("delegation key is unexpectedly not set" ),
348+ )
349+ if err != nil {
350+ return zero , err
351+ }
352+
353+ // Sanity check the key descriptor.
354+ if keyDesc .PubKey == nil {
355+ return zero , fmt .Errorf ("delegation key pubkey is nil" )
356+ }
357+
358+ // Insert the key descriptor into the internal_keys table.
359+ keyID , err := q .UpsertInternalKey (ctx , InternalKey {
360+ RawKey : keyDesc .PubKey .SerializeCompressed (),
361+ KeyFamily : int32 (keyDesc .Family ),
362+ KeyIndex : int32 (keyDesc .Index ),
363+ })
364+ if err != nil {
365+ return zero , fmt .Errorf ("unable to insert internal key: %w" ,
366+ err )
367+ }
368+
369+ return sqlInt64 (keyID ), nil
370+ }
371+
333372// insertMintAnchorTx inserts a mint anchor transaction into the database.
334373func insertMintAnchorTx (ctx context.Context , q PendingAssetStore ,
335374 anchorPackage tapgarden.FundedMintAnchorPsbt ,
@@ -442,9 +481,10 @@ func (a *AssetMintingStore) CommitMintingBatch(ctx context.Context,
442481 // With our internal key inserted, we can now insert a new
443482 // batch which references the target internal key.
444483 if err := q .NewMintingBatch (ctx , MintingBatchInit {
445- BatchID : batchID ,
446- HeightHint : int32 (newBatch .HeightHint ),
447- CreationTimeUnix : newBatch .CreationTime .UTC (),
484+ BatchID : batchID ,
485+ HeightHint : int32 (newBatch .HeightHint ),
486+ CreationTimeUnix : newBatch .CreationTime .UTC (),
487+ UniverseCommitments : newBatch .UniverseCommitments ,
448488 }); err != nil {
449489 return fmt .Errorf ("unable to insert minting " +
450490 "batch: %w" , err )
@@ -510,6 +550,9 @@ func (a *AssetMintingStore) CommitMintingBatch(ctx context.Context,
510550 AssetSupply : int64 (seedling .Amount ),
511551 AssetMetaID : assetMetaID ,
512552 EmissionEnabled : seedling .EnableEmission ,
553+
554+ // nolint: lll
555+ UniverseCommitments : seedling .UniverseCommitments ,
513556 }
514557
515558 scriptKeyID , err := upsertScriptKey (
@@ -544,6 +587,17 @@ func (a *AssetMintingStore) CommitMintingBatch(ctx context.Context,
544587 dbSeedling .GroupGenesisID = optionalDbIDs .GroupGenesisID
545588 dbSeedling .GroupAnchorID = optionalDbIDs .GroupAnchorID
546589
590+ // Upsert the seedling's delegation key if present.
591+ delegationKeyID , err := upsertDelegationKey (
592+ ctx , q , seedling .DelegationKey ,
593+ )
594+ if err != nil {
595+ return fmt .Errorf ("unable to insert " +
596+ "delegation key: %w" , err )
597+ }
598+
599+ dbSeedling .DelegationKeyID = delegationKeyID
600+
547601 err = q .InsertAssetSeedling (ctx , dbSeedling )
548602 if err != nil {
549603 return err
@@ -641,6 +695,9 @@ func (a *AssetMintingStore) AddSeedlingsToBatch(ctx context.Context,
641695 AssetSupply : int64 (seedling .Amount ),
642696 AssetMetaID : assetMetaID ,
643697 EmissionEnabled : seedling .EnableEmission ,
698+
699+ // nolint: lll
700+ UniverseCommitments : seedling .UniverseCommitments ,
644701 }
645702
646703 scriptKeyID , err := upsertScriptKey (
@@ -675,6 +732,18 @@ func (a *AssetMintingStore) AddSeedlingsToBatch(ctx context.Context,
675732 dbSeedling .GroupGenesisID = optionalDbIDs .GroupGenesisID
676733 dbSeedling .GroupAnchorID = optionalDbIDs .GroupAnchorID
677734
735+ // Handle delegation key: upsert to internal_keys and
736+ // reference in seedling.
737+ delegationKeyID , err := upsertDelegationKey (
738+ ctx , q , seedling .DelegationKey ,
739+ )
740+ if err != nil {
741+ return fmt .Errorf ("unable to insert " +
742+ "delegation key: %w" , err )
743+ }
744+
745+ dbSeedling .DelegationKeyID = delegationKeyID
746+
678747 err = q .InsertAssetSeedlingIntoBatch (ctx , dbSeedling )
679748 if err != nil {
680749 return fmt .Errorf ("unable to insert " +
@@ -724,7 +793,8 @@ func fetchAssetSeedlings(ctx context.Context, q PendingAssetStore,
724793 Amount : uint64 (
725794 dbSeedling .AssetSupply ,
726795 ),
727- EnableEmission : dbSeedling .EmissionEnabled ,
796+ EnableEmission : dbSeedling .EmissionEnabled ,
797+ UniverseCommitments : dbSeedling .UniverseCommitments ,
728798 }
729799
730800 if dbSeedling .TweakedScriptKey != nil {
@@ -792,6 +862,31 @@ func fetchAssetSeedlings(ctx context.Context, q PendingAssetStore,
792862 }
793863 }
794864
865+ // If the seedling has a delegation key, we'll parse it and
866+ // store it in the seedling.
867+ if dbSeedling .DelegationKeyRaw != nil {
868+ delegationKeyPub , err := btcec .ParsePubKey (
869+ dbSeedling .DelegationKeyRaw ,
870+ )
871+ if err != nil {
872+ return nil , err
873+ }
874+
875+ locator := keychain.KeyLocator {
876+ Index : extractSqlInt32 [uint32 ](
877+ dbSeedling .DelegationKeyIndex ,
878+ ),
879+ Family : extractSqlInt32 [keychain.KeyFamily ](
880+ dbSeedling .DelegationKeyFam ,
881+ ),
882+ }
883+
884+ seedling .DelegationKey = fn .Some (keychain.KeyDescriptor {
885+ KeyLocator : locator ,
886+ PubKey : delegationKeyPub ,
887+ })
888+ }
889+
795890 if len (dbSeedling .GroupTapscriptRoot ) != 0 {
796891 seedling .GroupTapscriptRoot = dbSeedling .
797892 GroupTapscriptRoot
@@ -1203,8 +1298,9 @@ func marshalMintingBatch(ctx context.Context, q PendingAssetStore,
12031298 },
12041299 PubKey : batchKey ,
12051300 },
1206- HeightHint : uint32 (dbBatch .HeightHint ),
1207- CreationTime : dbBatch .CreationTimeUnix .UTC (),
1301+ HeightHint : uint32 (dbBatch .HeightHint ),
1302+ CreationTime : dbBatch .CreationTimeUnix .UTC (),
1303+ UniverseCommitments : dbBatch .UniverseCommitments ,
12081304 }
12091305
12101306 batchState , err := tapgarden .NewBatchState (uint8 (dbBatch .BatchState ))
@@ -1336,12 +1432,9 @@ func marshalMintingBatch(ctx context.Context, q PendingAssetStore,
13361432 "genesis packet" )
13371433 }
13381434
1339- anchorOutputIndex := uint32 (0 )
1340- if batch .GenesisPacket .ChangeOutputIndex == 0 {
1341- anchorOutputIndex = 1
1342- }
1435+ assetAnchorOutIdx := batch .GenesisPacket .AssetAnchorOutIdx
13431436 genesisTx := batch .GenesisPacket .Pkt .UnsignedTx
1344- genesisScript := genesisTx .TxOut [anchorOutputIndex ].PkScript
1437+ genesisScript := genesisTx .TxOut [assetAnchorOutIdx ].PkScript
13451438 tapscriptSibling := batch .TapSibling ()
13461439 batch .RootAssetCommitment , err = fetchAssetSprouts (
13471440 ctx , q , dbBatch .RawKey , tapscriptSibling , genesisScript ,
0 commit comments