Skip to content

staticaddr: surface mempool deposits immediately#1104

Open
hieblmi wants to merge 10 commits intolightninglabs:masterfrom
hieblmi:dyn-conf-tracker
Open

staticaddr: surface mempool deposits immediately#1104
hieblmi wants to merge 10 commits intolightninglabs:masterfrom
hieblmi:dyn-conf-tracker

Conversation

@hieblmi
Copy link
Copy Markdown
Collaborator

@hieblmi hieblmi commented Mar 24, 2026

This PR does the following:

  • It changes static-address deposit handling so deposits are tracked as soon as they appear in the mempool, not only after they confirm.
  • It exposes those unconfirmed deposits through the static-address RPC/CLI flows, including summary totals and expiry-related metadata.
  • It allows static loop-ins to consider unconfirmed deposits, while still preferring confirmed deposits first during auto-selection.
  • It adds clearer user messaging for low-confirmation deposits, warning that swap execution may be delayed by the server’s confirmation-risk policy.
  • It keeps the safety boundary for other spend paths: withdrawals and static-address channel opens still require confirmed deposits.
  • It makes withdraw --all stricter so it fails instead of silently skipping unconfirmed deposits.
  • It preserves deposit identity across RBF/replacement scenarios, so a logical deposit can survive an outpoint change without losing associated loop-in state.
  • It hides replaced/vanished deposits from normal listings while still retaining them internally as historical records.
  • It hardens loop-in lifecycle handling by canceling orphan invoices on early failures and by aborting cleanly if selected deposits are replaced before payment
    settles.
  • It improves recovery/cleanup behavior around deposit finalization and restart handling, reducing cases where state can get stuck or become inconsistent.
  • It adds substantial test coverage around confirmation tracking, reconciliation, rebinding, loop-in selection, RPC behavior, and CLI warnings.

@hieblmi hieblmi self-assigned this Mar 24, 2026
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the user experience for static-address deposits by making them available for certain operations, specifically loop-ins, as soon as they are detected in the mempool. This change reduces the waiting time for users by removing the previous requirement for a minimum number of confirmations before a deposit could be utilized. The underlying logic has been updated to correctly track and manage the state and expiry of these newly visible unconfirmed deposits, while ensuring that more sensitive operations like withdrawals and channel opens still adhere to confirmation requirements.

Highlights

  • Immediate Deposit Visibility: Static-address deposits are now marked as 'Deposited' and become visible immediately upon detection in the wallet, rather than waiting for a minimum confirmation threshold.
  • Unconfirmed Deposit Tracking: The system now tracks unconfirmed deposits with a ConfirmationHeight of 0, and their first confirmation height is backfilled once the transaction confirms on the blockchain.
  • Expiry Logic for Unconfirmed Deposits: Unconfirmed deposits are treated as not yet expired, as their CSV (CheckSequenceVerify) timeout has not yet begun.
  • Loop-in Selection Enhancement: The static loop-in deposit selection process has been updated to consider and allow the use of unconfirmed deposits.
  • Confirmation Requirement for Other Flows: Cooperative withdrawal and channel-open flows continue to reject unconfirmed deposits, maintaining the requirement for confirmed funds for these operations.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a 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 refactors the static address deposit management by decoupling the 'Deposited' state from a minimum confirmation count. Deposits are now considered 'Deposited' as soon as they are detected, even if unconfirmed, and their actual confirmation height is tracked. This change impacts how unspent deposits are listed, how expiry is calculated (introducing depositBlocksUntilExpiry and confirmationHeightForUtxo helpers), and how IsExpired and IsSwappable functions behave for unconfirmed deposits. While unconfirmed deposits are now available for loop-ins, explicit checks have been added to openchannel and withdraw managers to ensure only confirmed deposits are used for these operations. The deposit.Manager now updates currentHeight and reconciles deposits on every new block, making the system more responsive. A review comment suggests that the pollDeposits function might be redundant given that reconcileDeposits is now called on every new block, proposing its removal for efficiency and logic simplification.

case height := <-newBlockChan:
m.currentHeight.Store(uint32(height))

err := m.reconcileDeposits(ctx)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Now that reconcileDeposits is called on every new block, the periodic polling started by pollDeposits seems redundant. Reconciling on new blocks is more efficient and responsive than polling on a fixed interval.

Consider removing the pollDeposits function and its call on line 127 to avoid unnecessary work and simplify the logic.

@hieblmi hieblmi force-pushed the dyn-conf-tracker branch 2 times, most recently from 43803c4 to 77cfd21 Compare March 25, 2026 10:34
@hieblmi hieblmi force-pushed the dyn-conf-tracker branch 3 times, most recently from 38c90ee to f61d02f Compare April 10, 2026 12:19
@lightninglabs-deploy
Copy link
Copy Markdown

