mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-22 06:21:40 +01:00
lnwallet: add tapscript tree to ScriptInfo
In this commit, we add the tapscript tree to the ScriptInfo struct, as in many cases the caller needs the tree in order to generate the control block or obtain the taptweak which is needed to spend revoked outputs.
This commit is contained in:
parent
a74c30fbdd
commit
a128b74dc1
2 changed files with 59 additions and 29 deletions
|
@ -801,7 +801,6 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
|
|||
ourP2WSH, theirP2WSH []byte
|
||||
ourWitnessScript, theirWitnessScript []byte
|
||||
pd PaymentDescriptor
|
||||
err error
|
||||
chanType = lc.channelState.ChanType
|
||||
)
|
||||
|
||||
|
@ -815,26 +814,30 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
|
|||
htlc.Amt.ToSatoshis(), lc.channelState.LocalChanCfg.DustLimit,
|
||||
)
|
||||
if !isDustLocal && localCommitKeys != nil {
|
||||
ourP2WSH, ourWitnessScript, err = genHtlcScript(
|
||||
scriptInfo, err := genHtlcScript(
|
||||
chanType, htlc.Incoming, true, htlc.RefundTimeout,
|
||||
htlc.RHash, localCommitKeys,
|
||||
)
|
||||
if err != nil {
|
||||
return pd, err
|
||||
}
|
||||
ourP2WSH = scriptInfo.PkScript
|
||||
ourWitnessScript = scriptInfo.WitnessScript
|
||||
}
|
||||
isDustRemote := HtlcIsDust(
|
||||
chanType, htlc.Incoming, false, feeRate,
|
||||
htlc.Amt.ToSatoshis(), lc.channelState.RemoteChanCfg.DustLimit,
|
||||
)
|
||||
if !isDustRemote && remoteCommitKeys != nil {
|
||||
theirP2WSH, theirWitnessScript, err = genHtlcScript(
|
||||
scriptInfo, err := genHtlcScript(
|
||||
chanType, htlc.Incoming, false, htlc.RefundTimeout,
|
||||
htlc.RHash, remoteCommitKeys,
|
||||
)
|
||||
if err != nil {
|
||||
return pd, err
|
||||
}
|
||||
theirP2WSH = scriptInfo.PkScript
|
||||
theirWitnessScript = scriptInfo.WitnessScript
|
||||
}
|
||||
|
||||
// Reconstruct the proper local/remote output indexes from the HTLC's
|
||||
|
@ -1563,7 +1566,7 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
|||
wireMsg.Amount.ToSatoshis(), remoteDustLimit,
|
||||
)
|
||||
if !isDustRemote {
|
||||
theirP2WSH, theirWitnessScript, err := genHtlcScript(
|
||||
scriptInfo, err := genHtlcScript(
|
||||
lc.channelState.ChanType, false, false,
|
||||
wireMsg.Expiry, wireMsg.PaymentHash,
|
||||
remoteCommitKeys,
|
||||
|
@ -1572,8 +1575,8 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
pd.theirPkScript = theirP2WSH
|
||||
pd.theirWitnessScript = theirWitnessScript
|
||||
pd.theirPkScript = scriptInfo.PkScript
|
||||
pd.theirWitnessScript = scriptInfo.WitnessScript
|
||||
}
|
||||
|
||||
// For HTLC's we're offered we'll fetch the original offered HTLC
|
||||
|
@ -2572,7 +2575,7 @@ func createHtlcRetribution(chanState *channeldb.OpenChannel,
|
|||
// HTLC script. Otherwise, is this was an outgoing HTLC that we sent,
|
||||
// then from the PoV of the remote commitment state, they're the
|
||||
// receiver of this HTLC.
|
||||
htlcPkScript, htlcWitnessScript, err := genHtlcScript(
|
||||
scriptInfo, err := genHtlcScript(
|
||||
chanState.ChanType, htlc.Incoming, false,
|
||||
htlc.RefundTimeout, htlc.RHash, keyRing,
|
||||
)
|
||||
|
@ -2585,9 +2588,9 @@ func createHtlcRetribution(chanState *channeldb.OpenChannel,
|
|||
KeyDesc: chanState.LocalChanCfg.
|
||||
RevocationBasePoint,
|
||||
DoubleTweak: commitmentSecret,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
WitnessScript: scriptInfo.WitnessScript,
|
||||
Output: &wire.TxOut{
|
||||
PkScript: htlcPkScript,
|
||||
PkScript: scriptInfo.PkScript,
|
||||
Value: int64(htlc.Amt),
|
||||
},
|
||||
HashType: txscript.SigHashAll,
|
||||
|
@ -6542,15 +6545,17 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||
Index: uint32(htlc.OutputIndex),
|
||||
}
|
||||
|
||||
// First, we'll re-generate the script used to send the HTLC to
|
||||
// the remote party within their commitment transaction.
|
||||
htlcScriptHash, htlcScript, err := genHtlcScript(
|
||||
// First, we'll re-generate the script used to send the HTLC to the
|
||||
// remote party within their commitment transaction.
|
||||
htlcScriptInfo, err := genHtlcScript(
|
||||
chanType, false, localCommit, htlc.RefundTimeout, htlc.RHash,
|
||||
keyRing,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
htlcPkScript := htlcScriptInfo.PkScript
|
||||
htlcWitnessScript := htlcScriptInfo.WitnessScript
|
||||
|
||||
// If we're spending this HTLC output from the remote node's
|
||||
// commitment, then we won't need to go to the second level as our
|
||||
|
@ -6564,9 +6569,9 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||
SweepSignDesc: input.SignDescriptor{
|
||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||
WitnessScript: htlcScript,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: &wire.TxOut{
|
||||
PkScript: htlcScriptHash,
|
||||
PkScript: htlcPkScript,
|
||||
Value: int64(htlc.Amt.ToSatoshis()),
|
||||
},
|
||||
HashType: txscript.SigHashAll,
|
||||
|
@ -6602,7 +6607,7 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||
timeoutSignDesc := input.SignDescriptor{
|
||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||
WitnessScript: htlcScript,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: txOut,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: input.NewTxSigHashesV0Only(timeoutTx),
|
||||
|
@ -6688,7 +6693,7 @@ func newIncomingHtlcResolution(signer input.Signer,
|
|||
|
||||
// First, we'll re-generate the script the remote party used to
|
||||
// send the HTLC to us in their commitment transaction.
|
||||
htlcScriptHash, htlcScript, err := genHtlcScript(
|
||||
scriptInfo, err := genHtlcScript(
|
||||
chanType, true, localCommit, htlc.RefundTimeout, htlc.RHash,
|
||||
keyRing,
|
||||
)
|
||||
|
@ -6696,6 +6701,9 @@ func newIncomingHtlcResolution(signer input.Signer,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
htlcPkScript := scriptInfo.PkScript
|
||||
htlcWitnessScript := scriptInfo.WitnessScript
|
||||
|
||||
// If we're spending this output from the remote node's commitment,
|
||||
// then we can skip the second layer and spend the output directly.
|
||||
if !localCommit {
|
||||
|
@ -6706,9 +6714,9 @@ func newIncomingHtlcResolution(signer input.Signer,
|
|||
SweepSignDesc: input.SignDescriptor{
|
||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||
WitnessScript: htlcScript,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: &wire.TxOut{
|
||||
PkScript: htlcScriptHash,
|
||||
PkScript: htlcPkScript,
|
||||
Value: int64(htlc.Amt.ToSatoshis()),
|
||||
},
|
||||
HashType: txscript.SigHashAll,
|
||||
|
@ -6737,7 +6745,7 @@ func newIncomingHtlcResolution(signer input.Signer,
|
|||
successSignDesc := input.SignDescriptor{
|
||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||
WitnessScript: htlcScript,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: txOut,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: input.NewTxSigHashesV0Only(successTx),
|
||||
|
|
|
@ -190,6 +190,10 @@ type ScriptInfo struct {
|
|||
// output is being signed. For p2wkh it should be set equal to the
|
||||
// PkScript.
|
||||
WitnessScript []byte
|
||||
|
||||
// ScriptTree is the script tree that stores all the scripts that are
|
||||
// committed to by the above PkScript, if it's a P2TR script template.
|
||||
ScriptTree *txscript.IndexedTapScriptTree
|
||||
}
|
||||
|
||||
// CommitScriptToSelf constructs the public key script for the output on the
|
||||
|
@ -225,9 +229,11 @@ func CommitScriptToSelf(chanType channeldb.ChannelType, initiator bool,
|
|||
"pkscript: %w", err)
|
||||
}
|
||||
|
||||
// TODO(rosabeef): recator to be able to get script key
|
||||
return &ScriptInfo{
|
||||
WitnessScript: toLocalScriptTree.SettleLeaf.Script,
|
||||
PkScript: toLocalPkScript,
|
||||
ScriptTree: toLocalScriptTree.TapscriptTree,
|
||||
}, nil
|
||||
|
||||
// If we are the initiator of a leased channel, then we have an
|
||||
|
@ -310,20 +316,24 @@ func CommitScriptToRemote(chanType channeldb.ChannelType, initiator bool,
|
|||
// we use a NUMS key to force the remote party to take a script path,
|
||||
// with the sole tap leaf enforcing the 1 CSV delay.
|
||||
case chanType.IsTaproot():
|
||||
toRemoteKey, err := input.TaprootCommitScriptToRemote(
|
||||
toRemoteScriptTree, err := input.NewRemoteCommitScriptTree(
|
||||
remoteKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
toRemotePkScript, err := input.PayToTaprootScript(toRemoteKey)
|
||||
toRemotePkScript, err := input.PayToTaprootScript(
|
||||
toRemoteScriptTree.TaprootKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return &ScriptInfo{
|
||||
PkScript: toRemotePkScript,
|
||||
WitnessScript: toRemoteScriptTree.SettleLeaf.Script,
|
||||
PkScript: toRemotePkScript,
|
||||
ScriptTree: toRemoteScriptTree.TapscriptTree,
|
||||
}, 1, nil
|
||||
|
||||
// If this channel type has anchors, we derive the delayed to_remote
|
||||
|
@ -533,20 +543,23 @@ func CommitScriptAnchors(chanType channeldb.ChannelType,
|
|||
// since these are fully revealed once the commitment hits the chain.
|
||||
case chanType.IsTaproot():
|
||||
anchorScript = func(key *btcec.PublicKey) (*ScriptInfo, error) {
|
||||
anchorKey, err := input.TaprootOutputKeyAnchor(key)
|
||||
anchorScriptTree, err := input.NewAnchorScriptTree(
|
||||
key,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
anchorPkScript, err := input.PayToTaprootScript(
|
||||
anchorKey,
|
||||
anchorScriptTree.TaprootKey,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ScriptInfo{
|
||||
PkScript: anchorPkScript,
|
||||
PkScript: anchorPkScript,
|
||||
ScriptTree: anchorScriptTree.TapscriptTree,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -1078,6 +1091,7 @@ func genTaprootHtlcScript(isIncoming, ourCommit bool, timeout uint32,
|
|||
var (
|
||||
taprootKey *btcec.PublicKey
|
||||
secondLevelScript []byte
|
||||
tapScriptTree *txscript.IndexedTapScriptTree
|
||||
)
|
||||
|
||||
// Generate the proper redeem scripts for the HTLC output modified by
|
||||
|
@ -1096,6 +1110,7 @@ func genTaprootHtlcScript(isIncoming, ourCommit bool, timeout uint32,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
tapScriptTree = scriptTree.TapscriptTree
|
||||
taprootKey = scriptTree.TaprootKey
|
||||
|
||||
// As this is an HTLC on our commitment transaction, the second
|
||||
|
@ -1116,6 +1131,7 @@ func genTaprootHtlcScript(isIncoming, ourCommit bool, timeout uint32,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
tapScriptTree = scriptTree.TapscriptTree
|
||||
taprootKey = scriptTree.TaprootKey
|
||||
|
||||
// In this case, this is an incoming HTLC on the commitment
|
||||
|
@ -1136,6 +1152,7 @@ func genTaprootHtlcScript(isIncoming, ourCommit bool, timeout uint32,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
tapScriptTree = scriptTree.TapscriptTree
|
||||
taprootKey = scriptTree.TaprootKey
|
||||
|
||||
// This is an outgoing HTLC on our commitment transaction, so
|
||||
|
@ -1155,6 +1172,7 @@ func genTaprootHtlcScript(isIncoming, ourCommit bool, timeout uint32,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
tapScriptTree = scriptTree.TapscriptTree
|
||||
taprootKey = scriptTree.TaprootKey
|
||||
|
||||
// This is an outgoing HTLC on the remote party's commitment
|
||||
|
@ -1174,6 +1192,7 @@ func genTaprootHtlcScript(isIncoming, ourCommit bool, timeout uint32,
|
|||
return &ScriptInfo{
|
||||
PkScript: p2trOutput,
|
||||
WitnessScript: secondLevelScript,
|
||||
ScriptTree: tapScriptTree,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -1182,7 +1201,7 @@ func genTaprootHtlcScript(isIncoming, ourCommit bool, timeout uint32,
|
|||
// HTLC is being applied to their commitment transaction or ours.
|
||||
func genHtlcScript(chanType channeldb.ChannelType, isIncoming, ourCommit bool,
|
||||
timeout uint32, rHash [32]byte,
|
||||
keyRing *CommitmentKeyRing) ([]byte, []byte, error) {
|
||||
keyRing *CommitmentKeyRing) (*ScriptInfo, error) {
|
||||
|
||||
var (
|
||||
scriptInfo *ScriptInfo
|
||||
|
@ -1200,10 +1219,10 @@ func genHtlcScript(chanType channeldb.ChannelType, isIncoming, ourCommit bool,
|
|||
)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return scriptInfo.PkScript, scriptInfo.WitnessScript, nil
|
||||
return scriptInfo, nil
|
||||
}
|
||||
|
||||
// addHTLC adds a new HTLC to the passed commitment transaction. One of four
|
||||
|
@ -1220,13 +1239,16 @@ func addHTLC(commitTx *wire.MsgTx, ourCommit bool,
|
|||
timeout := paymentDesc.Timeout
|
||||
rHash := paymentDesc.RHash
|
||||
|
||||
witnessProgram, witnessScript, err := genHtlcScript(
|
||||
scriptInfo, err := genHtlcScript(
|
||||
chanType, isIncoming, ourCommit, timeout, rHash, keyRing,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
witnessProgram := scriptInfo.PkScript
|
||||
witnessScript := scriptInfo.WitnessScript
|
||||
|
||||
// Add the new HTLC outputs to the respective commitment transactions.
|
||||
amountPending := int64(paymentDesc.Amount.ToSatoshis())
|
||||
commitTx.AddTxOut(wire.NewTxOut(amountPending, witnessProgram))
|
||||
|
|
Loading…
Add table
Reference in a new issue