mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-10-10 17:23:16 +02:00
input+lnwallet: update taproot scripts to accept optional aux leaf
In this commit, we update all the taproot scripts to also accept an optional aux leaf. This aux leaf can be used to add more redemption paths for advanced channels, or just as an extra commitment space.
This commit is contained in:
committed by
Oliver Gugger
parent
8588c9bfd7
commit
1aae47fd71
@@ -646,6 +646,13 @@ type HtlcScriptTree struct {
|
||||
// TimeoutTapLeaf is the tapleaf for the timeout path.
|
||||
TimeoutTapLeaf txscript.TapLeaf
|
||||
|
||||
// AuxLeaf is an auxiliary leaf that can be used to extend the base
|
||||
// HTLC script tree with new spend paths, or just as extra commitment
|
||||
// space. When present, this leaf will always be in the right-most area
|
||||
// of the tapscript tree.
|
||||
AuxLeaf AuxTapLeaf
|
||||
|
||||
// htlcType is the type of HTLC script this is.
|
||||
htlcType htlcType
|
||||
}
|
||||
|
||||
@@ -726,8 +733,8 @@ var _ TapscriptDescriptor = (*HtlcScriptTree)(nil)
|
||||
// senderHtlcTapScriptTree builds the tapscript tree which is used to anchor
|
||||
// the HTLC key for HTLCs on the sender's commitment.
|
||||
func senderHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
|
||||
revokeKey *btcec.PublicKey, payHash []byte,
|
||||
hType htlcType) (*HtlcScriptTree, error) {
|
||||
revokeKey *btcec.PublicKey, payHash []byte, hType htlcType,
|
||||
auxLeaf AuxTapLeaf) (*HtlcScriptTree, error) {
|
||||
|
||||
// First, we'll obtain the tap leaves for both the success and timeout
|
||||
// path.
|
||||
@@ -744,11 +751,14 @@ func senderHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tapLeaves := []txscript.TapLeaf{successTapLeaf, timeoutTapLeaf}
|
||||
auxLeaf.WhenSome(func(l txscript.TapLeaf) {
|
||||
tapLeaves = append(tapLeaves, l)
|
||||
})
|
||||
|
||||
// With the two leaves obtained, we'll now make the tapscript tree,
|
||||
// then obtain the root from that
|
||||
tapscriptTree := txscript.AssembleTaprootScriptTree(
|
||||
successTapLeaf, timeoutTapLeaf,
|
||||
)
|
||||
tapscriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...)
|
||||
|
||||
tapScriptRoot := tapscriptTree.RootNode.TapHash()
|
||||
|
||||
@@ -767,6 +777,7 @@ func senderHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
|
||||
},
|
||||
SuccessTapLeaf: successTapLeaf,
|
||||
TimeoutTapLeaf: timeoutTapLeaf,
|
||||
AuxLeaf: auxLeaf,
|
||||
htlcType: hType,
|
||||
}, nil
|
||||
}
|
||||
@@ -801,7 +812,8 @@ func senderHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
|
||||
// unilaterally spend the created output.
|
||||
func SenderHTLCScriptTaproot(senderHtlcKey, receiverHtlcKey,
|
||||
revokeKey *btcec.PublicKey, payHash []byte,
|
||||
whoseCommit lntypes.ChannelParty) (*HtlcScriptTree, error) {
|
||||
whoseCommit lntypes.ChannelParty, auxLeaf AuxTapLeaf) (*HtlcScriptTree,
|
||||
error) {
|
||||
|
||||
var hType htlcType
|
||||
if whoseCommit.IsLocal() {
|
||||
@@ -814,8 +826,8 @@ func SenderHTLCScriptTaproot(senderHtlcKey, receiverHtlcKey,
|
||||
// tree that includes the top level output script, as well as the two
|
||||
// tap leaf paths.
|
||||
return senderHtlcTapScriptTree(
|
||||
senderHtlcKey, receiverHtlcKey, revokeKey, payHash,
|
||||
hType,
|
||||
senderHtlcKey, receiverHtlcKey, revokeKey, payHash, hType,
|
||||
auxLeaf,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1285,8 +1297,8 @@ func ReceiverHtlcTapLeafSuccess(receiverHtlcKey *btcec.PublicKey,
|
||||
// receiverHtlcTapScriptTree builds the tapscript tree which is used to anchor
|
||||
// the HTLC key for HTLCs on the receiver's commitment.
|
||||
func receiverHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
|
||||
revokeKey *btcec.PublicKey, payHash []byte,
|
||||
cltvExpiry uint32, hType htlcType) (*HtlcScriptTree, error) {
|
||||
revokeKey *btcec.PublicKey, payHash []byte, cltvExpiry uint32,
|
||||
hType htlcType, auxLeaf AuxTapLeaf) (*HtlcScriptTree, error) {
|
||||
|
||||
// First, we'll obtain the tap leaves for both the success and timeout
|
||||
// path.
|
||||
@@ -1303,11 +1315,14 @@ func receiverHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tapLeaves := []txscript.TapLeaf{timeoutTapLeaf, successTapLeaf}
|
||||
auxLeaf.WhenSome(func(l txscript.TapLeaf) {
|
||||
tapLeaves = append(tapLeaves, l)
|
||||
})
|
||||
|
||||
// With the two leaves obtained, we'll now make the tapscript tree,
|
||||
// then obtain the root from that
|
||||
tapscriptTree := txscript.AssembleTaprootScriptTree(
|
||||
timeoutTapLeaf, successTapLeaf,
|
||||
)
|
||||
tapscriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...)
|
||||
|
||||
tapScriptRoot := tapscriptTree.RootNode.TapHash()
|
||||
|
||||
@@ -1326,6 +1341,7 @@ func receiverHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
|
||||
},
|
||||
SuccessTapLeaf: successTapLeaf,
|
||||
TimeoutTapLeaf: timeoutTapLeaf,
|
||||
AuxLeaf: auxLeaf,
|
||||
htlcType: hType,
|
||||
}, nil
|
||||
}
|
||||
@@ -1361,7 +1377,7 @@ func receiverHtlcTapScriptTree(senderHtlcKey, receiverHtlcKey,
|
||||
func ReceiverHTLCScriptTaproot(cltvExpiry uint32,
|
||||
senderHtlcKey, receiverHtlcKey, revocationKey *btcec.PublicKey,
|
||||
payHash []byte, whoseCommit lntypes.ChannelParty,
|
||||
) (*HtlcScriptTree, error) {
|
||||
auxLeaf AuxTapLeaf) (*HtlcScriptTree, error) {
|
||||
|
||||
var hType htlcType
|
||||
if whoseCommit.IsLocal() {
|
||||
@@ -1375,7 +1391,7 @@ func ReceiverHTLCScriptTaproot(cltvExpiry uint32,
|
||||
// tap leaf paths.
|
||||
return receiverHtlcTapScriptTree(
|
||||
senderHtlcKey, receiverHtlcKey, revocationKey, payHash,
|
||||
cltvExpiry, hType,
|
||||
cltvExpiry, hType, auxLeaf,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1604,9 +1620,9 @@ func TaprootSecondLevelTapLeaf(delayKey *btcec.PublicKey,
|
||||
}
|
||||
|
||||
// SecondLevelHtlcTapscriptTree construct the indexed tapscript tree needed to
|
||||
// generate the taptweak to create the final output and also control block.
|
||||
func SecondLevelHtlcTapscriptTree(delayKey *btcec.PublicKey,
|
||||
csvDelay uint32) (*txscript.IndexedTapScriptTree, error) {
|
||||
// generate the tap tweak to create the final output and also control block.
|
||||
func SecondLevelHtlcTapscriptTree(delayKey *btcec.PublicKey, csvDelay uint32,
|
||||
auxLeaf AuxTapLeaf) (*txscript.IndexedTapScriptTree, error) {
|
||||
|
||||
// First grab the second level leaf script we need to create the top
|
||||
// level output.
|
||||
@@ -1615,9 +1631,14 @@ func SecondLevelHtlcTapscriptTree(delayKey *btcec.PublicKey,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tapLeaves := []txscript.TapLeaf{secondLevelTapLeaf}
|
||||
auxLeaf.WhenSome(func(l txscript.TapLeaf) {
|
||||
tapLeaves = append(tapLeaves, l)
|
||||
})
|
||||
|
||||
// Now that we have the sole second level script, we can create the
|
||||
// tapscript tree that commits to both the leaves.
|
||||
return txscript.AssembleTaprootScriptTree(secondLevelTapLeaf), nil
|
||||
return txscript.AssembleTaprootScriptTree(tapLeaves...), nil
|
||||
}
|
||||
|
||||
// TaprootSecondLevelHtlcScript is the uniform script that's used as the output
|
||||
@@ -1637,12 +1658,12 @@ func SecondLevelHtlcTapscriptTree(delayKey *btcec.PublicKey,
|
||||
//
|
||||
// The keyspend path require knowledge of the top level revocation private key.
|
||||
func TaprootSecondLevelHtlcScript(revokeKey, delayKey *btcec.PublicKey,
|
||||
csvDelay uint32) (*btcec.PublicKey, error) {
|
||||
csvDelay uint32, auxLeaf AuxTapLeaf) (*btcec.PublicKey, error) {
|
||||
|
||||
// First, we'll make the tapscript tree that commits to the redemption
|
||||
// path.
|
||||
tapScriptTree, err := SecondLevelHtlcTapscriptTree(
|
||||
delayKey, csvDelay,
|
||||
delayKey, csvDelay, auxLeaf,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1667,17 +1688,21 @@ type SecondLevelScriptTree struct {
|
||||
|
||||
// SuccessTapLeaf is the tapleaf for the redemption path.
|
||||
SuccessTapLeaf txscript.TapLeaf
|
||||
|
||||
// AuxLeaf is an optional leaf that can be used to extend the script
|
||||
// tree.
|
||||
AuxLeaf AuxTapLeaf
|
||||
}
|
||||
|
||||
// TaprootSecondLevelScriptTree constructs the tapscript tree used to spend the
|
||||
// second level HTLC output.
|
||||
func TaprootSecondLevelScriptTree(revokeKey, delayKey *btcec.PublicKey,
|
||||
csvDelay uint32) (*SecondLevelScriptTree, error) {
|
||||
csvDelay uint32, auxLeaf AuxTapLeaf) (*SecondLevelScriptTree, error) {
|
||||
|
||||
// First, we'll make the tapscript tree that commits to the redemption
|
||||
// path.
|
||||
tapScriptTree, err := SecondLevelHtlcTapscriptTree(
|
||||
delayKey, csvDelay,
|
||||
delayKey, csvDelay, auxLeaf,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1698,6 +1723,7 @@ func TaprootSecondLevelScriptTree(revokeKey, delayKey *btcec.PublicKey,
|
||||
InternalKey: revokeKey,
|
||||
},
|
||||
SuccessTapLeaf: tapScriptTree.LeafMerkleProofs[0].TapLeaf,
|
||||
AuxLeaf: auxLeaf,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -2079,6 +2105,12 @@ type CommitScriptTree struct {
|
||||
// RevocationLeaf is the leaf used to spend the output with the
|
||||
// revocation key signature.
|
||||
RevocationLeaf txscript.TapLeaf
|
||||
|
||||
// AuxLeaf is an auxiliary leaf that can be used to extend the base
|
||||
// commitment script tree with new spend paths, or just as extra
|
||||
// commitment space. When present, this leaf will always be in the
|
||||
// left-most or right-most area of the tapscript tree.
|
||||
AuxLeaf AuxTapLeaf
|
||||
}
|
||||
|
||||
// A compile time check to ensure CommitScriptTree implements the
|
||||
@@ -2143,8 +2175,9 @@ func (c *CommitScriptTree) Tree() ScriptTree {
|
||||
|
||||
// NewLocalCommitScriptTree returns a new CommitScript tree that can be used to
|
||||
// create and spend the commitment output for the local party.
|
||||
func NewLocalCommitScriptTree(csvTimeout uint32,
|
||||
selfKey, revokeKey *btcec.PublicKey) (*CommitScriptTree, error) {
|
||||
func NewLocalCommitScriptTree(csvTimeout uint32, selfKey,
|
||||
revokeKey *btcec.PublicKey, auxLeaf AuxTapLeaf) (*CommitScriptTree,
|
||||
error) {
|
||||
|
||||
// First, we'll need to construct the tapLeaf that'll be our delay CSV
|
||||
// clause.
|
||||
@@ -2164,9 +2197,13 @@ func NewLocalCommitScriptTree(csvTimeout uint32,
|
||||
// the two leaves, and then obtain a root from that.
|
||||
delayTapLeaf := txscript.NewBaseTapLeaf(delayScript)
|
||||
revokeTapLeaf := txscript.NewBaseTapLeaf(revokeScript)
|
||||
tapScriptTree := txscript.AssembleTaprootScriptTree(
|
||||
delayTapLeaf, revokeTapLeaf,
|
||||
)
|
||||
|
||||
tapLeaves := []txscript.TapLeaf{delayTapLeaf, revokeTapLeaf}
|
||||
auxLeaf.WhenSome(func(l txscript.TapLeaf) {
|
||||
tapLeaves = append(tapLeaves, l)
|
||||
})
|
||||
|
||||
tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...)
|
||||
tapScriptRoot := tapScriptTree.RootNode.TapHash()
|
||||
|
||||
// Now that we have our root, we can arrive at the final output script
|
||||
@@ -2184,6 +2221,7 @@ func NewLocalCommitScriptTree(csvTimeout uint32,
|
||||
},
|
||||
SettleLeaf: delayTapLeaf,
|
||||
RevocationLeaf: revokeTapLeaf,
|
||||
AuxLeaf: auxLeaf,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -2253,7 +2291,7 @@ func TaprootCommitScriptToSelf(csvTimeout uint32,
|
||||
selfKey, revokeKey *btcec.PublicKey) (*btcec.PublicKey, error) {
|
||||
|
||||
commitScriptTree, err := NewLocalCommitScriptTree(
|
||||
csvTimeout, selfKey, revokeKey,
|
||||
csvTimeout, selfKey, revokeKey, NoneTapLeaf(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -2579,7 +2617,7 @@ func CommitScriptToRemoteConfirmed(key *btcec.PublicKey) ([]byte, error) {
|
||||
// NewRemoteCommitScriptTree constructs a new script tree for the remote party
|
||||
// to sweep their funds after a hard coded 1 block delay.
|
||||
func NewRemoteCommitScriptTree(remoteKey *btcec.PublicKey,
|
||||
) (*CommitScriptTree, error) {
|
||||
auxLeaf AuxTapLeaf) (*CommitScriptTree, error) {
|
||||
|
||||
// First, construct the remote party's tapscript they'll use to sweep
|
||||
// their outputs.
|
||||
@@ -2595,10 +2633,16 @@ func NewRemoteCommitScriptTree(remoteKey *btcec.PublicKey,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tapLeaf := txscript.NewBaseTapLeaf(remoteScript)
|
||||
|
||||
tapLeaves := []txscript.TapLeaf{tapLeaf}
|
||||
auxLeaf.WhenSome(func(l txscript.TapLeaf) {
|
||||
tapLeaves = append(tapLeaves, l)
|
||||
})
|
||||
|
||||
// With this script constructed, we'll map that into a tapLeaf, then
|
||||
// make a new tapscript root from that.
|
||||
tapLeaf := txscript.NewBaseTapLeaf(remoteScript)
|
||||
tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaf)
|
||||
tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...)
|
||||
tapScriptRoot := tapScriptTree.RootNode.TapHash()
|
||||
|
||||
// Now that we have our root, we can arrive at the final output script
|
||||
@@ -2615,6 +2659,7 @@ func NewRemoteCommitScriptTree(remoteKey *btcec.PublicKey,
|
||||
InternalKey: &TaprootNUMSKey,
|
||||
},
|
||||
SettleLeaf: tapLeaf,
|
||||
AuxLeaf: auxLeaf,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -2631,9 +2676,9 @@ func NewRemoteCommitScriptTree(remoteKey *btcec.PublicKey,
|
||||
// <remotepubkey> OP_CHECKSIG
|
||||
// 1 OP_CHECKSEQUENCEVERIFY OP_DROP
|
||||
func TaprootCommitScriptToRemote(remoteKey *btcec.PublicKey,
|
||||
) (*btcec.PublicKey, error) {
|
||||
auxLeaf AuxTapLeaf) (*btcec.PublicKey, error) {
|
||||
|
||||
commitScriptTree, err := NewRemoteCommitScriptTree(remoteKey)
|
||||
commitScriptTree, err := NewRemoteCommitScriptTree(remoteKey, auxLeaf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user