2
0
mirror of https://github.com/lightninglabs/loop synced 2024-11-09 19:10:47 +00:00

sweepbatcher: make greedy algo mixed batch aware

This commit is contained in:
Boris Nagaev 2024-07-29 23:36:50 -03:00
parent d007cf6e20
commit b171f76b27
No known key found for this signature in database
2 changed files with 199 additions and 27 deletions

View File

@ -51,7 +51,7 @@ func (b *Batcher) greedyAddSweep(ctx context.Context, sweep *sweep) error {
// Run the algorithm. Get batchId of possible batches, sorted from best
// to worst.
batchesIds, err := selectBatches(
batches, sweepFeeDetails, newBatchFeeDetails,
batches, sweepFeeDetails, newBatchFeeDetails, b.mixedBatch,
)
if err != nil {
return fmt.Errorf("batch selection algorithm failed for sweep "+
@ -129,6 +129,7 @@ func estimateSweepFeeIncrement(s *sweep) (feeDetails, feeDetails, error) {
IsExternalAddr: s.isExternalAddr,
// Calculate sweep weight as a difference.
MixedWeight: fd2.MixedWeight - fd1.MixedWeight,
CoopWeight: fd2.CoopWeight - fd1.CoopWeight,
NonCoopWeight: fd2.NonCoopWeight - fd1.NonCoopWeight,
}
@ -177,11 +178,16 @@ func estimateBatchWeight(batch *batch) (feeDetails, error) {
destAddr = (*btcutil.AddressTaproot)(nil)
}
// Make two estimators: for coop and non-coop cases.
var coopWeight, nonCoopWeight input.TxWeightEstimator
// Make three estimators: for mixed, coop and non-coop cases.
var mixedWeight, coopWeight, nonCoopWeight input.TxWeightEstimator
// Add output weight to the estimator.
err := sweeppkg.AddOutputEstimate(&coopWeight, destAddr)
err := sweeppkg.AddOutputEstimate(&mixedWeight, destAddr)
if err != nil {
return feeDetails{}, fmt.Errorf("sweep.AddOutputEstimate: %w",
err)
}
err = sweeppkg.AddOutputEstimate(&coopWeight, destAddr)
if err != nil {
return feeDetails{}, fmt.Errorf("sweep.AddOutputEstimate: %w",
err)
@ -194,6 +200,19 @@ func estimateBatchWeight(batch *batch) (feeDetails, error) {
// Add inputs.
for _, sweep := range batch.sweeps {
if sweep.nonCoopHint || sweep.coopFailed {
err = sweep.htlcSuccessEstimator(&mixedWeight)
if err != nil {
return feeDetails{}, fmt.Errorf(
"htlcSuccessEstimator failed: %w", err,
)
}
} else {
mixedWeight.AddTaprootKeySpendInput(
txscript.SigHashDefault,
)
}
coopWeight.AddTaprootKeySpendInput(txscript.SigHashDefault)
err = sweep.htlcSuccessEstimator(&nonCoopWeight)
@ -206,6 +225,7 @@ func estimateBatchWeight(batch *batch) (feeDetails, error) {
return feeDetails{
BatchId: batch.id,
FeeRate: batch.rbfCache.FeeRate,
MixedWeight: mixedWeight.Weight(),
CoopWeight: coopWeight.Weight(),
NonCoopWeight: nonCoopWeight.Weight(),
NonCoopHint: hasNonCoop,
@ -222,6 +242,7 @@ const newBatchSignal = -1
type feeDetails struct {
BatchId int32
FeeRate chainfee.SatPerKWeight
MixedWeight lntypes.WeightUnit
CoopWeight lntypes.WeightUnit
NonCoopWeight lntypes.WeightUnit
NonCoopHint bool
@ -229,11 +250,14 @@ type feeDetails struct {
}
// fee returns fee of onchain transaction representing this instance.
func (e feeDetails) fee() btcutil.Amount {
func (e feeDetails) fee(mixedBatch bool) btcutil.Amount {
var weight lntypes.WeightUnit
if e.NonCoopHint {
switch {
case mixedBatch:
weight = e.MixedWeight
case e.NonCoopHint:
weight = e.NonCoopWeight
} else {
default:
weight = e.CoopWeight
}
@ -250,6 +274,7 @@ func (e1 feeDetails) combine(e2 feeDetails) feeDetails {
return feeDetails{
FeeRate: feeRate,
MixedWeight: e1.MixedWeight + e2.MixedWeight,
CoopWeight: e1.CoopWeight + e2.CoopWeight,
NonCoopWeight: e1.NonCoopWeight + e2.NonCoopWeight,
NonCoopHint: e1.NonCoopHint || e2.NonCoopHint,
@ -259,21 +284,26 @@ func (e1 feeDetails) combine(e2 feeDetails) feeDetails {
// selectBatches returns the list of id of batches sorted from best to worst.
// Creation a new batch is encoded as newBatchSignal. For each batch its fee
// rate and two weights are provided: weight in case of cooperative spending and
// weight in case non-cooperative spending (using preimages instead of taproot
// key spend). Also, a hint is provided to signal if the batch has to use
// non-cooperative spending path. The same data is also provided to the sweep
// for which we are selecting a batch to add. In case of the sweep weights are
// weight deltas resulted from adding the sweep. Finally, the same data is
// provided for new batch having this sweep only. The algorithm compares costs
// of adding the sweep to each existing batch, and costs of new batch creation
// for this sweep and returns BatchId of the winning batch. If the best option
// is to create a new batch, return newBatchSignal. Each fee details has also
// IsExternalAddr flag. There is a rule that sweeps having flag IsExternalAddr
// must go in individual batches. Cooperative spending is only available if all
// the sweeps support cooperative spending path.
func selectBatches(batches []feeDetails, sweep, oneSweepBatch feeDetails) (
[]int32, error) {
// rate and a set of weights are provided: weight in case of a mixed batch,
// weight in case of cooperative spending and weight in case non-cooperative
// spending. Also, a hint is provided to signal what spending path will be used
// by the batch.
//
// The same data is also provided for the sweep for which we are selecting a
// batch to add. In case of the sweep weights are weight deltas resulted from
// adding the sweep. Finally, the same data is provided for new batch having
// this sweep only.
//
// The algorithm compares costs of adding the sweep to each existing batch, and
// costs of new batch creation for this sweep and returns BatchId of the winning
// batch. If the best option is to create a new batch, return newBatchSignal.
//
// Each fee details has also IsExternalAddr flag. There is a rule that sweeps
// having flag IsExternalAddr must go in individual batches. Cooperative
// spending is only available if all the sweeps support cooperative spending
// path of in a mixed batch.
func selectBatches(batches []feeDetails, sweep, oneSweepBatch feeDetails,
mixedBatch bool) ([]int32, error) {
// If the sweep has IsExternalAddr flag, the sweep can't be added to
// a batch, so create new batch for it.
@ -294,7 +324,7 @@ func selectBatches(batches []feeDetails, sweep, oneSweepBatch feeDetails) (
// creation with this sweep only in it. The cost is its full fee.
alternatives = append(alternatives, alternative{
batchId: newBatchSignal,
cost: oneSweepBatch.fee(),
cost: oneSweepBatch.fee(mixedBatch),
})
// Try to add the sweep to every batch, calculate the costs and
@ -310,7 +340,7 @@ func selectBatches(batches []feeDetails, sweep, oneSweepBatch feeDetails) (
combinedBatch := batch.combine(sweep)
// The cost is the fee increase.
cost := combinedBatch.fee() - batch.fee()
cost := combinedBatch.fee(mixedBatch) - batch.fee(mixedBatch)
// The cost must be positive, because we added a sweep.
if cost <= 0 {

View File

@ -29,9 +29,9 @@ const (
) * 4
coopTwoSweepBatchWeight = coopNewBatchWeight + coopInputWeight
nonCoopTwoSweepBatchWeight = coopTwoSweepBatchWeight +
2*nonCoopPenalty
v2v3BatchWeight = nonCoopTwoSweepBatchWeight - 25
nonCoopTwoSweepBatchWeight = coopTwoSweepBatchWeight + 2*nonCoopPenalty
v2v3BatchWeight = nonCoopTwoSweepBatchWeight - 25
mixedTwoSweepBatchWeight = coopTwoSweepBatchWeight + nonCoopPenalty
)
// testHtlcV2SuccessEstimator adds weight of non-cooperative input to estimator
@ -86,11 +86,13 @@ func TestEstimateSweepFeeIncrement(t *testing.T) {
},
wantSweepFeeDetails: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
},
wantNewBatchFeeDetails: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
@ -104,11 +106,13 @@ func TestEstimateSweepFeeIncrement(t *testing.T) {
},
wantSweepFeeDetails: feeDetails{
FeeRate: highFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
},
wantNewBatchFeeDetails: feeDetails{
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
@ -124,12 +128,14 @@ func TestEstimateSweepFeeIncrement(t *testing.T) {
},
wantSweepFeeDetails: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
IsExternalAddr: true,
},
wantNewBatchFeeDetails: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
IsExternalAddr: true,
@ -146,12 +152,15 @@ func TestEstimateSweepFeeIncrement(t *testing.T) {
},
wantSweepFeeDetails: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
IsExternalAddr: true,
},
wantNewBatchFeeDetails: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight -
p2pkhDiscount,
CoopWeight: coopNewBatchWeight -
p2pkhDiscount,
NonCoopWeight: nonCoopNewBatchWeight -
@ -169,12 +178,14 @@ func TestEstimateSweepFeeIncrement(t *testing.T) {
},
wantSweepFeeDetails: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
NonCoopHint: true,
},
wantNewBatchFeeDetails: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
@ -190,12 +201,14 @@ func TestEstimateSweepFeeIncrement(t *testing.T) {
},
wantSweepFeeDetails: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
NonCoopHint: true,
},
wantNewBatchFeeDetails: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
@ -251,6 +264,7 @@ func TestEstimateBatchWeight(t *testing.T) {
wantBatchFeeDetails: feeDetails{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
@ -275,6 +289,7 @@ func TestEstimateBatchWeight(t *testing.T) {
wantBatchFeeDetails: feeDetails{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: coopTwoSweepBatchWeight,
CoopWeight: coopTwoSweepBatchWeight,
NonCoopWeight: nonCoopTwoSweepBatchWeight,
},
@ -299,6 +314,7 @@ func TestEstimateBatchWeight(t *testing.T) {
wantBatchFeeDetails: feeDetails{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: coopTwoSweepBatchWeight,
CoopWeight: coopTwoSweepBatchWeight,
NonCoopWeight: v2v3BatchWeight,
},
@ -320,6 +336,7 @@ func TestEstimateBatchWeight(t *testing.T) {
wantBatchFeeDetails: feeDetails{
BatchId: 1,
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
@ -345,6 +362,7 @@ func TestEstimateBatchWeight(t *testing.T) {
wantBatchFeeDetails: feeDetails{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: mixedTwoSweepBatchWeight,
CoopWeight: coopTwoSweepBatchWeight,
NonCoopWeight: nonCoopTwoSweepBatchWeight,
NonCoopHint: true,
@ -371,6 +389,7 @@ func TestEstimateBatchWeight(t *testing.T) {
wantBatchFeeDetails: feeDetails{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: mixedTwoSweepBatchWeight,
CoopWeight: coopTwoSweepBatchWeight,
NonCoopWeight: nonCoopTwoSweepBatchWeight,
NonCoopHint: true,
@ -395,6 +414,7 @@ func TestEstimateBatchWeight(t *testing.T) {
wantBatchFeeDetails: feeDetails{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
IsExternalAddr: true,
@ -420,6 +440,7 @@ func TestSelectBatches(t *testing.T) {
name string
batches []feeDetails
sweep, oneSweepBatch feeDetails
mixedBatch bool
wantBestBatchesIds []int32
}{
{
@ -427,11 +448,13 @@ func TestSelectBatches(t *testing.T) {
batches: []feeDetails{},
sweep: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
},
oneSweepBatch: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
@ -444,17 +467,20 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
},
sweep: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
},
oneSweepBatch: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
@ -467,17 +493,20 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 1,
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
},
sweep: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
},
oneSweepBatch: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
@ -490,23 +519,27 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
},
sweep: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
},
oneSweepBatch: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
@ -519,23 +552,27 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
},
sweep: feeDetails{
FeeRate: highFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
},
oneSweepBatch: feeDetails{
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
@ -548,24 +585,28 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
},
sweep: feeDetails{
FeeRate: highFeeRate,
MixedWeight: nonCoopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
NonCoopHint: true,
},
oneSweepBatch: feeDetails{
FeeRate: highFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
@ -579,24 +620,28 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: 10000,
CoopWeight: 10000,
NonCoopWeight: 15000,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: 10000,
CoopWeight: 10000,
NonCoopWeight: 15000,
},
},
sweep: feeDetails{
FeeRate: highFeeRate,
MixedWeight: nonCoopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
NonCoopHint: true,
},
oneSweepBatch: feeDetails{
FeeRate: highFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
@ -604,18 +649,56 @@ func TestSelectBatches(t *testing.T) {
wantBestBatchesIds: []int32{newBatchSignal, 2, 1},
},
{
name: "high fee noncoop sweep, large batches, mixed",
batches: []feeDetails{
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: 10000,
CoopWeight: 10000,
NonCoopWeight: 15000,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: 10000,
CoopWeight: 10000,
NonCoopWeight: 15000,
},
},
sweep: feeDetails{
FeeRate: highFeeRate,
MixedWeight: nonCoopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
NonCoopHint: true,
},
oneSweepBatch: feeDetails{
FeeRate: highFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
},
mixedBatch: true,
wantBestBatchesIds: []int32{2, newBatchSignal, 1},
},
{
name: "high fee noncoop sweep, high batch noncoop",
batches: []feeDetails{
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
@ -623,12 +706,14 @@ func TestSelectBatches(t *testing.T) {
},
sweep: feeDetails{
FeeRate: highFeeRate,
MixedWeight: nonCoopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
NonCoopHint: true,
},
oneSweepBatch: feeDetails{
FeeRate: highFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
@ -642,24 +727,28 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
},
sweep: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
NonCoopHint: true,
},
oneSweepBatch: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
@ -673,24 +762,28 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: 10000,
CoopWeight: 10000,
NonCoopWeight: 15000,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: 10000,
CoopWeight: 10000,
NonCoopWeight: 15000,
},
},
sweep: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
NonCoopHint: true,
},
oneSweepBatch: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
@ -698,12 +791,49 @@ func TestSelectBatches(t *testing.T) {
wantBestBatchesIds: []int32{newBatchSignal, 1, 2},
},
{
name: "low fee noncoop sweep, large batches, mixed",
batches: []feeDetails{
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: 10000,
CoopWeight: 10000,
NonCoopWeight: 15000,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: 10000,
CoopWeight: 10000,
NonCoopWeight: 15000,
},
},
sweep: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
NonCoopHint: true,
},
oneSweepBatch: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
},
mixedBatch: true,
wantBestBatchesIds: []int32{1, newBatchSignal, 2},
},
{
name: "low fee noncoop sweep, low batch noncoop",
batches: []feeDetails{
{
BatchId: 1,
FeeRate: lowFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
@ -711,18 +841,21 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
},
sweep: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
NonCoopHint: true,
},
oneSweepBatch: feeDetails{
FeeRate: lowFeeRate,
MixedWeight: nonCoopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
NonCoopHint: true,
@ -736,24 +869,28 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 1,
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
},
sweep: feeDetails{
FeeRate: highFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
IsExternalAddr: true,
},
oneSweepBatch: feeDetails{
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
IsExternalAddr: true,
@ -767,12 +904,14 @@ func TestSelectBatches(t *testing.T) {
{
BatchId: 1,
FeeRate: highFeeRate - 1,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
{
BatchId: 2,
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
IsExternalAddr: true,
@ -780,11 +919,13 @@ func TestSelectBatches(t *testing.T) {
},
sweep: feeDetails{
FeeRate: highFeeRate,
MixedWeight: coopInputWeight,
CoopWeight: coopInputWeight,
NonCoopWeight: nonCoopInputWeight,
},
oneSweepBatch: feeDetails{
FeeRate: highFeeRate,
MixedWeight: coopNewBatchWeight,
CoopWeight: coopNewBatchWeight,
NonCoopWeight: nonCoopNewBatchWeight,
},
@ -797,6 +938,7 @@ func TestSelectBatches(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
gotBestBatchesIds, err := selectBatches(
tc.batches, tc.sweep, tc.oneSweepBatch,
tc.mixedBatch,
)
require.NoError(t, err)
require.Equal(