sweep: make sure recovered inputs are retried
Previously, when a given input is found spent in the mempool, we'd mark it as Published and never offer it to the fee bumper. This is dangerous as the input will never be fee bumped. We now fix it by always initializing the input with state Init, and only use mempool to check for fee and fee rate. This changes the current restart behavior - as previously when a sweeping tx is broadcast, the node shuts down, when it starts again, the input will be offered to the sweeper again, but not to the fee bumper, which means the sweeping tx will stay in the mempool with the last-tried fee rate. After this change, after a restart, the input will be swept again, and the fee bumper will monitor its status. The restart will also behave like a fee bump if there's already an existing sweeping tx in the mempool.
This commit is contained in:
2 files changed
+32
-33
No files matched your search
+10
-18
@@ -497,10 +497,9 @@ func TestUpdateSweeperInputs(t *testing.T) {
|
||||
require.Equal(expectedInputs, s.inputs)
|
||||
}
|
||||
|
||||
// TestDecideStateAndRBFInfo checks that the expected state and RBFInfo are
|
||||
// returned based on whether this input can be found both in mempool and the
|
||||
// sweeper store.
|
||||
func TestDecideStateAndRBFInfo(t *testing.T) {
|
||||
// TestDecideRBFInfo checks that the expected RBFInfo is returned based on
|
||||
// whether this input can be found both in mempool and the sweeper store.
|
||||
func TestDecideRBFInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require := require.New(t)
|
||||
@@ -524,11 +523,9 @@ func TestDecideStateAndRBFInfo(t *testing.T) {
|
||||
mockMempool.On("LookupInputMempoolSpend", op).Return(
|
||||
fn.None[wire.MsgTx]()).Once()
|
||||
|
||||
// Since the mempool lookup failed, we exepect state Init and no
|
||||
// RBFInfo.
|
||||
state, rbf := s.decideStateAndRBFInfo(op)
|
||||
// Since the mempool lookup failed, we expect no RBFInfo.
|
||||
rbf := s.decideRBFInfo(op)
|
||||
require.True(rbf.IsNone())
|
||||
require.Equal(Init, state)
|
||||
|
||||
// Mock the mempool lookup to return a tx three times as we are calling
|
||||
// attachAvailableRBFInfo three times.
|
||||
@@ -539,19 +536,17 @@ func TestDecideStateAndRBFInfo(t *testing.T) {
|
||||
// Mock the store to return an error saying the tx cannot be found.
|
||||
mockStore.On("GetTx", tx.TxHash()).Return(nil, ErrTxNotFound).Once()
|
||||
|
||||
// Although the db lookup failed, we expect the state to be Published.
|
||||
state, rbf = s.decideStateAndRBFInfo(op)
|
||||
// The db lookup failed, we expect no RBFInfo.
|
||||
rbf = s.decideRBFInfo(op)
|
||||
require.True(rbf.IsNone())
|
||||
require.Equal(Published, state)
|
||||
|
||||
// Mock the store to return a db error.
|
||||
dummyErr := errors.New("dummy error")
|
||||
mockStore.On("GetTx", tx.TxHash()).Return(nil, dummyErr).Once()
|
||||
|
||||
// Although the db lookup failed, we expect the state to be Published.
|
||||
state, rbf = s.decideStateAndRBFInfo(op)
|
||||
// The db lookup failed, we expect no RBFInfo.
|
||||
rbf = s.decideRBFInfo(op)
|
||||
require.True(rbf.IsNone())
|
||||
require.Equal(Published, state)
|
||||
|
||||
// Mock the store to return a record.
|
||||
tr := &TxRecord{
|
||||
@@ -561,7 +556,7 @@ func TestDecideStateAndRBFInfo(t *testing.T) {
|
||||
mockStore.On("GetTx", tx.TxHash()).Return(tr, nil).Once()
|
||||
|
||||
// Call the method again.
|
||||
state, rbf = s.decideStateAndRBFInfo(op)
|
||||
rbf = s.decideRBFInfo(op)
|
||||
|
||||
// Assert that the RBF info is returned.
|
||||
rbfInfo := fn.Some(RBFInfo{
|
||||
@@ -570,9 +565,6 @@ func TestDecideStateAndRBFInfo(t *testing.T) {
|
||||
FeeRate: chainfee.SatPerKWeight(tr.FeeRate),
|
||||
})
|
||||
require.Equal(rbfInfo, rbf)
|
||||
|
||||
// Assert the state is updated.
|
||||
require.Equal(Published, state)
|
||||
}
|
||||
|
||||
// TestMarkInputFatal checks that the input is marked as expected.
|
||||
|
||||
Reference in new issue
Block a user