mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-01-19 05:45:21 +01:00
lnwallet: update newIncomingHtlcResolution for taproot chans
Similar to the outgoing resolutions, the main change here is ensuring the sign method and control block are properly set for the various spend types.
This commit is contained in:
parent
a0a3c7aa89
commit
ad5305b99c
@ -6786,24 +6786,38 @@ func newIncomingHtlcResolution(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,
|
||||
scriptInfo.ScriptTree,
|
||||
)
|
||||
signDesc.ControlBlock, err = ctrlBlock.ToBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &IncomingHtlcResolution{
|
||||
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
|
||||
}
|
||||
|
||||
// Otherwise, we'll need to go to the second level to sweep this HTLC.
|
||||
|
||||
//
|
||||
// First, we'll reconstruct the original HTLC success transaction,
|
||||
// taking into account the fee rate used.
|
||||
htlcFee := HtlcSuccessFee(chanType, feePerKw)
|
||||
@ -6819,17 +6833,22 @@ func newIncomingHtlcResolution(signer input.Signer,
|
||||
// Once we've created the second-level transaction, we'll generate the
|
||||
// SignDesc needed spend the HTLC output using the success transaction.
|
||||
txOut := commitTx.TxOut[htlc.OutputIndex]
|
||||
prevFetcher := txscript.NewCannedPrevOutputFetcher(
|
||||
txOut.PkScript, txOut.Value,
|
||||
)
|
||||
hashCache := txscript.NewTxSigHashes(successTx, prevFetcher)
|
||||
successSignDesc := input.SignDescriptor{
|
||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||
WitnessScript: htlcWitnessScript,
|
||||
Output: txOut,
|
||||
HashType: txscript.SigHashAll,
|
||||
SigHashes: input.NewTxSigHashesV0Only(successTx),
|
||||
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
|
||||
}
|
||||
@ -6838,12 +6857,36 @@ func newIncomingHtlcResolution(signer input.Signer,
|
||||
// the success transaction. Don't specify the preimage yet. The preimage
|
||||
// will be supplied by the contract resolver, either directly or when it
|
||||
// becomes known.
|
||||
var successWitness wire.TxWitness
|
||||
sigHashType := HtlcSigHashType(chanType)
|
||||
successWitness, err := input.ReceiverHtlcSpendRedeem(
|
||||
htlcSig, sigHashType, nil, signer, &successSignDesc, successTx,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if chanType.IsTaproot() {
|
||||
// TODO(roasbeef): make sure default elsewhere
|
||||
successSignDesc.HashType = txscript.SigHashDefault
|
||||
successSignDesc.SignMethod = input.TaprootScriptSpendSignMethod
|
||||
|
||||
successWitness, err = input.ReceiverHTLCScriptTaprootRedeem(
|
||||
htlcSig, sigHashType, nil, signer, &successSignDesc,
|
||||
successTx, keyRing.RevocationKey, scriptInfo.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(successWitness) - 1
|
||||
successSignDesc.ControlBlock = successWitness[ctlrBlkIdx]
|
||||
} else {
|
||||
successWitness, err = input.ReceiverHtlcSpendRedeem(
|
||||
htlcSig, sigHashType, nil, signer, &successSignDesc,
|
||||
successTx,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
successTx.TxIn[0].Witness = successWitness
|
||||
|
||||
@ -6856,12 +6899,44 @@ func newIncomingHtlcResolution(signer input.Signer,
|
||||
// Finally, we'll generate the script that the second-level transaction
|
||||
// creates so we can generate the proper signDesc to sweep it after the
|
||||
// CSV delay has passed.
|
||||
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
|
||||
}
|
||||
|
||||
// TODO(roasbeef): conslidate logic to reduce vertical noise
|
||||
}
|
||||
|
||||
localDelayTweak := input.SingleTweakBytes(
|
||||
@ -6883,7 +6958,9 @@ func newIncomingHtlcResolution(signer input.Signer,
|
||||
PkScript: htlcSweepScript.PkScript,
|
||||
Value: int64(secondLevelOutputAmt),
|
||||
},
|
||||
HashType: txscript.SigHashAll,
|
||||
HashType: txscript.SigHashAll,
|
||||
SignMethod: signMethod,
|
||||
ControlBlock: ctrlBlock,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@ -6956,7 +7033,8 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool,
|
||||
ourCommit, isCommitFromInitiator, chanType,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("incoming resolution "+
|
||||
"failed: %v", err)
|
||||
}
|
||||
|
||||
incomingResolutions = append(incomingResolutions, *ihr)
|
||||
@ -6969,7 +7047,8 @@ func extractHtlcResolutions(feePerKw chainfee.SatPerKWeight, ourCommit bool,
|
||||
isCommitFromInitiator, chanType,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("outgoing resolution "+
|
||||
"failed: %v", err)
|
||||
}
|
||||
|
||||
outgoingResolutions = append(outgoingResolutions, *ohr)
|
||||
|
Loading…
Reference in New Issue
Block a user