@@ -410,34 +410,35 @@ func (t *TxPublisher) Broadcast(req *BumpRequest) <-chan *BumpResult {
410
410
lnutils .SpewLogClosure (req ))
411
411
412
412
// Store the request.
413
- requestID , record := t .storeInitialRecord (req )
413
+ record := t .storeInitialRecord (req )
414
414
415
415
// Create a chan to send the result to the caller.
416
416
subscriber := make (chan * BumpResult , 1 )
417
- t .subscriberChans .Store (requestID , subscriber )
417
+ t .subscriberChans .Store (record . requestID , subscriber )
418
418
419
419
// Publish the tx immediately if specified.
420
420
if req .Immediate {
421
- t .handleInitialBroadcast (record , requestID )
421
+ t .handleInitialBroadcast (record )
422
422
}
423
423
424
424
return subscriber
425
425
}
426
426
427
427
// storeInitialRecord initializes a monitor record and saves it in the map.
428
- func (t * TxPublisher ) storeInitialRecord (req * BumpRequest ) (
429
- uint64 , * monitorRecord ) {
430
-
428
+ func (t * TxPublisher ) storeInitialRecord (req * BumpRequest ) * monitorRecord {
431
429
// Increase the request counter.
432
430
//
433
431
// NOTE: this is the only place where we increase the counter.
434
432
requestID := t .requestCounter .Add (1 )
435
433
436
434
// Register the record.
437
- record := & monitorRecord {req : req }
435
+ record := & monitorRecord {
436
+ requestID : requestID ,
437
+ req : req ,
438
+ }
438
439
t .records .Store (requestID , record )
439
440
440
- return requestID , record
441
+ return record
441
442
}
442
443
443
444
// storeRecord stores the given record in the records map.
@@ -446,6 +447,7 @@ func (t *TxPublisher) storeRecord(requestID uint64, sweepCtx *sweepTxCtx,
446
447
447
448
// Register the record.
448
449
t .records .Store (requestID , & monitorRecord {
450
+ requestID : requestID ,
449
451
tx : sweepCtx .tx ,
450
452
req : req ,
451
453
feeFunction : f ,
@@ -461,16 +463,25 @@ func (t *TxPublisher) Name() string {
461
463
462
464
// initializeTx initializes a fee function and creates an RBF-compliant tx. If
463
465
// succeeded, the initial tx is stored in the records map.
464
- func (t * TxPublisher ) initializeTx (requestID uint64 , req * BumpRequest ) error {
466
+ func (t * TxPublisher ) initializeTx (r * monitorRecord ) error {
465
467
// Create a fee bumping algorithm to be used for future RBF.
466
- feeAlgo , err := t .initializeFeeFunction (req )
468
+ feeAlgo , err := t .initializeFeeFunction (r . req )
467
469
if err != nil {
468
470
return fmt .Errorf ("init fee function: %w" , err )
469
471
}
470
472
473
+ // Attach the newly created fee function.
474
+ //
475
+ // TODO(yy): current we'd initialize a monitorRecord before creating the
476
+ // fee function, while we could instead create the fee function first
477
+ // then save it to the record. To make this happen we need to change the
478
+ // conf target calculation below since we would be initializing the fee
479
+ // function one block before.
480
+ r .feeFunction = feeAlgo
481
+
471
482
// Create the initial tx to be broadcasted. This tx is guaranteed to
472
483
// comply with the RBF restrictions.
473
- err = t .createRBFCompliantTx (requestID , req , feeAlgo )
484
+ err = t .createRBFCompliantTx (r )
474
485
if err != nil {
475
486
return fmt .Errorf ("create RBF-compliant tx: %w" , err )
476
487
}
@@ -511,24 +522,24 @@ func (t *TxPublisher) initializeFeeFunction(
511
522
// so by creating a tx, validate it using `TestMempoolAccept`, and bump its fee
512
523
// and redo the process until the tx is valid, or return an error when non-RBF
513
524
// related errors occur or the budget has been used up.
514
- func (t * TxPublisher ) createRBFCompliantTx (requestID uint64 , req * BumpRequest ,
515
- f FeeFunction ) error {
525
+ func (t * TxPublisher ) createRBFCompliantTx (r * monitorRecord ) error {
526
+ f := r . feeFunction
516
527
517
528
for {
518
529
// Create a new tx with the given fee rate and check its
519
530
// mempool acceptance.
520
- sweepCtx , err := t .createAndCheckTx (req , f )
531
+ sweepCtx , err := t .createAndCheckTx (r . req , f )
521
532
522
533
switch {
523
534
case err == nil :
524
535
// The tx is valid, store it.
525
- t .storeRecord (requestID , sweepCtx , req , f )
536
+ t .storeRecord (r . requestID , sweepCtx , r . req , f )
526
537
527
538
log .Infof ("Created initial sweep tx=%v for %v inputs: " +
528
539
"feerate=%v, fee=%v, inputs:\n %v" ,
529
- sweepCtx .tx .TxHash (), len (req .Inputs ),
540
+ sweepCtx .tx .TxHash (), len (r . req .Inputs ),
530
541
f .FeeRate (), sweepCtx .fee ,
531
- inputTypeSummary (req .Inputs ))
542
+ inputTypeSummary (r . req .Inputs ))
532
543
533
544
return nil
534
545
@@ -773,6 +784,9 @@ func (t *TxPublisher) handleResult(result *BumpResult) {
773
784
// monitorRecord is used to keep track of the tx being monitored by the
774
785
// publisher internally.
775
786
type monitorRecord struct {
787
+ // requestID is the ID of the request that created this record.
788
+ requestID uint64
789
+
776
790
// tx is the tx being monitored.
777
791
tx * wire.MsgTx
778
792
@@ -915,51 +929,51 @@ func (t *TxPublisher) processRecords() {
915
929
t .records .ForEach (visitor )
916
930
917
931
// Handle the initial broadcast.
918
- for requestID , r := range initialRecords {
919
- t .handleInitialBroadcast (r , requestID )
932
+ for _ , r := range initialRecords {
933
+ t .handleInitialBroadcast (r )
920
934
}
921
935
922
936
// For records that are confirmed, we'll notify the caller about this
923
937
// result.
924
- for requestID , r := range confirmedRecords {
938
+ for _ , r := range confirmedRecords {
925
939
log .Debugf ("Tx=%v is confirmed" , r .tx .TxHash ())
926
940
t .wg .Add (1 )
927
- go t .handleTxConfirmed (r , requestID )
941
+ go t .handleTxConfirmed (r )
928
942
}
929
943
930
944
// Get the current height to be used in the following goroutines.
931
945
currentHeight := t .currentHeight .Load ()
932
946
933
947
// For records that are not confirmed, we perform a fee bump if needed.
934
- for requestID , r := range feeBumpRecords {
948
+ for _ , r := range feeBumpRecords {
935
949
log .Debugf ("Attempting to fee bump Tx=%v" , r .tx .TxHash ())
936
950
t .wg .Add (1 )
937
- go t .handleFeeBumpTx (requestID , r , currentHeight )
951
+ go t .handleFeeBumpTx (r , currentHeight )
938
952
}
939
953
940
954
// For records that are failed, we'll notify the caller about this
941
955
// result.
942
- for requestID , r := range failedRecords {
956
+ for _ , r := range failedRecords {
943
957
log .Debugf ("Tx=%v has inputs been spent by a third party, " +
944
958
"failing it now" , r .tx .TxHash ())
945
959
t .wg .Add (1 )
946
- go t .handleThirdPartySpent (r , requestID )
960
+ go t .handleThirdPartySpent (r )
947
961
}
948
962
}
949
963
950
964
// handleTxConfirmed is called when a monitored tx is confirmed. It will
951
965
// notify the subscriber then remove the record from the maps .
952
966
//
953
967
// NOTE: Must be run as a goroutine to avoid blocking on sending the result.
954
- func (t * TxPublisher ) handleTxConfirmed (r * monitorRecord , requestID uint64 ) {
968
+ func (t * TxPublisher ) handleTxConfirmed (r * monitorRecord ) {
955
969
defer t .wg .Done ()
956
970
957
971
// Create a result that will be sent to the resultChan which is
958
972
// listened by the caller.
959
973
result := & BumpResult {
960
974
Event : TxConfirmed ,
961
975
Tx : r .tx ,
962
- requestID : requestID ,
976
+ requestID : r . requestID ,
963
977
Fee : r .fee ,
964
978
FeeRate : r .feeFunction .FeeRate (),
965
979
}
@@ -1017,10 +1031,8 @@ func (t *TxPublisher) handleInitialTxError(requestID uint64, err error) {
1017
1031
// 1. init a fee function based on the given strategy.
1018
1032
// 2. create an RBF-compliant tx and monitor it for confirmation.
1019
1033
// 3. notify the initial broadcast result back to the caller.
1020
- func (t * TxPublisher ) handleInitialBroadcast (r * monitorRecord ,
1021
- requestID uint64 ) {
1022
-
1023
- log .Debugf ("Initial broadcast for requestID=%v" , requestID )
1034
+ func (t * TxPublisher ) handleInitialBroadcast (r * monitorRecord ) {
1035
+ log .Debugf ("Initial broadcast for requestID=%v" , r .requestID )
1024
1036
1025
1037
var (
1026
1038
result * BumpResult
@@ -1031,18 +1043,18 @@ func (t *TxPublisher) handleInitialBroadcast(r *monitorRecord,
1031
1043
// RBF rules.
1032
1044
//
1033
1045
// Create the initial tx to be broadcasted.
1034
- err = t .initializeTx (requestID , r . req )
1046
+ err = t .initializeTx (r )
1035
1047
if err != nil {
1036
1048
log .Errorf ("Initial broadcast failed: %v" , err )
1037
1049
1038
1050
// We now handle the initialization error and exit.
1039
- t .handleInitialTxError (requestID , err )
1051
+ t .handleInitialTxError (r . requestID , err )
1040
1052
1041
1053
return
1042
1054
}
1043
1055
1044
1056
// Successfully created the first tx, now broadcast it.
1045
- result , err = t .broadcast (requestID )
1057
+ result , err = t .broadcast (r . requestID )
1046
1058
if err != nil {
1047
1059
// The broadcast failed, which can only happen if the tx record
1048
1060
// cannot be found or the aux sweeper returns an error. In
@@ -1051,7 +1063,7 @@ func (t *TxPublisher) handleInitialBroadcast(r *monitorRecord,
1051
1063
result = & BumpResult {
1052
1064
Event : TxFailed ,
1053
1065
Err : err ,
1054
- requestID : requestID ,
1066
+ requestID : r . requestID ,
1055
1067
}
1056
1068
}
1057
1069
@@ -1062,9 +1074,7 @@ func (t *TxPublisher) handleInitialBroadcast(r *monitorRecord,
1062
1074
// attempt to bump the fee of the tx.
1063
1075
//
1064
1076
// NOTE: Must be run as a goroutine to avoid blocking on sending the result.
1065
- func (t * TxPublisher ) handleFeeBumpTx (requestID uint64 , r * monitorRecord ,
1066
- currentHeight int32 ) {
1067
-
1077
+ func (t * TxPublisher ) handleFeeBumpTx (r * monitorRecord , currentHeight int32 ) {
1068
1078
defer t .wg .Done ()
1069
1079
1070
1080
oldTxid := r .tx .TxHash ()
@@ -1095,7 +1105,7 @@ func (t *TxPublisher) handleFeeBumpTx(requestID uint64, r *monitorRecord,
1095
1105
1096
1106
// The fee function now has a new fee rate, we will use it to bump the
1097
1107
// fee of the tx.
1098
- resultOpt := t .createAndPublishTx (requestID , r )
1108
+ resultOpt := t .createAndPublishTx (r )
1099
1109
1100
1110
// If there's a result, we will notify the caller about the result.
1101
1111
resultOpt .WhenSome (func (result BumpResult ) {
@@ -1109,9 +1119,7 @@ func (t *TxPublisher) handleFeeBumpTx(requestID uint64, r *monitorRecord,
1109
1119
// and send a TxFailed event to the subscriber.
1110
1120
//
1111
1121
// NOTE: Must be run as a goroutine to avoid blocking on sending the result.
1112
- func (t * TxPublisher ) handleThirdPartySpent (r * monitorRecord ,
1113
- requestID uint64 ) {
1114
-
1122
+ func (t * TxPublisher ) handleThirdPartySpent (r * monitorRecord ) {
1115
1123
defer t .wg .Done ()
1116
1124
1117
1125
// Create a result that will be sent to the resultChan which is
@@ -1123,7 +1131,7 @@ func (t *TxPublisher) handleThirdPartySpent(r *monitorRecord,
1123
1131
result := & BumpResult {
1124
1132
Event : TxFailed ,
1125
1133
Tx : r .tx ,
1126
- requestID : requestID ,
1134
+ requestID : r . requestID ,
1127
1135
Err : ErrThirdPartySpent ,
1128
1136
}
1129
1137
@@ -1134,7 +1142,7 @@ func (t *TxPublisher) handleThirdPartySpent(r *monitorRecord,
1134
1142
// createAndPublishTx creates a new tx with a higher fee rate and publishes it
1135
1143
// to the network. It will update the record with the new tx and fee rate if
1136
1144
// successfully created, and return the result when published successfully.
1137
- func (t * TxPublisher ) createAndPublishTx (requestID uint64 ,
1145
+ func (t * TxPublisher ) createAndPublishTx (
1138
1146
r * monitorRecord ) fn.Option [BumpResult ] {
1139
1147
1140
1148
// Fetch the old tx.
@@ -1185,16 +1193,16 @@ func (t *TxPublisher) createAndPublishTx(requestID uint64,
1185
1193
Event : TxFailed ,
1186
1194
Tx : oldTx ,
1187
1195
Err : err ,
1188
- requestID : requestID ,
1196
+ requestID : r . requestID ,
1189
1197
})
1190
1198
}
1191
1199
1192
1200
// The tx has been created without any errors, we now register a new
1193
1201
// record by overwriting the same requestID.
1194
- t .storeRecord (requestID , sweepCtx , r .req , r .feeFunction )
1202
+ t .storeRecord (r . requestID , sweepCtx , r .req , r .feeFunction )
1195
1203
1196
1204
// Attempt to broadcast this new tx.
1197
- result , err := t .broadcast (requestID )
1205
+ result , err := t .broadcast (r . requestID )
1198
1206
if err != nil {
1199
1207
log .Infof ("Failed to broadcast replacement tx %v: %v" ,
1200
1208
sweepCtx .tx .TxHash (), err )
0 commit comments