Skip to content

Commit 184c191

Browse files
committed
sweep: break initialBroadcast into two steps
With the combination of the following commit we can have a more granular control over the bump result when handling it in the sweeper.
1 parent fd9c001 commit 184c191

File tree

1 file changed

+65
-46
lines changed

1 file changed

+65
-46
lines changed

sweep/fee_bumper.go

+65-46
Original file line numberDiff line numberDiff line change
@@ -417,31 +417,23 @@ func (t *TxPublisher) storeInitialRecord(req *BumpRequest) (
417417
return requestID, record
418418
}
419419

420-
// initialBroadcast initializes a fee function, creates an RBF-compliant tx and
421-
// broadcasts it.
422-
func (t *TxPublisher) initialBroadcast(requestID uint64,
423-
req *BumpRequest) (*BumpResult, error) {
424-
420+
// initializeTx initializes a fee function and creates an RBF-compliant tx. If
421+
// succeeded, the initial tx is stored in the records map.
422+
func (t *TxPublisher) initializeTx(requestID uint64, req *BumpRequest) error {
425423
// Create a fee bumping algorithm to be used for future RBF.
426424
feeAlgo, err := t.initializeFeeFunction(req)
427425
if err != nil {
428-
return nil, fmt.Errorf("init fee function: %w", err)
426+
return fmt.Errorf("init fee function: %w", err)
429427
}
430428

431429
// Create the initial tx to be broadcasted. This tx is guaranteed to
432430
// comply with the RBF restrictions.
433431
err = t.createRBFCompliantTx(requestID, req, feeAlgo)
434432
if err != nil {
435-
return nil, fmt.Errorf("create RBF-compliant tx: %w", err)
436-
}
437-
438-
// Broadcast the tx and return the monitored record.
439-
result, err := t.broadcast(requestID)
440-
if err != nil {
441-
return nil, fmt.Errorf("broadcast sweep tx: %w", err)
433+
return fmt.Errorf("create RBF-compliant tx: %w", err)
442434
}
443435

444-
return result, nil
436+
return nil
445437
}
446438

447439
// initializeFeeFunction initializes a fee function to be used for this request
@@ -954,6 +946,50 @@ func (t *TxPublisher) handleTxConfirmed(r *monitorRecord, requestID uint64) {
954946
t.handleResult(result)
955947
}
956948

949+
// handleInitialTxError takes the error from `initializeTx` and decides the
950+
// bump event. It will construct a BumpResult and handles it.
951+
func (t *TxPublisher) handleInitialTxError(requestID uint64, err error) {
952+
// We now decide what type of event to send.
953+
var event BumpEvent
954+
955+
switch {
956+
// When the error is due to a dust output, we'll send a TxFailed so
957+
// these inputs can be retried with a different group in the next
958+
// block.
959+
case errors.Is(err, ErrTxNoOutput):
960+
event = TxFailed
961+
962+
// When the error is due to budget being used up, we'll send a TxFailed
963+
// so these inputs can be retried with a different group in the next
964+
// block.
965+
case errors.Is(err, ErrMaxPosition):
966+
event = TxFailed
967+
968+
// When the error is due to zero fee rate delta, we'll send a TxFailed
969+
// so these inputs can be retried in the next block.
970+
case errors.Is(err, ErrZeroFeeRateDelta):
971+
event = TxFailed
972+
973+
// Otherwise this is not a fee-related error and the tx cannot be
974+
// retried. In that case we will fail ALL the inputs in this tx, which
975+
// means they will be removed from the sweeper and never be tried
976+
// again.
977+
//
978+
// TODO(yy): Find out which input is causing the failure and fail that
979+
// one only.
980+
default:
981+
event = TxFatal
982+
}
983+
984+
result := &BumpResult{
985+
Event: event,
986+
Err: err,
987+
requestID: requestID,
988+
}
989+
990+
t.handleResult(result)
991+
}
992+
957993
// handleInitialBroadcast is called when a new request is received. It will
958994
// handle the initial tx creation and broadcast. In details,
959995
// 1. init a fee function based on the given strategy.
@@ -971,44 +1007,27 @@ func (t *TxPublisher) handleInitialBroadcast(r *monitorRecord,
9711007

9721008
// Attempt an initial broadcast which is guaranteed to comply with the
9731009
// RBF rules.
974-
result, err = t.initialBroadcast(requestID, r.req)
1010+
//
1011+
// Create the initial tx to be broadcasted.
1012+
err = t.initializeTx(requestID, r.req)
9751013
if err != nil {
9761014
log.Errorf("Initial broadcast failed: %v", err)
9771015

978-
// We now decide what type of event to send.
979-
var event BumpEvent
1016+
// We now handle the initialization error and exit.
1017+
t.handleInitialTxError(requestID, err)
9801018

981-
switch {
982-
// When the error is due to a dust output, we'll send a
983-
// TxFailed so these inputs can be retried with a different
984-
// group in the next block.
985-
case errors.Is(err, ErrTxNoOutput):
986-
event = TxFailed
987-
988-
// When the error is due to budget being used up, we'll send a
989-
// TxFailed so these inputs can be retried with a different
990-
// group in the next block.
991-
case errors.Is(err, ErrMaxPosition):
992-
event = TxFailed
993-
994-
// When the error is due to zero fee rate delta, we'll send a
995-
// TxFailed so these inputs can be retried in the next block.
996-
case errors.Is(err, ErrZeroFeeRateDelta):
997-
event = TxFailed
998-
999-
// Otherwise this is not a fee-related error and the tx cannot
1000-
// be retried. In that case we will fail ALL the inputs in this
1001-
// tx, which means they will be removed from the sweeper and
1002-
// never be tried again.
1003-
//
1004-
// TODO(yy): Find out which input is causing the failure and
1005-
// fail that one only.
1006-
default:
1007-
event = TxFatal
1008-
}
1019+
return
1020+
}
10091021

1022+
// Successfully created the first tx, now broadcast it.
1023+
result, err = t.broadcast(requestID)
1024+
if err != nil {
1025+
// The broadcast failed, which can only happen if the tx record
1026+
// cannot be found or the aux sweeper returns an error. In
1027+
// either case, we will send back a TxFail event so these
1028+
// inputs can be retried.
10101029
result = &BumpResult{
1011-
Event: event,
1030+
Event: TxFailed,
10121031
Err: err,
10131032
requestID: requestID,
10141033
}

0 commit comments

Comments
 (0)