@@ -169,9 +169,10 @@ type batchConfig struct {
169169 // initial delay completion and publishing the batch transaction.
170170 batchPublishDelay time.Duration
171171
172- // noBumping instructs sweepbatcher not to fee bump itself and rely on
173- // external source of fee rates (FeeRateProvider).
174- noBumping bool
172+ // customFeeRate provides custom min fee rate per swap. The batch uses
173+ // max of the fee rates of its swaps. In this mode confTarget is
174+ // ignored and fee bumping by sweepbatcher is disabled.
175+ customFeeRate FeeRateProvider
175176
176177 // txLabeler is a function generating a transaction label. It is called
177178 // before publishing a batch transaction. Batch ID is passed to it.
@@ -723,6 +724,9 @@ func (b *batch) addSweeps(ctx context.Context, sweeps []*sweep) (bool, error) {
723724 // lower that minFeeRate of other sweeps (so it is
724725 // applied).
725726 if b .rbfCache .FeeRate < s .minFeeRate {
727+ b .Infof ("Increasing feerate of the batch " +
728+ "from %v to %v" , b .rbfCache .FeeRate ,
729+ s .minFeeRate )
726730 b .rbfCache .FeeRate = s .minFeeRate
727731 }
728732 }
@@ -769,6 +773,9 @@ func (b *batch) addSweeps(ctx context.Context, sweeps []*sweep) (bool, error) {
769773 // Update FeeRate. Max(s.minFeeRate) for all the sweeps of
770774 // the batch is the basis for fee bumps.
771775 if b .rbfCache .FeeRate < s .minFeeRate {
776+ b .Infof ("Increasing feerate of the batch " +
777+ "from %v to %v" , b .rbfCache .FeeRate ,
778+ s .minFeeRate )
772779 b .rbfCache .FeeRate = s .minFeeRate
773780 b .rbfCache .SkipNextBump = true
774781 }
@@ -968,6 +975,12 @@ func (b *batch) Run(ctx context.Context) error {
968975 continue
969976 }
970977
978+ // Update feerate of sweeps. This is normally done by
979+ // AddSweep, but it may not be called after the sweep
980+ // is confirmed, but fresh feerate is still needed to
981+ // keep publishing in case of reorg.
982+ b .updateFeeRate (ctx )
983+
971984 err := b .publish (ctx )
972985 if err != nil {
973986 return fmt .Errorf ("publish error: %w" , err )
@@ -1016,6 +1029,41 @@ func (b *batch) Run(ctx context.Context) error {
10161029 }
10171030}
10181031
1032+ // updateFeeRate gets fresh values of minFeeRate for sweeps and updates the
1033+ // feerate of the batch if needed. This method must be called from event loop.
1034+ func (b * batch ) updateFeeRate (ctx context.Context ) {
1035+ for outpoint , s := range b .sweeps {
1036+ minFeeRate , err := minimumSweepFeeRate (
1037+ ctx , b .cfg .customFeeRate , b .wallet ,
1038+ s .swapHash , s .outpoint , s .confTarget ,
1039+ )
1040+ if err != nil {
1041+ b .Warnf ("failed to determine feerate for sweep %v of " +
1042+ "swap %x, confTarget %d: %w" , s .outpoint ,
1043+ s .swapHash [:6 ], s .confTarget , err )
1044+ continue
1045+ }
1046+
1047+ if minFeeRate <= s .minFeeRate {
1048+ continue
1049+ }
1050+
1051+ b .Infof ("Increasing feerate of sweep %v of swap %x from %v " +
1052+ "to %v" , s .outpoint , s .swapHash [:6 ], s .minFeeRate ,
1053+ minFeeRate )
1054+ s .minFeeRate = minFeeRate
1055+ b .sweeps [outpoint ] = s
1056+
1057+ if s .minFeeRate <= b .rbfCache .FeeRate {
1058+ continue
1059+ }
1060+
1061+ b .Infof ("Increasing feerate of the batch from %v to %v" ,
1062+ b .rbfCache .FeeRate , s .minFeeRate )
1063+ b .rbfCache .FeeRate = s .minFeeRate
1064+ }
1065+ }
1066+
10191067// testRunInEventLoop runs a function in the event loop blocking until
10201068// the function returns. For unit tests only!
10211069func (b * batch ) testRunInEventLoop (ctx context.Context , handler func ()) {
@@ -1793,7 +1841,7 @@ func (b *batch) updateRbfRate(ctx context.Context) error {
17931841
17941842 // Set the initial value for our fee rate.
17951843 b .rbfCache .FeeRate = rate
1796- } else if ! b .cfg .noBumping {
1844+ } else if noBumping := b .cfg .customFeeRate != nil ; ! noBumping {
17971845 if b .rbfCache .SkipNextBump {
17981846 // Skip fee bumping, unset the flag, to bump next time.
17991847 b .rbfCache .SkipNextBump = false
0 commit comments