-
Notifications
You must be signed in to change notification settings - Fork 123
sweepbatcher: batch change outputs #976
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
19b13cd
to
c7091de
Compare
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces the ability to handle change outputs in sweep batches, which is a significant feature. I've found a critical bug in fee calculation within CheckSignedTx
that needs to be addressed. I've also pointed out a minor code simplification and a gap in test coverage for the new logic.
c20504a
to
0567051
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
The pull request introduces functionality to handle change outputs in sweep batcher, specifically for presigned transactions. The changes involve modifying the sweep
struct, updating transaction construction to include change outputs, and adding a function to retrieve and de-duplicate change outputs. The code also includes unit tests for the new functionality. The changes look good overall, but there are a few areas that could be improved for robustness and clarity.
0567051
to
950fd4e
Compare
576270f
to
35f5810
Compare
This seems to be outdated. |
35f5810
to
4c58f85
Compare
fe4ec68
to
c0418e3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 🥇
Added a couple of proposals.
c0418e3
to
1b73395
Compare
4d91489
to
767b9cd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 🌴
One comment pending: #976 (comment)
767b9cd
to
738ff64
Compare
This commit adds an optional change output to the sweep struct.
Presigning sweeps takes change outputs into account. Each primary deposit id of a sweep group points to an optional change output. sweepbatcher.presign scans all passed sweeps for change outputs and passes them to constructUnsignedTx. Optional change of a swap is encoded in its sweeps as a pointer to the same change output. This change is taken into account when constructing the unsigned batch transaction when it comes to tx weight and outputs.
738ff64
to
26c8b27
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM pending subtle issues with dust limits and relay fee! 💾
Please add min relay fee to constructUnsignedTx
in a separate commit, since it is a separate factor.
}, | ||
sweep: feeDetails{ | ||
FeeRate: highFeeRate, | ||
Weight: coopInputWeight + changeOutputWeight, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test case passes even if changeOutputWeight
is not added. Also its name is confusing, because the sweep is not placed in "existing medium batch", but it also added to a new batch.
I propose to replace this test case which another one which works as control for "low fee change sweep, placed in new batch":
diff --git a/sweepbatcher/greedy_batch_selection_test.go b/sweepbatcher/greedy_batch_selection_test.go
index 33b0d5a..0a819f9 100644
--- a/sweepbatcher/greedy_batch_selection_test.go
+++ b/sweepbatcher/greedy_batch_selection_test.go
@@ -835,8 +835,8 @@ func TestSelectBatches(t *testing.T) {
},
{
- name: "high fee change sweep, placed in existing " +
- "medium batch",
+ name: "low fee sweep without change, placed in "+
+ "existing batch",
batches: []feeDetails{
{
BatchId: 1,
@@ -845,14 +845,14 @@ func TestSelectBatches(t *testing.T) {
},
},
sweep: feeDetails{
- FeeRate: highFeeRate,
- Weight: coopInputWeight + changeOutputWeight,
+ FeeRate: lowFeeRate,
+ Weight: coopInputWeight,
},
oneSweepBatch: feeDetails{
- FeeRate: highFeeRate,
+ FeeRate: lowFeeRate,
Weight: coopNewBatchWeight,
},
- wantBestBatchesIds: []int32{newBatchSignal, 1},
+ wantBestBatchesIds: []int32{1, newBatchSignal},
},
}
// Clamp the calculated fee to the max allowed fee amount for the batch. | ||
fee := clampBatchFee(feeForWeight, batchAmt) | ||
fee := clampBatchFee(feeForWeight, batchAmt-btcutil.Amount(sumChange)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In test TestPresigned/dust_main_output
I saw:
fee 0.00000065 BTC
Such a fee is too low (below relay fee).
I think we should fail here if the fee is below relay fee rate. The function should accept min relay fee rate as an argument, we already have the value in many places, where the function is called.
Feerate can be found with chainfee.NewSatPerKWeight(fee, weight)
.
Please add a unit test for constructUnsignedTx
for this error and adjust test TestPresigned/dust_main_output
not to crash on this error. Additionally, you can add another test case for TestPresigned to reproduce this new error (fee below relay fee).
@@ -70,6 +97,8 @@ func TestConstructUnsignedTx(t *testing.T) { | |||
return fmt.Errorf("weight estimator test failure") | |||
} | |||
|
|||
dustLimit := lnwallet.DustLimitForSize(input.P2TRSize) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
destAddr
and batchPkScript
used as batch destination address in most cases are a p2wkh address, not taproot.
I propose to use our new function utils.DustLimitForPkScript(batchPkScript)
here instead of lnwallet.DustLimitForSize(input.P2TRSize)
to get the same values. The numeric values are different. Taproot is 330, p2wkh is 294.
I discovered this by changing change amounts by 2 satoshis in the test cases:
diff --git a/sweepbatcher/sweep_batcher_presigned_test.go b/sweepbatcher/sweep_batcher_presigned_test.go
index fd28bc7..2ad90ab 100644
--- a/sweepbatcher/sweep_batcher_presigned_test.go
+++ b/sweepbatcher/sweep_batcher_presigned_test.go
@@ -1318,7 +1318,7 @@ func testPresigned_presigned_group_with_dust_main_output(t *testing.T,
}
dustLimit := int64(lnwallet.DustLimitForSize(input.P2TRSize))
change := &wire.TxOut{
- Value: inputValue - dustLimit + 1,
+ Value: inputValue - dustLimit - 1,
PkScript: []byte{0xaf, 0xfe},
}
@@ -1401,7 +1401,7 @@ func testPresigned_presigned_group_with_dust_change(t *testing.T,
}
dustLimit := lnwallet.DustLimitForSize(input.P2TRSize)
change := &wire.TxOut{
- Value: int64(dustLimit - 1),
+ Value: int64(dustLimit + 1),
PkScript: []byte{0xaf, 0xfe},
}
My expectation was that inputs would be added successfully (and the tests would fail, as they test failures). However it was not the case, because these dustLimit
variables used in sweep_batch_test.go
are higher than the actual limit.
Please use utils.DustLimitForPkScript(batchPkScript)
here below in this file.
The batcher receives the ability to sign and publish batches with change outputs.
Change is created when the clients choose fractional swap amounts from the input values to be swapped. Usually the change is sent back to client's addresses.
If change is provided to
ensurePresigned
,presign
andpublishPresigned
, it is expected to be placed within the passed[]sweep
.Each
sweep
optionally holds a pointer to a change output. Only the first sweep in a sweep group called primary deposit will hold a pointer to the respective swap's change output.