Skip to content

staticaddr: various fixes#1078

Open
hieblmi wants to merge 19 commits intolightninglabs:masterfrom
hieblmi:static-fixes
Open

staticaddr: various fixes#1078
hieblmi wants to merge 19 commits intolightninglabs:masterfrom
hieblmi:static-fixes

Conversation

@hieblmi
Copy link
Collaborator

@hieblmi hieblmi commented Feb 28, 2026

A small collection of fixes for issues that agents identified.

@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 delivers a collection of minor but important fixes across various components of the staticaddr package. The changes primarily focus on enhancing the robustness, correctness, and error handling of FSM-driven processes, HTLC sweeps, and channel funding operations. By addressing logging inaccuracies, variable scoping, potential data races, and context management during cleanup, the PR improves the overall stability and reliability of the static address functionality.

Highlights

  • Corrected Comment: A comment for the ServerPubkey field in staticaddr/address/interface.go was updated to accurately reflect its purpose.
  • FSM Event Handling Fixes: Addressed logging inconsistencies and variable scoping issues in staticaddr/deposit/manager.go and staticaddr/loopin/manager.go related to Finite State Machine (FSM) event processing during recovery and startup.
  • HTLC Timeout Sweep Robustness: Improved the error handling for HTLC timeout sweeps in staticaddr/loopin/actions.go by properly managing context cancellation and refining the retry mechanism.
  • HTLC Output Value Correction: Fixed an incorrect index used to retrieve the HTLC output value during sweep transaction creation in staticaddr/loopin/loopin.go.
  • Data Race Prevention: Resolved a potential data race in staticaddr/loopin/manager.go by ensuring FSMs are added to the active map before event processing during recovery.
  • Shim Cancellation Context Handling: Ensured proper shim cancellation in staticaddr/openchannel/manager.go by utilizing context.WithoutCancel for FundingStateStep during cleanup, allowing the operation to complete even if the original request context is canceled.
  • Enhanced Error Handling in Withdrawals: Improved error logging and added crucial error checks for chain notifier registrations (spend and confirmation notifications) within staticaddr/withdraw/manager.go.
  • New Test Case for Context Cancellation: A new test case was added in staticaddr/openchannel/manager_test.go to specifically verify the behavior of shim cleanup when the calling context is canceled.

🧠 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.

Changelog
  • staticaddr/address/interface.go
    • Updated comment for ServerPubkey to correctly state it's the server's pubkey.
  • staticaddr/deposit/manager.go
    • Corrected log message from OnStart to OnRecover when an error occurs during OnRecover event sending.
    • Changed err = fsm.SendEvent to err := fsm.SendEvent to correctly scope the err variable in startDepositFsm.
  • staticaddr/loopin/actions.go
    • Removed extra space in log message for HTLC timeout sweep.
    • Changed f.Errorf("%v", ctx.Err()) to return f.HandleError(ctx.Err()) for context cancellation.
    • Moved <-time.After into the select statement, removing the default case.
  • staticaddr/loopin/loopin.go
    • Changed htlcTx.TxOut[0].Value to htlcTx.TxOut[htlcInputIndex].Value to use the correct output index for HTLC value.
  • staticaddr/loopin/manager.go
    • Moved m.activeLoopIns[loopIn.SwapHash] = fsm before go func() to prevent a data race during recovery.
    • Corrected log message from OnStart to OnRecover for error during OnRecover event sending.
    • Changed err = loopInFsm.SendEvent to err := loopInFsm.SendEvent to correctly scope the err variable in startLoopInFsm.
  • staticaddr/openchannel/manager.go
    • Used context.WithoutCancel(ctx) when calling FundingStateStep during shim cancellation to ensure the cleanup operation is not prematurely canceled.
  • staticaddr/openchannel/manager_test.go
    • Added fundingStepCtxErrs slice to mockLndClient to record context errors.
    • Modified FundingStateStep in mockLndClient to record the context error.
    • Updated TestStreamOpenError to assert on fundingStepCtxErrs.
    • Added TestStreamOpenErrorWithCanceledContext to specifically test shim cleanup with a canceled context.
  • staticaddr/withdraw/manager.go
    • Changed error formatting for log.Errorf when retrieving address parameters.
    • Added error check for m.cfg.ChainNotifier.RegisterSpendNtfn.
    • Introduced confErrChan for RegisterConfirmationsNtfn and added an error check for its registration.
    • Updated the select statement to listen on confErrChan.
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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

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 introduces a series of fixes across the staticaddr functionality. The changes include correcting comments and log messages, fixing data races and potential nil pointer dereferences, and adding missing error handling. The logic for handling context cancellation during cleanup has also been improved. Overall, the changes enhance the robustness and correctness of the code. I've found one minor issue with a log message that was not updated along with the code logic.

Copy link
Collaborator

@starius starius left a comment

Choose a reason for hiding this comment

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

LGTM! 🚀
Great work! I left few comments.

