mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-29 15:11:09 +02:00
itest: add new RBF coop close itest
The itest has both sides try to close multiple times, each time with increasing fee rates. We also test the reconnection case, bad RBF updates, and instances where the local party can't actually pay for fees.
This commit is contained in:
@@ -1211,6 +1211,19 @@ func (h *HarnessTest) OpenChannelAssertErr(srcNode, destNode *node.HarnessNode,
|
||||
// closeChannelOpts holds the options for closing a channel.
|
||||
type closeChannelOpts struct {
|
||||
feeRate fn.Option[chainfee.SatPerVByte]
|
||||
|
||||
// localTxOnly is a boolean indicating if we should only attempt to
|
||||
// consume close pending notifications for the local transaction.
|
||||
localTxOnly bool
|
||||
|
||||
// skipMempoolCheck is a boolean indicating if we should skip the normal
|
||||
// mempool check after a coop close.
|
||||
skipMempoolCheck bool
|
||||
|
||||
// errString is an expected error. If this is non-blank, then we'll
|
||||
// assert that the coop close wasn't possible, and returns an error that
|
||||
// contains this err string.
|
||||
errString string
|
||||
}
|
||||
|
||||
// CloseChanOpt is a functional option to modify the way we close a channel.
|
||||
@@ -1224,6 +1237,32 @@ func WithCoopCloseFeeRate(rate chainfee.SatPerVByte) CloseChanOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// WithLocalTxNotify is a functional option to indicate that we should only
|
||||
// notify for the local txn. This is useful for the RBF coop close type, as
|
||||
// it'll notify for both local and remote txns.
|
||||
func WithLocalTxNotify() CloseChanOpt {
|
||||
return func(o *closeChannelOpts) {
|
||||
o.localTxOnly = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithSkipMempoolCheck is a functional option to indicate that we should skip
|
||||
// the mempool check. This can be used when a coop close iteration may not
|
||||
// result in a newly broadcast transaction.
|
||||
func WithSkipMempoolCheck() CloseChanOpt {
|
||||
return func(o *closeChannelOpts) {
|
||||
o.skipMempoolCheck = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithExpectedErrString is a functional option that can be used to assert that
|
||||
// an error occurs during the coop close process.
|
||||
func WithExpectedErrString(errString string) CloseChanOpt {
|
||||
return func(o *closeChannelOpts) {
|
||||
o.errString = errString
|
||||
}
|
||||
}
|
||||
|
||||
// defaultCloseOpts returns the set of default close options.
|
||||
func defaultCloseOpts() *closeChannelOpts {
|
||||
return &closeChannelOpts{}
|
||||
@@ -1267,23 +1306,49 @@ func (h *HarnessTest) CloseChannelAssertPending(hn *node.HarnessNode,
|
||||
_, err = h.ReceiveCloseChannelUpdate(stream)
|
||||
require.NoError(h, err, "close channel update got error: %v", err)
|
||||
|
||||
event, err = h.ReceiveCloseChannelUpdate(stream)
|
||||
if err != nil {
|
||||
h.Logf("Test: %s, close channel got error: %v",
|
||||
h.manager.currentTestCase, err)
|
||||
var closeTxid *chainhash.Hash
|
||||
for {
|
||||
event, err = h.ReceiveCloseChannelUpdate(stream)
|
||||
if err != nil {
|
||||
h.Logf("Test: %s, close channel got error: %v",
|
||||
h.manager.currentTestCase, err)
|
||||
}
|
||||
if err != nil && closeOpts.errString == "" {
|
||||
require.NoError(h, err, "retry closing channel failed")
|
||||
} else if err != nil && closeOpts.errString != "" {
|
||||
require.ErrorContains(h, err, closeOpts.errString)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
pendingClose, ok := event.Update.(*lnrpc.CloseStatusUpdate_ClosePending) //nolint:ll
|
||||
require.Truef(h, ok, "expected channel close "+
|
||||
"update, instead got %v", pendingClose)
|
||||
|
||||
if !pendingClose.ClosePending.LocalCloseTx &&
|
||||
closeOpts.localTxOnly {
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
notifyRate := pendingClose.ClosePending.FeePerVbyte
|
||||
if closeOpts.localTxOnly &&
|
||||
notifyRate != int64(closeReq.SatPerVbyte) {
|
||||
continue
|
||||
}
|
||||
|
||||
closeTxid, err = chainhash.NewHash(
|
||||
pendingClose.ClosePending.Txid,
|
||||
)
|
||||
require.NoErrorf(h, err, "unable to decode closeTxid: %v",
|
||||
pendingClose.ClosePending.Txid)
|
||||
|
||||
break
|
||||
}
|
||||
require.NoError(h, err, "retry closing channel failed")
|
||||
|
||||
pendingClose, ok := event.Update.(*lnrpc.CloseStatusUpdate_ClosePending)
|
||||
require.Truef(h, ok, "expected channel close update, instead got %v",
|
||||
pendingClose)
|
||||
|
||||
closeTxid, err := chainhash.NewHash(pendingClose.ClosePending.Txid)
|
||||
require.NoErrorf(h, err, "unable to decode closeTxid: %v",
|
||||
pendingClose.ClosePending.Txid)
|
||||
|
||||
// Assert the closing tx is in the mempool.
|
||||
h.miner.AssertTxInMempool(*closeTxid)
|
||||
if !closeOpts.skipMempoolCheck {
|
||||
// Assert the closing tx is in the mempool.
|
||||
h.miner.AssertTxInMempool(*closeTxid)
|
||||
}
|
||||
|
||||
return stream, event
|
||||
}
|
||||
|
Reference in New Issue
Block a user