@hieblmi, remember to re-request review from reviewers when ready

@hieblmi hieblmi force-pushed the dyn-conf-tracker branch 3 times, most recently from b4fe625 to 5bba57d Compare April 15, 2026 14:08
@hieblmi hieblmi requested review from bhandras and starius April 15, 2026 14:33
Comment thread staticaddr/deposit/manager.go Outdated
Comment thread staticaddr/loopin/manager.go
Comment thread staticaddr/loopin/manager.go
@hieblmi hieblmi force-pushed the dyn-conf-tracker branch 2 times, most recently from 14d52be to 6babc2d Compare April 16, 2026 09:40
@hieblmi hieblmi requested a review from starius April 16, 2026 12:32
@hieblmi hieblmi force-pushed the dyn-conf-tracker branch 7 times, most recently from a69f04c to 7c9ab14 Compare April 23, 2026 11:38
hieblmi added 3 commits April 23, 2026 13:58
Surface static-address deposits as soon as they appear in the wallet, without waiting for six confirmations.

Reconcile the wallet view on startup, on each block, and on the polling ticker so mempool deposits are created immediately. Backfill the first confirmation height once those deposits confirm, guard unconfirmed deposits against expiry, and mark vanished unconfirmed outpoints as Replaced so RBFed-away deposits stop showing up in RPCs.
Switch ListUnspentDeposits to derive availability from stored deposit state instead of a MinConfs split. Treat wallet UTXOs that are unknown to the store as new deposits, and only keep known deposits that are still in the Deposited state.

Also update the static-address RPC responses to report sensible expiry data for unconfirmed deposits, derive summary totals from stored deposit state, and hide Replaced records from normal deposit listings and totals.
Treat deposits with ConfirmationHeight=0 as swappable because their CSV timeout has not started yet.

When auto-selecting deposits, still prefer confirmed outputs first so the server can accept them immediately, and only use blocks-until-expiry as a tie-breaker inside the confirmed and unconfirmed groups.
hieblmi added 5 commits April 23, 2026 13:58
Once Deposited includes mempool outputs, the channel-open and withdrawal flows must explicitly require confirmed inputs.

Filter unconfirmed deposits out of automatic selection and fail manual requests that reference mempool deposits so we do not build PSBTs or withdrawal attempts with unusable inputs.
Remove the old "no confirmed deposits available" error now that mempool deposits are listed immediately.

Add a conservative warning when the selected deposits have fewer than six confirmations so the user knows the swap payment may wait for the server's dynamic confirmation-risk policy.
If InitHtlcAction creates the private swap invoice but fails before the loop-in is stored, the retry path otherwise leaves behind a live orphan invoice.

Cancel that invoice on the early error path with a detached, timeout-limited context, and reuse the same helper when tearing down the monitor path.
FinalizeDepositAction only needs to tell the manager to remove the FSM from its active set, but the old synchronous send was still tied to the caller context and could race with request cancellation or a busy manager loop.

Send the cleanup notification asynchronously and tie it to the FSM lifetime instead, so withdrawal completion does not block while deposit locks are held.
Do not silently drop unconfirmed deposited outputs when the caller requests an all-deposit withdrawal. Fail the request instead so the RPC and CLI semantics stay aligned with the documented meaning of all.

Add helper coverage for both the rejecting and all-confirmed cases.
hieblmi added 2 commits April 23, 2026 14:16
When an unconfirmed static-address deposit was replaced, the client reconciler only knew how to mark the original outpoint gone and discover the descendant as a brand-new deposit. That split the logical deposit identity across two records: the old deposit, active FSM and pending loop-in still pointed at the dead outpoint while the replacement surfaced as unrelated new funds.

Teach the deposit manager to rebind uniquely matched unconfirmed replacements in place, carrying the deposit ID, state and active FSM forward to the new outpoint. This keeps looping-in deposits attached to the replacement chain instead of leaving them stranded on the vanished outpoint. Keep the existing vanished-deposit invalidation path for cases that cannot be matched safely.

Also reload static loop-ins from the current deposit rows rather than the stale outpoint snapshot stored at swap creation time, and add targeted tests for replacement rebinding and recovered outpoint loading.
Reproduce the server's static-address deposit selection order in the CLI using the already-returned deposit metadata. This keeps the low-confirmation warning focused on the deposits that auto-selection would actually choose.

Add coverage for the confirmed-preferred and unconfirmed-needed cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants