diff --git a/sweep/fee_bumper.go b/sweep/fee_bumper.go index 99360d6fb..d69158eab 100644 --- a/sweep/fee_bumper.go +++ b/sweep/fee_bumper.go @@ -1267,56 +1267,17 @@ func (t *TxPublisher) createUnknownSpentBumpResult( SpentInputs: r.spentInputs, } - // Get the fee function, which will be used to decided the next fee rate - // to use if the sweeper decides to retry sweeping this input. - feeFunc := r.feeFunction - - // When the record is failed before the initial broadcast is attempted, - // it will have a nil fee func. In this case, we'll create the fee func - // here. - // - // NOTE: Since the current record is failed and will be deleted, we - // don't need to update the record on this fee function. We only need - // the fee rate data so the sweeper can pick up where we left off. - if feeFunc == nil { - f, err := t.initializeFeeFunction(r.req) - // TODO(yy): The only error we would receive here is when the - // pkScript is not recognized by the weightEstimator. What we - // should do instead is to check the pkScript immediately after - // receiving a sweep request so we don't need to check it again, - // which will also save us from error checking from several - // callsites. - if err != nil { - log.Errorf("Failed to create fee func for record %v: "+ - "%v", r.requestID, err) - - // Overwrite the event and error so the sweeper will - // remove this input. - result.Event = TxFatal - result.Err = err - - return result - } - - feeFunc = f - } - - // Since the sweeping tx has been replaced by another party's tx, we - // missed this block window to increase its fee rate. To make sure the - // fee rate stays in the initial line, we now ask the fee function to - // give us the next fee rate as if the sweeping tx were RBFed. This new - // fee rate will be used as the starting fee rate if the upper system - // decides to continue sweeping the rest of the inputs. - _, err := feeFunc.Increment() + // Calculate the next fee rate for the retry. + feeRate, err := t.calculateRetryFeeRate(r) if err != nil { - // The fee function has reached its max position - nothing we - // can do here other than letting the user increase the budget. - log.Errorf("Failed to calculate the next fee rate for "+ - "Record(%v): %v", r.requestID, err) + // Overwrite the event and error so the sweeper will + // remove this input. + result.Event = TxFatal + result.Err = err } // Attach the new fee rate to be used for the next sweeping attempt. - result.FeeRate = feeFunc.FeeRate() + result.FeeRate = feeRate return result } @@ -1893,3 +1854,59 @@ func (t *TxPublisher) handleReplacementTxError(r *monitorRecord, return result } + +// calculateRetryFeeRate calculates a new fee rate to be used as the starting +// fee rate for the next sweep attempt if the inputs are to be retried. When the +// fee function is nil it will be created here, and an error is returned if the +// fee func cannot be initialized. +func (t *TxPublisher) calculateRetryFeeRate( + r *monitorRecord) (chainfee.SatPerKWeight, error) { + + // Get the fee function, which will be used to decided the next fee rate + // to use if the sweeper decides to retry sweeping this input. + feeFunc := r.feeFunction + + // When the record is failed before the initial broadcast is attempted, + // it will have a nil fee func. In this case, we'll create the fee func + // here. + // + // NOTE: Since the current record is failed and will be deleted, we + // don't need to update the record on this fee function. We only need + // the fee rate data so the sweeper can pick up where we left off. + if feeFunc == nil { + f, err := t.initializeFeeFunction(r.req) + + // TODO(yy): The only error we would receive here is when the + // pkScript is not recognized by the weightEstimator. What we + // should do instead is to check the pkScript immediately after + // receiving a sweep request so we don't need to check it again, + // which will also save us from error checking from several + // callsites. + if err != nil { + log.Errorf("Failed to create fee func for record %v: "+ + "%v", r.requestID, err) + + return 0, err + } + + feeFunc = f + } + + // Since we failed to sweep the inputs, either the sweeping tx has been + // replaced by another party's tx, or the current output values cannot + // cover the budget, we missed this block window to increase its fee + // rate. To make sure the fee rate stays in the initial line, we now ask + // the fee function to give us the next fee rate as if the sweeping tx + // were RBFed. This new fee rate will be used as the starting fee rate + // if the upper system decides to continue sweeping the rest of the + // inputs. + _, err := feeFunc.Increment() + if err != nil { + // The fee function has reached its max position - nothing we + // can do here other than letting the user increase the budget. + log.Errorf("Failed to calculate the next fee rate for "+ + "Record(%v): %v", r.requestID, err) + } + + return feeFunc.FeeRate(), nil +}