Skip to content

staticaddr: surface mempool deposits immediately#1104

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

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

Conversation

@hieblmi
Copy link
Collaborator

@hieblmi hieblmi commented Mar 24, 2026

This PR updates static-address deposit handling so deposits become visible and
usable as soon as they are detected in the wallet, instead of waiting for the
historical confirmed-only threshold.

What changed

  • mark new static-address deposits as Deposited immediately on detection
  • track unconfirmed deposits with ConfirmationHeight=0
  • backfill the first confirmation height later once the deposit confirms
  • treat unconfirmed deposits as not yet expired because their CSV has not
    started
  • allow static loop-in deposit selection to consider unconfirmed deposits
  • keep cooperative withdrawal and channel-open flows rejecting unconfirmed
    deposits

hieblmi added 8 commits March 24, 2026 17:31
Replace the blocking RegisterConfirmationsNtfn-based getBlockHeight with
a lightweight confirmationHeightForUtxo that derives the first
confirmation height from the wallet UTXO confirmation count and the
currently tracked block height. This removes the MinConfs gating from
reconcileDeposits so that mempool deposits are detected immediately with
ConfirmationHeight=0.

Add updateDepositConfirmations to backfill confirmation heights once
previously-unconfirmed deposits get mined. The manager now stores the
current block height via an atomic and reconciles deposits on every new
block.
Unconfirmed deposits (ConfirmationHeight <= 0) cannot have started their
CSV timer, so IsExpired now returns false for them. Update the Deposited
state and OnStart event documentation to reflect that deposits are
detected from the mempool rather than after reaching a confirmation
threshold.
Remove the MinConfs-based bifurcation from ListUnspentDeposits. All
wallet UTXOs are now checked against the deposit store: known deposits
in the Deposited state are available, unknown outpoints are new deposits
and also available, and all other known states are filtered out.

The mock deposit store now returns ErrDepositNotFound for missing
outpoints to match the real store behavior, and tests are updated to
verify availability by deposit state rather than confirmation depth.
Extract depositBlocksUntilExpiry helper that returns 0 for unconfirmed
deposits (ConfirmationHeight <= 0) since their CSV has not started. Use
it in ListStaticAddressSwaps and populateBlocksUntilExpiry.

In GetStaticAddressSummary, derive the unconfirmed value from deposits
in the Deposited state with no confirmation height instead of issuing a
separate wallet ListUnspent call.
Unconfirmed deposits (ConfirmationHeight == 0) are considered swappable
because their CSV timeout has not started yet. Extract
blocksUntilDepositExpiry helper that returns MaxUint32 for unconfirmed
deposits and use it in SelectDeposits sorting and IsSwappable.
Now that Deposited includes mempool outputs, channel opens and
withdrawals must explicitly reject unconfirmed deposits
(ConfirmationHeight <= 0) since both operations require confirmed
inputs.
Update the loop-in CLI error message to no longer reference a minimum
confirmation count now that mempool deposits are surfaced immediately.
Remove the unused MinConfs constant from the deposit package.
Unconfirmed deposits still have the full CSV window ahead of them, so
depositBlocksUntilExpiry should return the full expiry value rather than
0, which would misleadingly suggest the deposit is about to expire.
@hieblmi hieblmi self-assigned this Mar 24, 2026
@gemini-code-assist
Copy link

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

@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)

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.

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.

1 participant