@@ -673,6 +673,13 @@ type HtlcScriptTree struct {
673673 // TimeoutTapLeaf is the tapleaf for the timeout path.
674674 TimeoutTapLeaf txscript.TapLeaf
675675
676+ // AuxLeaf is an auxiliary leaf that can be used to extend the base
677+ // HTLC script tree with new spend paths, or just as extra commitment
678+ // space. When present, this leaf will always be in the left-most or
679+ // right-most area of the tapscript tree.
680+ AuxLeaf AuxTapLeaf
681+
682+ // htlcType is the type of HTLC script this is.
676683 htlcType htlcType
677684}
678685
@@ -748,8 +755,8 @@ var _ TapscriptDescriptor = (*HtlcScriptTree)(nil)
748755// senderHtlcTapScriptTree builds the tapscript tree which is used to anchor
749756// the HTLC key for HTLCs on the sender's commitment.
750757func senderHtlcTapScriptTree (senderHtlcKey , receiverHtlcKey ,
751- revokeKey * btcec.PublicKey , payHash []byte ,
752- hType htlcType ) (* HtlcScriptTree , error ) {
758+ revokeKey * btcec.PublicKey , payHash []byte , hType htlcType ,
759+ auxLeaf AuxTapLeaf ) (* HtlcScriptTree , error ) {
753760
754761 // First, we'll obtain the tap leaves for both the success and timeout
755762 // path.
@@ -766,11 +773,14 @@ func senderHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
766773 return nil , err
767774 }
768775
776+ tapLeaves := []txscript.TapLeaf {successTapLeaf , timeoutTapLeaf }
777+ auxLeaf .WhenSome (func (l txscript.TapLeaf ) {
778+ tapLeaves = append (tapLeaves , l )
779+ })
780+
769781 // With the two leaves obtained, we'll now make the tapscript tree,
770782 // then obtain the root from that
771- tapscriptTree := txscript .AssembleTaprootScriptTree (
772- successTapLeaf , timeoutTapLeaf ,
773- )
783+ tapscriptTree := txscript .AssembleTaprootScriptTree (tapLeaves ... )
774784
775785 tapScriptRoot := tapscriptTree .RootNode .TapHash ()
776786
@@ -789,6 +799,7 @@ func senderHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
789799 },
790800 SuccessTapLeaf : successTapLeaf ,
791801 TimeoutTapLeaf : timeoutTapLeaf ,
802+ AuxLeaf : auxLeaf ,
792803 htlcType : hType ,
793804 }, nil
794805}
@@ -822,8 +833,8 @@ func senderHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
822833// The top level keyspend key is the revocation key, which allows a defender to
823834// unilaterally spend the created output.
824835func SenderHTLCScriptTaproot (senderHtlcKey , receiverHtlcKey ,
825- revokeKey * btcec.PublicKey , payHash []byte ,
826- localCommit bool ) (* HtlcScriptTree , error ) {
836+ revokeKey * btcec.PublicKey , payHash []byte , localCommit bool ,
837+ auxLeaf AuxTapLeaf ) (* HtlcScriptTree , error ) {
827838
828839 var hType htlcType
829840 if localCommit {
@@ -836,8 +847,8 @@ func SenderHTLCScriptTaproot(senderHtlcKey, receiverHtlcKey,
836847 // tree that includes the top level output script, as well as the two
837848 // tap leaf paths.
838849 return senderHtlcTapScriptTree (
839- senderHtlcKey , receiverHtlcKey , revokeKey , payHash ,
840- hType ,
850+ senderHtlcKey , receiverHtlcKey , revokeKey , payHash , hType ,
851+ auxLeaf ,
841852 )
842853}
843854
@@ -1307,8 +1318,8 @@ func ReceiverHtlcTapLeafSuccess(receiverHtlcKey *btcec.PublicKey,
13071318// receiverHtlcTapScriptTree builds the tapscript tree which is used to anchor
13081319// the HTLC key for HTLCs on the receiver's commitment.
13091320func receiverHtlcTapScriptTree (senderHtlcKey , receiverHtlcKey ,
1310- revokeKey * btcec.PublicKey , payHash []byte ,
1311- cltvExpiry uint32 , hType htlcType ) (* HtlcScriptTree , error ) {
1321+ revokeKey * btcec.PublicKey , payHash []byte , cltvExpiry uint32 ,
1322+ hType htlcType , auxLeaf AuxTapLeaf ) (* HtlcScriptTree , error ) {
13121323
13131324 // First, we'll obtain the tap leaves for both the success and timeout
13141325 // path.
@@ -1325,11 +1336,14 @@ func receiverHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
13251336 return nil , err
13261337 }
13271338
1339+ tapLeaves := []txscript.TapLeaf {timeoutTapLeaf , successTapLeaf }
1340+ auxLeaf .WhenSome (func (l txscript.TapLeaf ) {
1341+ tapLeaves = append (tapLeaves , l )
1342+ })
1343+
13281344 // With the two leaves obtained, we'll now make the tapscript tree,
13291345 // then obtain the root from that
1330- tapscriptTree := txscript .AssembleTaprootScriptTree (
1331- timeoutTapLeaf , successTapLeaf ,
1332- )
1346+ tapscriptTree := txscript .AssembleTaprootScriptTree (tapLeaves ... )
13331347
13341348 tapScriptRoot := tapscriptTree .RootNode .TapHash ()
13351349
@@ -1348,6 +1362,7 @@ func receiverHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
13481362 },
13491363 SuccessTapLeaf : successTapLeaf ,
13501364 TimeoutTapLeaf : timeoutTapLeaf ,
1365+ AuxLeaf : auxLeaf ,
13511366 htlcType : hType ,
13521367 }, nil
13531368}
@@ -1382,7 +1397,8 @@ func receiverHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
13821397// the tap leaf are returned.
13831398func ReceiverHTLCScriptTaproot (cltvExpiry uint32 ,
13841399 senderHtlcKey , receiverHtlcKey , revocationKey * btcec.PublicKey ,
1385- payHash []byte , ourCommit bool ) (* HtlcScriptTree , error ) {
1400+ payHash []byte , ourCommit bool , auxLeaf AuxTapLeaf ) (* HtlcScriptTree ,
1401+ error ) {
13861402
13871403 var hType htlcType
13881404 if ourCommit {
@@ -1396,7 +1412,7 @@ func ReceiverHTLCScriptTaproot(cltvExpiry uint32,
13961412 // tap leaf paths.
13971413 return receiverHtlcTapScriptTree (
13981414 senderHtlcKey , receiverHtlcKey , revocationKey , payHash ,
1399- cltvExpiry , hType ,
1415+ cltvExpiry , hType , auxLeaf ,
14001416 )
14011417}
14021418
@@ -1625,9 +1641,9 @@ func TaprootSecondLevelTapLeaf(delayKey *btcec.PublicKey,
16251641}
16261642
16271643// SecondLevelHtlcTapscriptTree construct the indexed tapscript tree needed to
1628- // generate the taptweak to create the final output and also control block.
1629- func SecondLevelHtlcTapscriptTree (delayKey * btcec.PublicKey ,
1630- csvDelay uint32 ) (* txscript.IndexedTapScriptTree , error ) {
1644+ // generate the tap tweak to create the final output and also control block.
1645+ func SecondLevelHtlcTapscriptTree (delayKey * btcec.PublicKey , csvDelay uint32 ,
1646+ auxLeaf AuxTapLeaf ) (* txscript.IndexedTapScriptTree , error ) {
16311647
16321648 // First grab the second level leaf script we need to create the top
16331649 // level output.
@@ -1636,9 +1652,14 @@ func SecondLevelHtlcTapscriptTree(delayKey *btcec.PublicKey,
16361652 return nil , err
16371653 }
16381654
1655+ tapLeaves := []txscript.TapLeaf {secondLevelTapLeaf }
1656+ auxLeaf .WhenSome (func (l txscript.TapLeaf ) {
1657+ tapLeaves = append (tapLeaves , l )
1658+ })
1659+
16391660 // Now that we have the sole second level script, we can create the
16401661 // tapscript tree that commits to both the leaves.
1641- return txscript .AssembleTaprootScriptTree (secondLevelTapLeaf ), nil
1662+ return txscript .AssembleTaprootScriptTree (tapLeaves ... ), nil
16421663}
16431664
16441665// TaprootSecondLevelHtlcScript is the uniform script that's used as the output
@@ -1658,12 +1679,12 @@ func SecondLevelHtlcTapscriptTree(delayKey *btcec.PublicKey,
16581679//
16591680// The keyspend path require knowledge of the top level revocation private key.
16601681func TaprootSecondLevelHtlcScript (revokeKey , delayKey * btcec.PublicKey ,
1661- csvDelay uint32 ) (* btcec.PublicKey , error ) {
1682+ csvDelay uint32 , auxLeaf AuxTapLeaf ) (* btcec.PublicKey , error ) {
16621683
16631684 // First, we'll make the tapscript tree that commits to the redemption
16641685 // path.
16651686 tapScriptTree , err := SecondLevelHtlcTapscriptTree (
1666- delayKey , csvDelay ,
1687+ delayKey , csvDelay , auxLeaf ,
16671688 )
16681689 if err != nil {
16691690 return nil , err
@@ -1688,17 +1709,21 @@ type SecondLevelScriptTree struct {
16881709
16891710 // SuccessTapLeaf is the tapleaf for the redemption path.
16901711 SuccessTapLeaf txscript.TapLeaf
1712+
1713+ // AuxLeaf is an optional leaf that can be used to extend the script
1714+ // tree.
1715+ AuxLeaf AuxTapLeaf
16911716}
16921717
16931718// TaprootSecondLevelScriptTree constructs the tapscript tree used to spend the
16941719// second level HTLC output.
16951720func TaprootSecondLevelScriptTree (revokeKey , delayKey * btcec.PublicKey ,
1696- csvDelay uint32 ) (* SecondLevelScriptTree , error ) {
1721+ csvDelay uint32 , auxLeaf AuxTapLeaf ) (* SecondLevelScriptTree , error ) {
16971722
16981723 // First, we'll make the tapscript tree that commits to the redemption
16991724 // path.
17001725 tapScriptTree , err := SecondLevelHtlcTapscriptTree (
1701- delayKey , csvDelay ,
1726+ delayKey , csvDelay , auxLeaf ,
17021727 )
17031728 if err != nil {
17041729 return nil , err
@@ -1719,6 +1744,7 @@ func TaprootSecondLevelScriptTree(revokeKey, delayKey *btcec.PublicKey,
17191744 InternalKey : revokeKey ,
17201745 },
17211746 SuccessTapLeaf : tapScriptTree .LeafMerkleProofs [0 ].TapLeaf ,
1747+ AuxLeaf : auxLeaf ,
17221748 }, nil
17231749}
17241750
@@ -2095,6 +2121,12 @@ type CommitScriptTree struct {
20952121 // RevocationLeaf is the leaf used to spend the output with the
20962122 // revocation key signature.
20972123 RevocationLeaf txscript.TapLeaf
2124+
2125+ // AuxLeaf is an auxiliary leaf that can be used to extend the base
2126+ // commitment script tree with new spend paths, or just as extra
2127+ // commitment space. When present, this leaf will always be in the
2128+ // left-most or right-most area of the tapscript tree.
2129+ AuxLeaf AuxTapLeaf
20982130}
20992131
21002132// A compile time check to ensure CommitScriptTree implements the
@@ -2154,8 +2186,9 @@ func (c *CommitScriptTree) CtrlBlockForPath(path ScriptPath,
21542186
21552187// NewLocalCommitScriptTree returns a new CommitScript tree that can be used to
21562188// create and spend the commitment output for the local party.
2157- func NewLocalCommitScriptTree (csvTimeout uint32 ,
2158- selfKey , revokeKey * btcec.PublicKey ) (* CommitScriptTree , error ) {
2189+ func NewLocalCommitScriptTree (csvTimeout uint32 , selfKey ,
2190+ revokeKey * btcec.PublicKey , auxLeaf AuxTapLeaf ) (* CommitScriptTree ,
2191+ error ) {
21592192
21602193 // First, we'll need to construct the tapLeaf that'll be our delay CSV
21612194 // clause.
@@ -2175,9 +2208,13 @@ func NewLocalCommitScriptTree(csvTimeout uint32,
21752208 // the two leaves, and then obtain a root from that.
21762209 delayTapLeaf := txscript .NewBaseTapLeaf (delayScript )
21772210 revokeTapLeaf := txscript .NewBaseTapLeaf (revokeScript )
2178- tapScriptTree := txscript .AssembleTaprootScriptTree (
2179- delayTapLeaf , revokeTapLeaf ,
2180- )
2211+
2212+ tapLeaves := []txscript.TapLeaf {delayTapLeaf , revokeTapLeaf }
2213+ auxLeaf .WhenSome (func (l txscript.TapLeaf ) {
2214+ tapLeaves = append (tapLeaves , l )
2215+ })
2216+
2217+ tapScriptTree := txscript .AssembleTaprootScriptTree (tapLeaves ... )
21812218 tapScriptRoot := tapScriptTree .RootNode .TapHash ()
21822219
21832220 // Now that we have our root, we can arrive at the final output script
@@ -2195,6 +2232,7 @@ func NewLocalCommitScriptTree(csvTimeout uint32,
21952232 },
21962233 SettleLeaf : delayTapLeaf ,
21972234 RevocationLeaf : revokeTapLeaf ,
2235+ AuxLeaf : auxLeaf ,
21982236 }, nil
21992237}
22002238
@@ -2264,7 +2302,7 @@ func TaprootCommitScriptToSelf(csvTimeout uint32,
22642302 selfKey , revokeKey * btcec.PublicKey ) (* btcec.PublicKey , error ) {
22652303
22662304 commitScriptTree , err := NewLocalCommitScriptTree (
2267- csvTimeout , selfKey , revokeKey ,
2305+ csvTimeout , selfKey , revokeKey , NoneTapLeaf (),
22682306 )
22692307 if err != nil {
22702308 return nil , err
@@ -2593,7 +2631,7 @@ func CommitScriptToRemoteConfirmed(key *btcec.PublicKey) ([]byte, error) {
25932631// NewRemoteCommitScriptTree constructs a new script tree for the remote party
25942632// to sweep their funds after a hard coded 1 block delay.
25952633func NewRemoteCommitScriptTree (remoteKey * btcec.PublicKey ,
2596- ) (* CommitScriptTree , error ) {
2634+ auxLeaf AuxTapLeaf ) (* CommitScriptTree , error ) {
25972635
25982636 // First, construct the remote party's tapscript they'll use to sweep
25992637 // their outputs.
@@ -2609,10 +2647,16 @@ func NewRemoteCommitScriptTree(remoteKey *btcec.PublicKey,
26092647 return nil , err
26102648 }
26112649
2650+ tapLeaf := txscript .NewBaseTapLeaf (remoteScript )
2651+
2652+ tapLeaves := []txscript.TapLeaf {tapLeaf }
2653+ auxLeaf .WhenSome (func (l txscript.TapLeaf ) {
2654+ tapLeaves = append (tapLeaves , l )
2655+ })
2656+
26122657 // With this script constructed, we'll map that into a tapLeaf, then
26132658 // make a new tapscript root from that.
2614- tapLeaf := txscript .NewBaseTapLeaf (remoteScript )
2615- tapScriptTree := txscript .AssembleTaprootScriptTree (tapLeaf )
2659+ tapScriptTree := txscript .AssembleTaprootScriptTree (tapLeaves ... )
26162660 tapScriptRoot := tapScriptTree .RootNode .TapHash ()
26172661
26182662 // Now that we have our root, we can arrive at the final output script
@@ -2629,6 +2673,7 @@ func NewRemoteCommitScriptTree(remoteKey *btcec.PublicKey,
26292673 InternalKey : & TaprootNUMSKey ,
26302674 },
26312675 SettleLeaf : tapLeaf ,
2676+ AuxLeaf : auxLeaf ,
26322677 }, nil
26332678}
26342679
@@ -2645,9 +2690,9 @@ func NewRemoteCommitScriptTree(remoteKey *btcec.PublicKey,
26452690// <remotepubkey> OP_CHECKSIG
26462691// 1 OP_CHECKSEQUENCEVERIFY OP_DROP
26472692func TaprootCommitScriptToRemote (remoteKey * btcec.PublicKey ,
2648- ) (* btcec.PublicKey , error ) {
2693+ auxLeaf AuxTapLeaf ) (* btcec.PublicKey , error ) {
26492694
2650- commitScriptTree , err := NewRemoteCommitScriptTree (remoteKey )
2695+ commitScriptTree , err := NewRemoteCommitScriptTree (remoteKey , auxLeaf )
26512696 if err != nil {
26522697 return nil , err
26532698 }
0 commit comments