@hieblmi hieblmi force-pushed the static-fixes branch 3 times, most recently from cb93650 to b1f944f Compare March 5, 2026 09:01
@hieblmi hieblmi force-pushed the static-fixes branch 4 times, most recently from 601e008 to b6d86f1 Compare March 5, 2026 11:19
@hieblmi hieblmi self-assigned this Mar 5, 2026
@hieblmi
Copy link
Collaborator Author

hieblmi commented Mar 5, 2026

Thanks for your review @starius. Please not that I upgraded the linter version and successively fixed all newly discovered linter issues, see commit: b6d86f1

@hieblmi hieblmi force-pushed the static-fixes branch 6 times, most recently from 93f6cd8 to 1471df6 Compare March 5, 2026 16:06
@hieblmi
Copy link
Collaborator Author

hieblmi commented Mar 6, 2026

@starius Created #1088 to track your suggestion about the Secret type for reading passwords from files.

hieblmi added 4 commits March 6, 2026 11:14
…ex 0

When createHtlcTx produces a transaction with a change output at index
0, createHtlcSweepTx correctly determines htlcInputIndex=1 to identify
the HTLC output, but then unconditionally reads TxOut[0].Value for
htlcOutValue. This uses the change amount instead of the HTLC amount,
producing an incorrect sweep transaction with wrong fee calculation.

Use TxOut[htlcInputIndex].Value so the sweep always references the
correct HTLC output.
SweepHtlcTimeoutAction used a select with a default case containing a
blocking time.After. When the context was canceled, it logged the error
but continued the retry loop instead of returning. The default case
also meant that ctx.Done was only checked when it was already signaled,
while an hour-long sleep blocked without listening for cancellation.

Replace the default+time.After pattern with a proper select on both
ctx.Done and time.After so the function exits promptly on shutdown.
recoverLoopIns wrote to the activeLoopIns map from inside a goroutine
without any synchronization. The map is shared state accessed from
the manager's main Run loop, creating a data race.

Move the map write before the goroutine spawn so it happens
synchronously during recovery. Also fix the stale log message that
said "OnStart" instead of "OnRecover".
handleWithdrawal did not check the error returned by
RegisterSpendNtfn before spawning a goroutine to read from the
notification channels. If registration failed, spentChan would be nil
and the goroutine would block forever on a nil channel read.

Add the missing error check so the function returns early on
registration failure.
hieblmi and others added 11 commits March 6, 2026 11:14
The %w formatting verb is only meaningful for fmt.Errorf where it
enables error wrapping. In log.Errorf it prints as %%!w(error=...),
producing garbled log output. Use %v and add the missing colon
separator.
In manager.go, deferred shim cleanup was calling
FundingStateStep with the original request ctx.
If the user had already canceled that context,
the cleanup RPC would run with a canceled context
and could fail to remove the pending shim. I changed
that cleanup path to use context.WithoutCancel(ctx)
so the cancellation RPC still has a live context.
Remove unused errChan fields from the loopin, openchannel, and withdraw
managers. These channels were declared and initialized but never read
from or written to.

Remove the unused activeLoopIns map from the loopin manager. The map
was only written to but never read, making it dead code.

Remove the stale withdraw.Store interface whose method signatures no
longer match the concrete SqlStore API used by the manager.

Remove unused config fields from openchannel.Config (Server,
AddressManager, ChainNotifier, Signer) and deposit.ManagerConfig
(AddressClient, SwapClient, ChainParams) along with their daemon
wiring. Also remove the now-orphaned openchannel.AddressManager
interface.

Remove the unused GetStaticAddress and Close methods from
address.SqlStore and the GetStaticAddress method from the address.Store
interface, as the codebase only uses GetAllStaticAddresses.
`ReleaseRoutingPlugin` called `Done` with the caller context. In the
loop-out payment flow this cleanup is deferred, so the context may already be
canceled by the time teardown runs.

That can prevent mission-control restoration in `Done`, leaving
plugin-induced routing state behind after a swap exits.

Fix this by detaching cancellation in `ReleaseRoutingPlugin` and passing
`context.WithoutCancel(ctx)` to `Done`, so teardown still executes during
caller cancellation.

Also add a regression test that cancels the caller context before release and
asserts the plugin `Done` call still receives a live context.
The probe monitor goroutine cancelled the probe invoice with the same
monitoring context used by awaitProbe. The caller cancels that context as soon
as swap initiation returns.

If cancellation races with or precedes the invoice-cancel RPC, the cleanup can
be skipped and the probe invoice may remain open longer than intended.

Fix by calling CancelInvoice with context.WithoutCancel(ctx) so cleanup is not
aborted by caller cancellation.

Add a regression test that cancels the parent context between probe success
and invoice cleanup, and verifies CancelInvoice still receives a live context.
Send the batch confirmation after AssertRegisterConf so the batch
exits cleanly, and use a cancellable context so the batcher stops
before leaktest runs.
@hieblmi hieblmi force-pushed the static-fixes branch 3 times, most recently from f88770c to 67bcb25 Compare March 6, 2026 12:28
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.

2 participants