mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-06-06 21:20:32 +02:00
lnwallet: add taproot case to TestForceClose
This adds some extra assertions to ensure things like the taproot commitment weight estimation is correct.
This commit is contained in:
parent
ff055ce0a4
commit
fcbf6f2483
@ -6702,6 +6702,9 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||||||
if !localCommit {
|
if !localCommit {
|
||||||
// With the script generated, we can completely populated the
|
// With the script generated, we can completely populated the
|
||||||
// SignDescriptor needed to sweep the output.
|
// SignDescriptor needed to sweep the output.
|
||||||
|
prevFetcher := txscript.NewCannedPrevOutputFetcher(
|
||||||
|
htlcPkScript, int64(htlc.Amt.ToSatoshis()),
|
||||||
|
)
|
||||||
signDesc := input.SignDescriptor{
|
signDesc := input.SignDescriptor{
|
||||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||||
@ -6710,7 +6713,8 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||||||
PkScript: htlcPkScript,
|
PkScript: htlcPkScript,
|
||||||
Value: int64(htlc.Amt.ToSatoshis()),
|
Value: int64(htlc.Amt.ToSatoshis()),
|
||||||
},
|
},
|
||||||
HashType: sweepSigHash(chanType),
|
HashType: sweepSigHash(chanType),
|
||||||
|
PrevOutputFetcher: prevFetcher,
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptTree, ok := htlcScriptInfo.(input.TapscriptDescriptor)
|
scriptTree, ok := htlcScriptInfo.(input.TapscriptDescriptor)
|
||||||
@ -6892,7 +6896,11 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||||||
PkScript: htlcSweepScript.PkScript(),
|
PkScript: htlcSweepScript.PkScript(),
|
||||||
Value: int64(secondLevelOutputAmt),
|
Value: int64(secondLevelOutputAmt),
|
||||||
},
|
},
|
||||||
HashType: sweepSigHash(chanType),
|
HashType: sweepSigHash(chanType),
|
||||||
|
PrevOutputFetcher: txscript.NewCannedPrevOutputFetcher(
|
||||||
|
htlcSweepScript.PkScript(),
|
||||||
|
int64(secondLevelOutputAmt),
|
||||||
|
),
|
||||||
SignMethod: signMethod,
|
SignMethod: signMethod,
|
||||||
ControlBlock: ctrlBlock,
|
ControlBlock: ctrlBlock,
|
||||||
},
|
},
|
||||||
@ -6945,6 +6953,9 @@ func newIncomingHtlcResolution(signer input.Signer,
|
|||||||
if !localCommit {
|
if !localCommit {
|
||||||
// With the script generated, we can completely populated the
|
// With the script generated, we can completely populated the
|
||||||
// SignDescriptor needed to sweep the output.
|
// SignDescriptor needed to sweep the output.
|
||||||
|
prevFetcher := txscript.NewCannedPrevOutputFetcher(
|
||||||
|
htlcPkScript, int64(htlc.Amt.ToSatoshis()),
|
||||||
|
)
|
||||||
signDesc := input.SignDescriptor{
|
signDesc := input.SignDescriptor{
|
||||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||||
@ -6953,7 +6964,8 @@ func newIncomingHtlcResolution(signer input.Signer,
|
|||||||
PkScript: htlcPkScript,
|
PkScript: htlcPkScript,
|
||||||
Value: int64(htlc.Amt.ToSatoshis()),
|
Value: int64(htlc.Amt.ToSatoshis()),
|
||||||
},
|
},
|
||||||
HashType: sweepSigHash(chanType),
|
HashType: sweepSigHash(chanType),
|
||||||
|
PrevOutputFetcher: prevFetcher,
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:lll
|
//nolint:lll
|
||||||
@ -7127,7 +7139,11 @@ func newIncomingHtlcResolution(signer input.Signer,
|
|||||||
PkScript: htlcSweepScript.PkScript(),
|
PkScript: htlcSweepScript.PkScript(),
|
||||||
Value: int64(secondLevelOutputAmt),
|
Value: int64(secondLevelOutputAmt),
|
||||||
},
|
},
|
||||||
HashType: sweepSigHash(chanType),
|
HashType: sweepSigHash(chanType),
|
||||||
|
PrevOutputFetcher: txscript.NewCannedPrevOutputFetcher(
|
||||||
|
htlcSweepScript.PkScript(),
|
||||||
|
int64(secondLevelOutputAmt),
|
||||||
|
),
|
||||||
SignMethod: signMethod,
|
SignMethod: signMethod,
|
||||||
ControlBlock: ctrlBlock,
|
ControlBlock: ctrlBlock,
|
||||||
},
|
},
|
||||||
|
@ -819,6 +819,15 @@ func TestForceClose(t *testing.T) {
|
|||||||
anchorAmt: anchorSize * 2,
|
anchorAmt: anchorSize * 2,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
t.Run("taproot", func(t *testing.T) { //nolint:paralleltest
|
||||||
|
testForceClose(t, &forceCloseTestCase{
|
||||||
|
chanType: channeldb.SingleFunderTweaklessBit |
|
||||||
|
channeldb.AnchorOutputsBit |
|
||||||
|
channeldb.SimpleTaprootFeatureBit,
|
||||||
|
expectedCommitWeight: input.TaprootCommitWeight,
|
||||||
|
anchorAmt: anchorSize * 2,
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type forceCloseTestCase struct {
|
type forceCloseTestCase struct {
|
||||||
@ -982,13 +991,14 @@ func testForceClose(t *testing.T, testCase *forceCloseTestCase) {
|
|||||||
// the multi-sig clause within the output on the commitment transaction
|
// the multi-sig clause within the output on the commitment transaction
|
||||||
// that produces this HTLC.
|
// that produces this HTLC.
|
||||||
timeoutTx := htlcResolution.SignedTimeoutTx
|
timeoutTx := htlcResolution.SignedTimeoutTx
|
||||||
|
prevOutputFetcher := txscript.NewCannedPrevOutputFetcher(
|
||||||
|
senderHtlcPkScript, int64(htlcAmount.ToSatoshis()),
|
||||||
|
)
|
||||||
|
hashCache := txscript.NewTxSigHashes(timeoutTx, prevOutputFetcher)
|
||||||
vm, err := txscript.NewEngine(
|
vm, err := txscript.NewEngine(
|
||||||
senderHtlcPkScript,
|
senderHtlcPkScript,
|
||||||
timeoutTx, 0, txscript.StandardVerifyFlags, nil,
|
timeoutTx, 0, txscript.StandardVerifyFlags, nil,
|
||||||
nil, int64(htlcAmount.ToSatoshis()),
|
hashCache, int64(htlcAmount.ToSatoshis()), prevOutputFetcher,
|
||||||
txscript.NewCannedPrevOutputFetcher(
|
|
||||||
senderHtlcPkScript, int64(htlcAmount.ToSatoshis()),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to create engine")
|
require.NoError(t, err, "unable to create engine")
|
||||||
if err := vm.Execute(); err != nil {
|
if err := vm.Execute(); err != nil {
|
||||||
@ -1009,22 +1019,37 @@ func testForceClose(t *testing.T, testCase *forceCloseTestCase) {
|
|||||||
Value: htlcResolution.SweepSignDesc.Output.Value,
|
Value: htlcResolution.SweepSignDesc.Output.Value,
|
||||||
})
|
})
|
||||||
htlcResolution.SweepSignDesc.InputIndex = 0
|
htlcResolution.SweepSignDesc.InputIndex = 0
|
||||||
sweepTx.TxIn[0].Witness, err = input.HtlcSpendSuccess(aliceChannel.Signer,
|
|
||||||
&htlcResolution.SweepSignDesc, sweepTx,
|
csvDelay := uint32(aliceChannel.channelState.LocalChanCfg.CsvDelay)
|
||||||
uint32(aliceChannel.channelState.LocalChanCfg.CsvDelay))
|
if testCase.chanType.IsTaproot() {
|
||||||
|
sweepTx.TxIn[0].Sequence = input.LockTimeToSequence(
|
||||||
|
false, csvDelay,
|
||||||
|
)
|
||||||
|
sweepTx.TxIn[0].Witness, err = input.TaprootHtlcSpendSuccess(
|
||||||
|
aliceChannel.Signer, &htlcResolution.SweepSignDesc,
|
||||||
|
sweepTx, nil, nil,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
sweepTx.TxIn[0].Witness, err = input.HtlcSpendSuccess(
|
||||||
|
aliceChannel.Signer, &htlcResolution.SweepSignDesc,
|
||||||
|
sweepTx, csvDelay,
|
||||||
|
)
|
||||||
|
}
|
||||||
require.NoError(t, err, "unable to gen witness for timeout output")
|
require.NoError(t, err, "unable to gen witness for timeout output")
|
||||||
|
|
||||||
// With the witness fully populated for the success spend from the
|
// With the witness fully populated for the success spend from the
|
||||||
// second-level transaction, we ensure that the scripts properly
|
// second-level transaction, we ensure that the scripts properly
|
||||||
// validate given the information within the htlc resolution struct.
|
// validate given the information within the htlc resolution struct.
|
||||||
|
prevOutFetcher := txscript.NewCannedPrevOutputFetcher(
|
||||||
|
htlcResolution.SweepSignDesc.Output.PkScript,
|
||||||
|
htlcResolution.SweepSignDesc.Output.Value,
|
||||||
|
)
|
||||||
|
hashCache = txscript.NewTxSigHashes(sweepTx, prevOutFetcher)
|
||||||
vm, err = txscript.NewEngine(
|
vm, err = txscript.NewEngine(
|
||||||
htlcResolution.SweepSignDesc.Output.PkScript,
|
htlcResolution.SweepSignDesc.Output.PkScript,
|
||||||
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
||||||
nil, htlcResolution.SweepSignDesc.Output.Value,
|
hashCache, htlcResolution.SweepSignDesc.Output.Value,
|
||||||
txscript.NewCannedPrevOutputFetcher(
|
prevOutFetcher,
|
||||||
htlcResolution.SweepSignDesc.Output.PkScript,
|
|
||||||
htlcResolution.SweepSignDesc.Output.Value,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to create engine")
|
require.NoError(t, err, "unable to create engine")
|
||||||
if err := vm.Execute(); err != nil {
|
if err := vm.Execute(); err != nil {
|
||||||
@ -1051,14 +1076,23 @@ func testForceClose(t *testing.T, testCase *forceCloseTestCase) {
|
|||||||
// preimage manually. This is usually done by the contract resolver
|
// preimage manually. This is usually done by the contract resolver
|
||||||
// before publication.
|
// before publication.
|
||||||
successTx := inHtlcResolution.SignedSuccessTx
|
successTx := inHtlcResolution.SignedSuccessTx
|
||||||
successTx.TxIn[0].Witness[3] = preimageBob[:]
|
|
||||||
|
// For taproot channels, the preimage goes into a slightly different
|
||||||
|
// location.
|
||||||
|
if testCase.chanType.IsTaproot() {
|
||||||
|
successTx.TxIn[0].Witness[2] = preimageBob[:]
|
||||||
|
} else {
|
||||||
|
successTx.TxIn[0].Witness[3] = preimageBob[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
prevOuts := txscript.NewCannedPrevOutputFetcher(
|
||||||
|
receiverHtlcScript, int64(htlcAmount.ToSatoshis()),
|
||||||
|
)
|
||||||
|
hashCache = txscript.NewTxSigHashes(successTx, prevOuts)
|
||||||
vm, err = txscript.NewEngine(
|
vm, err = txscript.NewEngine(
|
||||||
receiverHtlcScript,
|
receiverHtlcScript,
|
||||||
successTx, 0, txscript.StandardVerifyFlags, nil,
|
successTx, 0, txscript.StandardVerifyFlags, nil,
|
||||||
nil, int64(htlcAmount.ToSatoshis()),
|
hashCache, int64(htlcAmount.ToSatoshis()), prevOuts,
|
||||||
txscript.NewCannedPrevOutputFetcher(
|
|
||||||
receiverHtlcScript, int64(htlcAmount.ToSatoshis()),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to create engine")
|
require.NoError(t, err, "unable to create engine")
|
||||||
if err := vm.Execute(); err != nil {
|
if err := vm.Execute(); err != nil {
|
||||||
@ -1076,21 +1110,35 @@ func testForceClose(t *testing.T, testCase *forceCloseTestCase) {
|
|||||||
Value: inHtlcResolution.SweepSignDesc.Output.Value,
|
Value: inHtlcResolution.SweepSignDesc.Output.Value,
|
||||||
})
|
})
|
||||||
inHtlcResolution.SweepSignDesc.InputIndex = 0
|
inHtlcResolution.SweepSignDesc.InputIndex = 0
|
||||||
sweepTx.TxIn[0].Witness, err = input.HtlcSpendSuccess(aliceChannel.Signer,
|
if testCase.chanType.IsTaproot() {
|
||||||
&inHtlcResolution.SweepSignDesc, sweepTx,
|
sweepTx.TxIn[0].Sequence = input.LockTimeToSequence(
|
||||||
uint32(aliceChannel.channelState.LocalChanCfg.CsvDelay))
|
false, csvDelay,
|
||||||
|
)
|
||||||
|
sweepTx.TxIn[0].Witness, err = input.TaprootHtlcSpendSuccess(
|
||||||
|
aliceChannel.Signer, &inHtlcResolution.SweepSignDesc,
|
||||||
|
sweepTx, nil, nil,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
sweepTx.TxIn[0].Witness, err = input.HtlcSpendSuccess(
|
||||||
|
aliceChannel.Signer, &inHtlcResolution.SweepSignDesc,
|
||||||
|
sweepTx,
|
||||||
|
uint32(aliceChannel.channelState.LocalChanCfg.CsvDelay),
|
||||||
|
)
|
||||||
|
}
|
||||||
require.NoError(t, err, "unable to gen witness for timeout output")
|
require.NoError(t, err, "unable to gen witness for timeout output")
|
||||||
|
|
||||||
// The spend we create above spending the second level HTLC output
|
// The spend we create above spending the second level HTLC output
|
||||||
// should validate without any issues.
|
// should validate without any issues.
|
||||||
|
prevOuts = txscript.NewCannedPrevOutputFetcher(
|
||||||
|
inHtlcResolution.SweepSignDesc.Output.PkScript,
|
||||||
|
inHtlcResolution.SweepSignDesc.Output.Value,
|
||||||
|
)
|
||||||
|
hashCache = txscript.NewTxSigHashes(sweepTx, prevOuts)
|
||||||
vm, err = txscript.NewEngine(
|
vm, err = txscript.NewEngine(
|
||||||
inHtlcResolution.SweepSignDesc.Output.PkScript,
|
inHtlcResolution.SweepSignDesc.Output.PkScript,
|
||||||
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
||||||
nil, inHtlcResolution.SweepSignDesc.Output.Value,
|
hashCache, inHtlcResolution.SweepSignDesc.Output.Value,
|
||||||
txscript.NewCannedPrevOutputFetcher(
|
prevOuts,
|
||||||
inHtlcResolution.SweepSignDesc.Output.PkScript,
|
|
||||||
inHtlcResolution.SweepSignDesc.Output.Value,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "unable to create engine")
|
require.NoError(t, err, "unable to create engine")
|
||||||
if err := vm.Execute(); err != nil {
|
if err := vm.Execute(); err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user