Skip to content
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

sweepbatcher: add mode with presigned transactions #891

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

starius
Copy link
Collaborator

@starius starius commented Feb 27, 2025

In this mode sweepbatcher uses transactions provided by the Presigned helper.
Transactions are signed upon adding an input to a batch.

A single Batcher instance can handle both presigned and regular batches.
Currently presigned and non-presigned sweeps never appear in the same batch.

Pull Request Checklist

  • Update release_notes.md if your PR contains major features, breaking changes or bugfixes

@starius starius self-assigned this Feb 28, 2025
@starius starius marked this pull request as ready for review February 28, 2025 03:55
starius added 5 commits March 4, 2025 14:13
In this mode sweepbatcher uses transactions provided by the Presigned helper.
Transactions are signed upon adding an input to a batch.

A single Batcher instance can handle both presigned and regular batches.
Currently presigned and non-presigned sweeps never appear in the same batch.
Copy link
Collaborator

@hieblmi hieblmi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work @starius. I've left a couple of questions in my first pass.

for _, s := range b.sweeps {
if !s.presigned {
b.log().Infof("failed to add sweep %x to the "+
"batch, because the batch has "+
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe clarify "failed to add presigned sweep %x..."

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

// Ensure that all the sweeps in the batch don't use presigned.
for _, s := range b.sweeps {
if s.presigned {
b.log().Infof("failed to add sweep %x to the "+
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe clarify "failed to add non-presigned sweep %x..."

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


for _, sweep := range b.sweeps {
if sweep.presigned {
return true, nil
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if all sweeps are presigned we return true, false otherwise. So we should return false here if !sweep.presigned, otherwise a presigned batch could still have non-presigned sweeps.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I rewrote the function to ensure that all the sweeps have the same presigned status. If there is a mix, the function returns an error. This would be a bug.

@@ -564,8 +628,40 @@ func (b *Batcher) Run(ctx context.Context) error {
}
}

// PresignSweep creates and stores presigned 1:1 transactions for the sweep.
// This method must be called prior to AddSweep if presigned mode is enabled.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this is ensured in the batch by b.ensurePresigned

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated ensurePresigned and SignTx interface (added argument presignedOnly), so ensurePresigned actually ensured that it is presigned, not tried to sign (become read-only). Also added a test making sure that the batcher crashes if AddSweep is called before calling PresignSweep (for a presigned sweep). (AddSweep can't return that error, since it only pushes a sweep to the event loop.)

}

// Find the feerate needed to get into next block. Use conf_target=2,
nextBlockFeerate, err := b.wallet.EstimateFeeRate(ctx, 2)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: camel case nextBlockFeeRate

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

return false, nil
}
} else {
if err := b.ensurePresigned(ctx, sweep); err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if err == nil here, don't we then have to call b.presign for the sweep here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If ensurePresigned returned no error, this means, it has been presigned already. No need to presign again. If not presigned, then crash the batcher (this is only possible because of a bug).

// use the same mode (presigned or regular).
if sweep.presigned {
// Ensure that all the sweeps in the batch use presigned mode.
for _, s := range b.sweeps {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of iterating, do you think it makes sense to add a presigned flag to the batch struct that we can check before adding a sweep to a batch?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I plan to allow half-presigned batches in the future to use a regular sweep an an anchor and such a flag would be removed. So I decided to keep this calculated not to forget to remove it in the future :)

batchAmt += sweep.value
}

// Find when at least one sweep expires.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "find the sweep with the earliest expiry"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

}

// Find the feerate needed to get into next block. Use conf_target=2,
nextBlockFeerate, err := b.wallet.EstimateFeeRate(ctx, 2)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it 2? Maybe create a constant?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated this place:

        // priorityConfTarget defines the confirmation target for quick
        // inclusion in a block. A value of 2, rather than 1, is used to prevent
        // overestimation caused by temporary anomalies, such as periods without
        // blocks.
        const priorityConfTarget = 2

        // Find the feerate needed to get into next block.
        nextBlockFeeRate, err := b.wallet.EstimateFeeRate(
                ctx, priorityConfTarget,
        )

This fee rate is only used to define a high fee rate (10x of this value and at least 100 sats/vbyte).

starius added 4 commits March 5, 2025 15:18
This is needed to implement ensurePresigned as read-only, so it only checks if
a presigned transaction exists, not tries to sign it.
@starius starius requested a review from hieblmi March 6, 2025 14:15
@lightninglabs-deploy
Copy link

@hieblmi: review reminder

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants