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

dont use sweeper unconfirmed utxos #8545

Merged

Conversation

ziggie1984
Copy link
Collaborator

@ziggie1984 ziggie1984 commented Mar 13, 2024

Fixes #8543
Fixes #8540

We will not use any unconfirmed funds which are labeled by the sweeper subsystem to open internal wallet funded channels.

Seems to be a quick win comparing the change scope ?

@yyforyongyu or is this fix already part of your sweeper series ?

Added an itest to verify this behavior.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Improved UTXO selection for internal channel funding to enhance transaction security by excluding unconfirmed and labeled UTXOs.
    • Added a new test case to verify channel funding with labeled transactions, ensuring robustness against potential Replace-By-Fee (RBF) issues.
    • Introduced a method to fetch transaction labels from the wallet, aiding in transaction management and identification.
  • Bug Fixes

    • Updated error messages to provide clearer information when a funding transaction is locked by the sweeper subsystem, improving user understanding of transaction status.
  • Tests

    • Expanded testing suite to cover new functionalities and error handling improvements related to channel funding and UTXO selection.

Copy link

coderabbitai bot commented Mar 13, 2024

Important

Auto Review Skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This set of changes focuses on enhancing the UTXO selection process for channel funding within a cryptocurrency network, specifically targeting the exclusion of unconfirmed and labeled UTXOs by the sweeper subsystem. It introduces new testing for channel funding with labeled transactions, updates error messaging for clarity on UTXO status, and adds functionality to fetch transaction labels. These improvements aim to prevent the use of potentially compromised UTXOs in critical operations, thereby increasing the robustness and reliability of channel funding.

Changes

Files Change Summary
docs/release-notes/release-notes-0.18.0.md Improved UTXO selection by excluding unconfirmed and labeled UTXOs.
funding/manager.go, funding/manager_test.go Added functions to query and exclude unconfirmed utxos for funding.
itest/list_on_test.go, itest/lnd_funding_test.go, lnwallet/chanfunding/wallet_assembler.go Updated error messaging and logic for handling locked UTXOs by the sweeper subsystem.
lntest/mock/walletcontroller.go, lnwallet/btcwallet/btcwallet.go, lnwallet/interface.go, lnwallet/mock.go Added FetchTxLabel method to fetch transaction labels.

Assessment against linked issues

