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:
2 files changed
+88
-24
No files matched your search
@@ -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,
|
||||||
@@ -6711,6 +6714,7 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||||||
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)
|
||||||
@@ -6893,6 +6897,10 @@ func newOutgoingHtlcResolution(signer input.Signer,
|
|||||||
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,
|
||||||
@@ -6954,6 +6965,7 @@ func newIncomingHtlcResolution(signer input.Signer,
|
|||||||
Value: int64(htlc.Amt.ToSatoshis()),
|
Value: int64(htlc.Amt.ToSatoshis()),
|
||||||
},
|
},
|
||||||
HashType: sweepSigHash(chanType),
|
HashType: sweepSigHash(chanType),
|
||||||
|
PrevOutputFetcher: prevFetcher,
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:lll
|
//nolint:lll
|
||||||
@@ -7128,6 +7140,10 @@ func newIncomingHtlcResolution(signer input.Signer,
|
|||||||
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,
|
||||||
},
|
},
|
||||||
|
|||||||
+72
-24
@@ -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
|
||||||
|
|
||||||
|
// 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[:]
|
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 {
|
||||||
|
|||||||
Reference in new issue
Block a user