Skip to content

Commit 29c3f66

Browse files
committedNov 11, 2024
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 fb91290 commit 29c3f66

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
@@ -421,31 +421,23 @@ func (t *TxPublisher) storeInitialRecord(req *BumpRequest) (
421421
return requestID, record
422422
}
423423

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

435433
// Create the initial tx to be broadcasted. This tx is guaranteed to
436434
// comply with the RBF restrictions.
437435
err = t.createRBFCompliantTx(requestID, req, feeAlgo)
438436
if err != nil {
439-
return nil, fmt.Errorf("create RBF-compliant tx: %w", err)
440-
}
441-
442-
// Broadcast the tx and return the monitored record.
443-
result, err := t.broadcast(requestID)
444-
if err != nil {
445-
return nil, fmt.Errorf("broadcast sweep tx: %w", err)
437+
return fmt.Errorf("create RBF-compliant tx: %w", err)
446438
}
447439

448-
return result, nil
440+
return nil
449441
}
450442

451443
// initializeFeeFunction initializes a fee function to be used for this request
@@ -957,6 +949,50 @@ func (t *TxPublisher) handleTxConfirmed(r *monitorRecord, requestID uint64) {
957949
t.handleResult(result)
958950
}
959951

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

9751011
// Attempt an initial broadcast which is guaranteed to comply with the
9761012
// RBF rules.
977-
result, err = t.initialBroadcast(requestID, r.req)
1013+
//
1014+
// Create the initial tx to be broadcasted.
1015+
err = t.initializeTx(requestID, r.req)
9781016
if err != nil {
9791017
log.Errorf("Initial broadcast failed: %v", err)
9801018

981-
// We now decide what type of event to send.
982-
var event BumpEvent
1019+
// We now handle the initialization error and exit.
1020+
t.handleInitialTxError(requestID, err)
9831021

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

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

0 commit comments

Comments
 (0)
Please sign in to comment.