Objective Addressed Explanation
Don't allow unconfirmed Inputs for Channel Openings which are used/labeled by the sweeper subsystem (#8543)
Address transaction broadcast failures and mempool scanning issues (#7300) The changes do not directly address transaction broadcast failures or enhance mempool scanning during wallet restoration.
Correctly handle RBFed inputs in funding transactions (#7971)
Improve error handling for spent UTXO in channel funding (#7300, #7971)

Possibly related issues

🐇🎉
To the lands of code, where changes abound,
A rabbit hopped, improvements found.
No unconfirmed UTXOs to be seen,
For the sweeper's label keeps them clean.
With tests in tow and errors clear,
The channels open, devoid of fear.
🎊🐰


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch 2 times, most recently from d7b91d0 to 546e369 Compare March 13, 2024 10:43
@yyforyongyu
Copy link
Collaborator

Nope it's not part of the sweeper scope, and concept ACK.

@saubyk saubyk added this to the v0.18.0 milestone Mar 13, 2024
@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from b289f05 to 86d8d12 Compare March 13, 2024 16:21
@ziggie1984 ziggie1984 added the funding Related to the opening of new channels with funding transactions on the blockchain label Mar 13, 2024
@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch 2 times, most recently from 1010d7f to 404f2bd Compare March 13, 2024 16:28
@ziggie1984 ziggie1984 marked this pull request as ready for review March 13, 2024 16:29
@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from 404f2bd to 9c6b9f9 Compare March 13, 2024 16:45
@aakselrod
Copy link
Contributor

Concept ACK, looking forward to this fix!

@ProofOfKeags ProofOfKeags requested review from ProofOfKeags, a team and bhandras and removed request for a team March 13, 2024 20:52
@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from 9c6b9f9 to de9b38c Compare March 13, 2024 22:31
@ziggie1984
Copy link
Collaborator Author

@coderabbitai review

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Review Status

Actionable comments generated: 2

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between d9887f3 and de9b38c.
Files selected for processing (10)
  • docs/release-notes/release-notes-0.18.0.md (1 hunks)
  • itest/list_on_test.go (1 hunks)
  • itest/lnd_channel_funding_utxo_selection_test.go (1 hunks)
  • itest/lnd_funding_test.go (2 hunks)
  • lntest/mock/walletcontroller.go (1 hunks)
  • lnwallet/btcwallet/btcwallet.go (1 hunks)
  • lnwallet/chanfunding/wallet_assembler.go (1 hunks)
  • lnwallet/interface.go (1 hunks)
  • lnwallet/mock.go (1 hunks)
  • lnwallet/wallet.go (4 hunks)
Additional comments: 9
lntest/mock/walletcontroller.go (1)
  • 290-292: The implementation of FetchTxLabel in the mock WalletController returns a hardcoded empty string and nil error, which is appropriate for a mock. Ensure that this behavior aligns with the intended test scenarios where transaction labels are involved.
lnwallet/mock.go (1)
  • 300-303: The implementation of FetchTxLabel in the mockWalletController returns a hardcoded empty string and nil error, which is appropriate for a mock. Ensure that this behavior aligns with the intended test scenarios where transaction labels are involved.
itest/lnd_channel_funding_utxo_selection_test.go (1)
  • 333-334: The updated error message provides clearer information about why an outpoint cannot be reused for channel funding, specifically mentioning its lock by the sweeper subsystem. This enhancement improves the clarity and actionability of error messages in test scenarios.
itest/list_on_test.go (1)
  • 120-123: The addition of the new test case "open channel with labeled txns" is correctly implemented and follows the existing pattern for defining test cases. This test case is crucial for verifying the new behavior related to channel funding with labeled UTXOs, aligning with the PR's objectives.
docs/release-notes/release-notes-0.18.0.md (1)
  • 93-96: The summary of the fix for utxo selection in the internal channel funding flow is clear and concise. However, it would be beneficial to include a brief explanation of why using unconfirmed and labeled UTXOs by the sweeper subsystem poses a risk. This additional context can help users understand the importance of the fix and the potential issues it prevents.
lnwallet/chanfunding/wallet_assembler.go (1)
  • 306-307: The updated error message now explicitly mentions the possibility of an outpoint being locked by the sweeper subsystem. This enhancement improves clarity for the user, helping them understand the specific reason why an outpoint cannot be used for channel funding.
lnwallet/btcwallet/btcwallet.go (1)
  • 1926-1948: The implementation of FetchTxLabel correctly fetches the label of a transaction, handling cases where no label bucket exists or the transaction does not have a label by silencing the error. This approach is well-documented and aligns with the intended behavior.
lnwallet/wallet.go (2)
  • 2549-2581: > 📝 NOTE

This review was outside the diff hunks and was mapped to the diff hunk with the greatest overlap. Original lines [2537-2578]

The logic to exclude unconfirmed UTXOs marked by the sweeper subsystem from coin selection is sound and aligns with the goal of preventing the use of potentially replaceable transactions in critical operations like channel funding. However, it's important to ensure that this exclusion logic is consistently applied across all relevant parts of the wallet to maintain the integrity of the funding process.

  • 2552-2578: The implementation of excluding unconfirmed UTXOs marked by the sweeper subsystem is correctly done by checking the transaction label against the sweepLabel. This approach effectively prevents the use of such UTXOs in channel funding, which is crucial for avoiding issues related to transaction malleability and replace-by-fee (RBF) scenarios. The use of strings.Contains for label comparison is appropriate here, considering the label format.

lnwallet/interface.go Outdated Show resolved Hide resolved
itest/lnd_funding_test.go Outdated Show resolved Hide resolved
@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from de9b38c to 969ffae Compare March 14, 2024 10:02
lnwallet/wallet.go Outdated Show resolved Hide resolved
Copy link
Collaborator

@ProofOfKeags ProofOfKeags left a comment

Choose a reason for hiding this comment

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

This seems to me to be a layer violation. I could be wrong here and would love others to weigh in but the way I see it is that lnwallet sits below both the sweeper and the channel open facility. As such, we should deal with this elsewhere. We should have the sweeper and other various subsystems to enumerate the utxos that it is responsible for creating and whether or not they are stable. We can assume that if they are unconfirmed that they are unstable.

From here, the OpenChannel/AcceptChannel code should ask the lnwallet to list out the outputs it is aware of, and then perform a set difference, removing the outputs that the sweeper (or other systems) says are currently unstable.

@ziggie1984
Copy link
Collaborator Author

ziggie1984 commented Mar 16, 2024

From here, the OpenChannel/AcceptChannel code should ask the lnwallet to list out the outputs it is aware of, and then perform a set difference, removing the outputs that the sweeper (or other systems) says are currently unstable.

Interesting idea, so the point is, that we do the coin-selection (checking if we have enough funds for the channel) in the lnwallet package CoinSelectUpToAmount, so if we would check the stable inputs somewhere in the OpenChannel code, we would fail the opening as soon as a unstable input would be part of the selection. So I think it makes sense to integrate the check somewhere where we allocate the funds to the channel opening ProvisionChannel, wdyt ?

Happy to discuss other ways to redesign it, will also think about alternatives.

@saubyk saubyk requested review from ellemouton and removed request for bhandras March 19, 2024 16:34
@ProofOfKeags
Copy link
Collaborator

Interesting idea, so the point is, that we do the coin-selection (checking if we have enough funds for the channel) in the lnwallet package CoinSelectUpToAmount

I'll admit I'm not super familiar with the code that implements the funding manager. We probably can't do coin select "up to amount" prior to this filter so maybe we would need to accept a filter function like this Utxo -> bool and construct that function based off of the other subsystems that enumerate unstable UTXOs. There are many ways to go about this but the main thing I want to highlight is that lnwallet should be oblivious to the sweeper imo.

CC @Roasbeef @yyforyongyu for their opinions here.

@ziggie1984
Copy link
Collaborator Author

Thanks to your valuable feedback @ProofOfKeags, so I agree with you and will diverge from this approach.

Instead of filtering for the label lets just filter the wallet transaction for RBF signaling. Although current bitcoind implementations disregard it and will still allow RBFs for non signaling transactions (full-rbf) we can still use this signaling to decide whether we consider this utxo safe to use for further transactions ?

Will work on the new design and show a draft soonish.

@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from 4330027 to d424906 Compare April 4, 2024 10:39
@ziggie1984
Copy link
Collaborator Author

Last push only update of the latest btcwallet lib.

@guggero guggero closed this Apr 4, 2024
@ellemouton ellemouton reopened this Apr 4, 2024
@guggero
Copy link
Collaborator

guggero commented Apr 4, 2024

Sorry for the accidental close. GitHub tried to be smart, the PR btcsuite/btcwallet#919 has the word "fix" in front of this PR's link...

Copy link
Collaborator

@ellemouton ellemouton left a comment

Choose a reason for hiding this comment

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

Just some quick questions 🙏

for _, utxo := range utxos {
// If there is a filter function supplied all utxos not adhering
// to these conditions will be discared.
if c.allowUtxo != nil && !c.allowUtxo(*utxo) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why not also just add a WithUtxoFilter option to ListUnspentWitnessFromDefaultAccount in btcwallet? just wondering if we could do the filtering in a single place instead

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes agree we might consider doing this. I liked doing it way higher up the design because I realized I would need to funnel the argument into every function call, so because I started with the single funding flow I was happy to introduce the change at a higher level. Only later I found out that the psbt part can only be done by funneling the argument all the way down to the btcwallet lib. Maybe you are right having the filtering all in one place might be more cleaner. I open to rework it. Keep in mind that the filter logic will live in two different functions tho in the btcwallet lib. (findEligibleOutputs and ListUnspent). The latter is also exported so it might cause a bigger API change. Wdyt ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The psbt case had already options in the call CreateSimpleTx so it was easy to introduce.

//
// NOTE: This is very useful when opening channels with unconfirmed
// inputs to make sure stable non-replaceable inputs are used.
AllowUtxoForFunding func(Utxo) bool
Copy link
Collaborator

Choose a reason for hiding this comment

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

hmm ok one style thing that stands out to me here is that we are making this a request specific field but it is not something that changes per request. So why not instead have this on the main lnwallet.Config? Then it is just defined once and can be re-used over and over again per channel funding request.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ie, to me, anything in InitFundingReserveMsg should be specific to that request

Copy link
Collaborator

Choose a reason for hiding this comment

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

if we wanna make things way more generic (so that this is a request specific thing) then how about making the field on InitFundingReserveMsg something like UtxoFilter func(utxo) bool and then pass that straight as a functional option to btcwallet.

That way this does make sense on a per-request level here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

i know there was potentially already some off-line discussion about this between other reviewers & the author - so apologies if this has already been covered - just want to make sure I understand the decision properly

Copy link
Collaborator

Choose a reason for hiding this comment

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

ok upon further inspection, I see that that would quite a bit of refactor since the lnwallet.Config gets create way before the sweeper is created. So perhaps not worth the effort to change this 👍

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 agree your proposal seems definitely better design wise, but I don't think it's worth the effort going down this route.

go.mod Outdated Show resolved Hide resolved
@@ -1417,21 +1418,80 @@ func (w *WalletKit) fundPsbtInternalWallet(account string,
return err
}

// filterFn makes sure utxos which are unconfirmed and
// still used by the sweeper are not used.
filterFn := func(u *lnwallet.Utxo) bool {
Copy link
Collaborator

Choose a reason for hiding this comment

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

same question as prev commit - could we not expand ListUnspentWitness to take the UtxoFilter functional option?

@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from d424906 to 3573bab Compare April 4, 2024 17:37
@Roasbeef
Copy link
Member

Roasbeef commented Apr 4, 2024

I think we should pause on merging this until the sweeper series is in. There'll be quite a lot of conflicts within the itests, and given all the work put into that series so far, I think we want to minimize extra work created for the OP.

@saubyk saubyk requested a review from ellemouton April 11, 2024 15:20
@lightninglabs-deploy
Copy link

@ellemouton: review reminder
@ziggie1984, remember to re-request review from reviewers when ready

Copy link
Collaborator

@ellemouton ellemouton left a comment

Choose a reason for hiding this comment

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

LGTM!

itest/lnd_funding_test.go Show resolved Hide resolved
@ellemouton
Copy link
Collaborator

Just needs a rebase 🙏

@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from 3573bab to 558d7ee Compare April 22, 2024 19:50
@ProofOfKeags
Copy link
Collaborator

Looks like a couple of the unit tests are failing. Afaict they seem unrelated, do we have flakes again?

docs/release-notes/release-notes-0.18.0.md Outdated Show resolved Hide resolved
lnwallet/wallet.go Outdated Show resolved Hide resolved
itest/lnd_funding_test.go Outdated Show resolved Hide resolved
// the restictions of unstable utxos.
// We create the unconfirmed sweeper originating utxo just like before
// by force-closing a channel from dave's side.
ht.CloseChannelAssertPending(dave, chanPoint3, true)
Copy link
Collaborator

Choose a reason for hiding this comment

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

just FYI we can easily create an unconfirmed utxo using BumpFee to avoid force closing channels now - sth like calling BumpFee with a node's wallet utxo and using Immediate: true.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Using the BumpFee RPC, is more involved then just FCing the Channel here which immediately creates the sweep-output. To use the BumpFee RPC we need an unconfirmed transaction in the first place.

itest/lnd_funding_test.go Show resolved Hide resolved
// Fund Carol's wallet with an unconfirmed utxo.
ht.FundCoinsUnconfirmed(fundingAmt, carol)

ht.AssertNumUTXOsUnconfirmed(carol, 1)
Copy link
Collaborator

Choose a reason for hiding this comment

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

again think the test can be simplified by using the BumpFee - we then no longer need to create FC to generate a sweeper-used utxo and can exit the test earlier.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

see comment above, because we are opening channels anyway in this test to prove that one can open channels with unconfirmed utxos, we can just FC the channel and immediately have a sweeper related utxo for further testing.

itest/lnd_psbt_test.go Show resolved Hide resolved
itest/lnd_funding_test.go Outdated Show resolved Hide resolved
lnwallet/wallet.go Show resolved Hide resolved
AliasManager: s.aliasMgr,
DeleteAliasEdge: deleteAliasEdge,
AliasManager: s.aliasMgr,
IsSweeperOutpoint: s.sweeper.IsSweeperOutpoint,
Copy link
Collaborator

Choose a reason for hiding this comment

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

not a big fan of passing func as config params but I guess the alternative would require a larger change.

@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from 558d7ee to bb7b108 Compare April 23, 2024 09:44
@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from bb7b108 to 8c44c67 Compare April 23, 2024 14:41
@yyforyongyu
Copy link
Collaborator

itest failed 😢

@ziggie1984
Copy link
Collaborator Author

Looking into it.

@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from 8c44c67 to a14f48e Compare April 23, 2024 16:59
Copy link
Collaborator

@yyforyongyu yyforyongyu left a comment

Choose a reason for hiding this comment

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

LGTM🧹

lnrpc/walletrpc/walletkit_server.go Outdated Show resolved Hide resolved
lnrpc/walletrpc/walletkit_server.go Outdated Show resolved Hide resolved
Restrict the utxo selection when opening a single internal wallet
funded backed channel.
Add utxo restrictions for psbt internal wallet funded lightning
channels. This also includes batchopening channels backed by the
internal wallet.
Allow unconfirmed inputs to be used when funding a channel via
the psbt channel opening flow. We do now check for unstable utxos.
Itests were added to the normal channel funding flow and the psbt
funding flow using unstable (unconfirmed sweeper inputs).
@ziggie1984 ziggie1984 force-pushed the dont-use-sweeper-unconfirmed-utxos branch from a14f48e to 58e1288 Compare April 24, 2024 12:58
@guggero guggero merged commit acc5951 into lightningnetwork:master Apr 24, 2024
24 of 27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
funding Related to the opening of new channels with funding transactions on the blockchain utxo sweeping
Projects
Status: Done
10 participants