mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-02-22 06:21:40 +01:00
lnwallet: update newOutgoingHtlcResolution for taproot chans
For taproot channels, we need to thread through the control block in the sign descriptor. We also ensure that the proper sign method is set. We leverage the new input.Signature generalization be able to support handling both schnorr and ECDSA signatures for the second level output.
This commit is contained in:
parent
ee59e3f181
commit
a0a3c7aa89
1 changed files with 105 additions and 28 deletions
|
@ -6563,20 +6563,34 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||
if !localCommit {
|
||||
// With the script generated, we can completely populated the
|
||||
// SignDescriptor needed to sweep the output.
|
||||
signDesc := input.SignDescriptor{
|
||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: &wire.TxOut{
|
||||
PkScript: htlcPkScript,
|
||||
Value: int64(htlc.Amt.ToSatoshis()),
|
||||
},
|
||||
HashType: txscript.SigHashAll,
|
||||
}
|
||||
|
||||
if chanType.IsTaproot() {
|
||||
signDesc.SignMethod = input.TaprootScriptSpendSignMethod
|
||||
ctrlBlock := input.MakeTaprootCtrlBlock(
|
||||
htlcWitnessScript, keyRing.RevocationKey,
|
||||
htlcScriptInfo.ScriptTree,
|
||||
)
|
||||
signDesc.ControlBlock, err = ctrlBlock.ToBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &OutgoingHtlcResolution{
|
||||
Expiry: htlc.RefundTimeout,
|
||||
ClaimOutpoint: op,
|
||||
SweepSignDesc: input.SignDescriptor{
|
||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: &wire.TxOut{
|
||||
PkScript: htlcPkScript,
|
||||
Value: int64(htlc.Amt.ToSatoshis()),
|
||||
},
|
||||
HashType: txscript.SigHashAll,
|
||||
},
|
||||
CsvDelay: HtlcSecondLevelInputSequence(chanType),
|
||||
SweepSignDesc: signDesc,
|
||||
CsvDelay: HtlcSecondLevelInputSequence(chanType),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -6604,17 +6618,22 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||
// that's capable of generating the signature required to spend the
|
||||
// HTLC output using the timeout transaction.
|
||||
txOut := commitTx.TxOut[htlc.OutputIndex]
|
||||
prevFetcher := txscript.NewCannedPrevOutputFetcher(
|
||||
txOut.PkScript, txOut.Value,
|
||||
)
|
||||
hashCache := txscript.NewTxSigHashes(timeoutTx, prevFetcher)
|
||||
timeoutSignDesc := input.SignDescriptor{
|
||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: txOut,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: input.NewTxSigHashesV0Only(timeoutTx),
|
||||
InputIndex: 0,
|
||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: txOut,
|
||||
HashType: txscript.SigHashAll,
|
||||
PrevOutputFetcher: prevFetcher,
|
||||
SigHashes: hashCache,
|
||||
InputIndex: 0,
|
||||
}
|
||||
|
||||
htlcSig, err := ecdsa.ParseDERSignature(htlc.Signature)
|
||||
htlcSig, err := input.ParseSignature(htlc.Signature)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -6622,12 +6641,38 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||
// With the sign desc created, we can now construct the full witness
|
||||
// for the timeout transaction, and populate it as well.
|
||||
sigHashType := HtlcSigHashType(chanType)
|
||||
timeoutWitness, err := input.SenderHtlcSpendTimeout(
|
||||
htlcSig, sigHashType, signer, &timeoutSignDesc, timeoutTx,
|
||||
)
|
||||
var timeoutWitness wire.TxWitness
|
||||
if chanType.IsTaproot() {
|
||||
// TODO(roasbeef): make sure default elsewhere
|
||||
timeoutSignDesc.SignMethod = input.TaprootScriptSpendSignMethod
|
||||
timeoutSignDesc.HashType = txscript.SigHashDefault
|
||||
|
||||
timeoutWitness, err = input.SenderHTLCScriptTaprootTimeout(
|
||||
htlcSig, sigHashType, signer, &timeoutSignDesc,
|
||||
timeoutTx, keyRing.RevocationKey,
|
||||
htlcScriptInfo.ScriptTree,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The control block is always the final element of the witness
|
||||
// stack. We set this here as eventually the sweeper will need
|
||||
// to re-sign, so it needs the isolated control block.
|
||||
//
|
||||
// TODO(roasbeef): move this into input.go?
|
||||
ctlrBlkIdx := len(timeoutWitness) - 1
|
||||
timeoutSignDesc.ControlBlock = timeoutWitness[ctlrBlkIdx]
|
||||
} else {
|
||||
timeoutWitness, err = input.SenderHtlcSpendTimeout(
|
||||
htlcSig, sigHashType, signer, &timeoutSignDesc,
|
||||
timeoutTx,
|
||||
)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
timeoutTx.TxIn[0].Witness = timeoutWitness
|
||||
|
||||
// If this is an anchor type channel, the sign details will let us
|
||||
|
@ -6639,12 +6684,42 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||
// Finally, we'll generate the script output that the timeout
|
||||
// transaction creates so we can generate the signDesc required to
|
||||
// complete the claim process after a delay period.
|
||||
htlcSweepScript, err := SecondLevelHtlcScript(
|
||||
chanType, isCommitFromInitiator, keyRing.RevocationKey,
|
||||
keyRing.ToLocalKey, csvDelay, leaseExpiry,
|
||||
var (
|
||||
htlcSweepScript *ScriptInfo
|
||||
signMethod input.SignMethod
|
||||
ctrlBlock []byte
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if !chanType.IsTaproot() {
|
||||
htlcSweepScript, err = SecondLevelHtlcScript(
|
||||
chanType, isCommitFromInitiator, keyRing.RevocationKey,
|
||||
keyRing.ToLocalKey, csvDelay, leaseExpiry,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
secondLevelScriptTree, err := input.TaprootSecondLevelScriptTree(
|
||||
keyRing.RevocationKey, keyRing.ToLocalKey, csvDelay,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
htlcSweepScript = &ScriptInfo{
|
||||
PkScript: secondLevelScriptTree.PkScript,
|
||||
WitnessScript: secondLevelScriptTree.SuccessTapLeaf.Script,
|
||||
}
|
||||
|
||||
signMethod = input.TaprootScriptSpendSignMethod
|
||||
|
||||
controlBlock := input.MakeTaprootCtrlBlock(
|
||||
htlcSweepScript.WitnessScript, keyRing.RevocationKey,
|
||||
secondLevelScriptTree.TapscriptTree,
|
||||
)
|
||||
ctrlBlock, err = controlBlock.ToBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
localDelayTweak := input.SingleTweakBytes(
|
||||
|
@ -6667,7 +6742,9 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||
PkScript: htlcSweepScript.PkScript,
|
||||
Value: int64(secondLevelOutputAmt),
|
||||
},
|
||||
HashType: txscript.SigHashAll,
|
||||
HashType: txscript.SigHashAll,
|
||||
SignMethod: signMethod,
|
||||
ControlBlock: ctrlBlock,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue