@@ -309,6 +309,109 @@ func SignVirtualTx(priv *btcec.PrivateKey, signDesc *lndclient.SignDescriptor,
309309 return sig , nil
310310}
311311
312+ // AssetCustomGroupKey constructs a new asset group key and anchor asset from a
313+ // given asset genesis. The asset group key may also commit to a Tapscript tree
314+ // root. The tree used in that case includes a hash lock and signature lock.
315+ // The validity of that Tapscript tree is set by the caller.
316+ //
317+ // The following group key derivation methods are supported:
318+ //
319+ // BIP86: The group key commits to an empty tapscript tree. Assets can only be
320+ // added to the group with a valid signature from the tweaked group key.
321+ //
322+ // Key-spend: The group key commits to a tapscript tree root, but the witness
323+ // for the group anchor will be a signature using the tweaked group key. Assets
324+ // could later be added to the group with either a signature from the tweaked
325+ // group key or a valid witness for a script in the committed tapscript tree.
326+ //
327+ // Script-spend: The group key commits to a tapscript tree root, and the witness
328+ // for the group anchor is a valid script witness for a script in the tapscript
329+ // tree. Assets could later be added to the group with either a signature from
330+ // the tweaked group key or a valid witness for a script in the committed
331+ // tapscript tree.
332+ func AssetCustomGroupKey (t * testing.T , useHashLock , BIP86 , keySpend ,
333+ validScriptWitness bool , gen Genesis ) * Asset {
334+
335+ t .Helper ()
336+
337+ // Sanity check the custom group key request. If both flags are false,
338+ // the script-spend path will be used.
339+ if BIP86 && keySpend {
340+ require .Fail (t , "Cannot have both BIP 86 and key spend group " +
341+ "key types" )
342+ }
343+
344+ var (
345+ groupKey * GroupKey
346+ err error
347+ )
348+
349+ genID := gen .ID ()
350+ scriptKey := RandScriptKey (t )
351+ protoAsset := RandAssetWithValues (t , gen , nil , scriptKey )
352+
353+ groupPrivKey := test .RandPrivKey (t )
354+ groupInternalKey := groupPrivKey .PubKey ()
355+ genSigner := NewMockGenesisSigner (groupPrivKey )
356+ genBuilder := MockGroupTxBuilder {}
357+
358+ // Manually create and use the singly tweaked key here, to match the
359+ // signing behavior later when using the signing descriptor.
360+ groupSinglyTweakedKey := input .TweakPubKeyWithTweak (
361+ groupInternalKey , genID [:],
362+ )
363+
364+ // Populate the initial parameters for the group key request.
365+ groupReq := GroupKeyRequest {
366+ RawKey : test .PubToKeyDesc (groupInternalKey ),
367+ AnchorGen : gen ,
368+ NewAsset : protoAsset ,
369+ }
370+
371+ // Update the group key request and group key derivation arguments
372+ // to match the requested group key type.
373+ switch {
374+ // Use an empty tapscript and script witness.
375+ case BIP86 :
376+ groupKey , err = DeriveCustomGroupKey (
377+ genSigner , & genBuilder , groupReq , nil , nil ,
378+ )
379+
380+ // Derive a tapscipt root using the default tapscript tree used for
381+ // testing, but use a signature as a witness.
382+ case keySpend :
383+ tapRootHash := test .BuildTapscriptTreeNoReveal (
384+ t , groupSinglyTweakedKey ,
385+ )
386+
387+ groupReq .TapscriptRoot = tapRootHash
388+ groupKey , err = DeriveCustomGroupKey (
389+ genSigner , & genBuilder , groupReq , nil , nil ,
390+ )
391+
392+ // For a script spend, we derive a tapscript root, and create the needed
393+ // tapscript and script witness.
394+ default :
395+ _ , _ , tapLeaf , tapRootHash , witness := test .BuildTapscriptTree (
396+ t , useHashLock , validScriptWitness ,
397+ groupSinglyTweakedKey ,
398+ )
399+
400+ groupReq .TapscriptRoot = tapRootHash
401+ groupKey , err = DeriveCustomGroupKey (
402+ genSigner , & genBuilder , groupReq , tapLeaf , witness ,
403+ )
404+ }
405+
406+ require .NoError (t , err )
407+
408+ return NewAssetNoErr (
409+ t , gen , protoAsset .Amount , protoAsset .LockTime ,
410+ protoAsset .RelativeLockTime , scriptKey , groupKey ,
411+ WithAssetVersion (protoAsset .Version ),
412+ )
413+ }
414+
312415// RandScriptKey creates a random script key for testing.
313416func RandScriptKey (t testing.TB ) ScriptKey {
314417 return NewScriptKey (test .RandPrivKey (t ).PubKey ())
0 commit comments