@@ -10,6 +10,7 @@ import (
1010 "github.com/btcsuite/btcd/txscript"
1111 "github.com/lightninglabs/taproot-assets/asset"
1212 "github.com/lightninglabs/taproot-assets/commitment"
13+ "github.com/lightninglabs/taproot-assets/fn"
1314 "github.com/lightninglabs/taproot-assets/proof"
1415 "github.com/lightninglabs/taproot-assets/tapscript"
1516 "github.com/lightninglabs/taproot-assets/tapsend"
@@ -75,6 +76,62 @@ type MintingBatch struct {
7576 taprootAssetScriptRoot []byte
7677}
7778
79+ type VerboseBatch struct {
80+ // CreationTime is the time that this batch was created.
81+ CreationTime time.Time
82+
83+ // HeightHint is the recorded block height at time of creating this
84+ // batch. We use it to know where to start looking for the signed batch
85+ // transaction.
86+ HeightHint uint32
87+
88+ // batchState is the state of the batch.
89+ batchState atomic.Uint32
90+
91+ // BatchKey is the unique identifier for a batch.
92+ BatchKey keychain.KeyDescriptor
93+
94+ // Seedlings is the set of unsealed seedlings for this batch. This maps
95+ // an asset's name to the seedling itself.
96+ //
97+ // NOTE: This field is only set if the state is BatchStateFrozen or
98+ // BatchStatePending.
99+ Seedlings map [string ]* UnsealedSeedling
100+
101+ // GenesisPacket is the funded genesis packet that may or may not be
102+ // fully signed. When broadcast, this will create all assets stored
103+ // within this batch.
104+ GenesisPacket * tapsend.FundedPsbt
105+
106+ // RootAssetCommitment is the root Taproot Asset commitment for all the
107+ // assets contained in this batch.
108+ //
109+ // NOTE: This field is only set if the state is beyond
110+ // BatchStateCommitted.
111+ RootAssetCommitment * commitment.TapCommitment
112+
113+ // AssetMetas maps the serialized script key of an asset to the meta
114+ // reveal for that asset, if it has one.
115+ AssetMetas AssetMetas
116+
117+ // mintingPubKey is the top-level Taproot output key that will be used
118+ // to commit to the Taproot Asset commitment above.
119+ mintingPubKey * btcec.PublicKey
120+
121+ // tapSibling is an optional root hash of a tapscript tree that will be
122+ // used with the taprootAssetScriptRoot to construct the mintingPubKey.
123+ tapSibling * chainhash.Hash
124+
125+ // taprootAssetScriptRoot is the root hash of the Taproot Asset
126+ // commitment. If this is nil, then the mintingPubKey will be as well.
127+ taprootAssetScriptRoot []byte
128+ }
129+
130+ type MinterBatch interface {
131+ * MintingBatch | * VerboseBatch
132+ State () BatchState
133+ }
134+
78135// validateGroupAnchor checks if the group anchor for a seedling is valid.
79136// A valid anchor must already be part of the batch and have emission enabled.
80137func (m * MintingBatch ) validateGroupAnchor (s * Seedling ) error {
@@ -173,6 +230,84 @@ func (m *MintingBatch) UpdateTapSibling(sibling *chainhash.Hash) {
173230 m .tapSibling = sibling
174231}
175232
233+ // IsFunded checks if the batch already has a funded genesis packet.
176234func (m * MintingBatch ) IsFunded () bool {
177235 return m .GenesisPacket != nil
178236}
237+
238+ // HasSeedlings checks if the batch has any seedlings. A batch with no seedlings
239+ // cannot be sealed nor finalized.
240+ func (m * MintingBatch ) HasSeedlings () bool {
241+ return len (m .Seedlings ) != 0
242+ }
243+
244+ func (m * MintingBatch ) ToVerbose () * VerboseBatch {
245+ newBatch := & VerboseBatch {
246+ CreationTime : m .CreationTime ,
247+ HeightHint : m .HeightHint ,
248+ BatchKey : m .BatchKey ,
249+ GenesisPacket : m .GenesisPacket ,
250+ RootAssetCommitment : m .RootAssetCommitment ,
251+ AssetMetas : m .AssetMetas ,
252+ mintingPubKey : m .mintingPubKey ,
253+ tapSibling : m .tapSibling ,
254+ taprootAssetScriptRoot : m .taprootAssetScriptRoot ,
255+ }
256+ newBatch .batchState .Store (uint32 (m .State ()))
257+ seedlings := make (map [string ]* UnsealedSeedling , len (m .Seedlings ))
258+ toUnsealed := func (seedlingName string , seedling * Seedling ) {
259+ seedlings [seedlingName ] = & UnsealedSeedling {
260+ seedling ,
261+ nil ,
262+ }
263+ }
264+ fn .ForEachMapItem (m .Seedlings , toUnsealed )
265+
266+ newBatch .Seedlings = seedlings
267+
268+ return newBatch
269+ }
270+
271+ func (v * VerboseBatch ) ToMintingBatch () * MintingBatch {
272+ newBatch := & MintingBatch {
273+ CreationTime : v .CreationTime ,
274+ HeightHint : v .HeightHint ,
275+ BatchKey : v .BatchKey ,
276+ GenesisPacket : v .GenesisPacket ,
277+ RootAssetCommitment : v .RootAssetCommitment ,
278+ AssetMetas : v .AssetMetas ,
279+ mintingPubKey : v .mintingPubKey ,
280+ tapSibling : v .tapSibling ,
281+ taprootAssetScriptRoot : v .taprootAssetScriptRoot ,
282+ }
283+ newBatch .batchState .Store (uint32 (v .State ()))
284+ seedlings := make (map [string ]* Seedling , len (v .Seedlings ))
285+ toUnsealed := func (seedlingName string , seedling * UnsealedSeedling ) {
286+ seedlings [seedlingName ] = seedling .Seedling
287+ }
288+ fn .ForEachMapItem (v .Seedlings , toUnsealed )
289+
290+ newBatch .Seedlings = seedlings
291+
292+ return newBatch
293+ }
294+
295+ // State returns the private state of the batch.
296+ func (v * VerboseBatch ) State () BatchState {
297+ currentBatchState := v .batchState .Load ()
298+
299+ // Drop the error when converting the stored state to a BatchState, as
300+ // we verify the batch state before storing it.
301+ batchStateCopy , _ := NewBatchState (uint8 (currentBatchState ))
302+ return batchStateCopy
303+ }
304+
305+ // TapSibling returns the optional tapscript sibling for the batch, which is a
306+ // root hash of a tapscript tree.
307+ func (v * VerboseBatch ) TapSibling () []byte {
308+ if v .tapSibling == nil {
309+ return nil
310+ }
311+
312+ return v .tapSibling .CloneBytes ()
313+ }
0 commit comments