Commit graph

2390 commits

Author SHA1 Message Date
Slyghtning
978a2cbe05
cmd/loop: update static loop-in replay flow
Delay the static address summary RPC until after validation and quote fee
checks. This keeps early error paths on their previous gRPC flow.

Add summary RPC events to the static loop-in sessions that reach the
confirmation prompt or swap dispatch, where the CLI needs the expiry
horizon for low-confirmation warnings.
2026-05-22 12:16:29 +02:00
Slyghtning
ec42d48aac
notifications: deduplicate risk fanout
Risk accepted and rejected notifications had nearly identical parsing,
persistence, cache update, and subscriber fanout code. The duplication made it
easy for the two decision paths to drift.

Introduce a shared risk-decision handler that validates the swap hash, persists
the decision, updates the matching cache, clears the opposite cache, and fans
out only to the subscriber for that swap.

Keep risk-decision delivery best-effort for slow subscribers, while queued
delivery remains limited to notification types that must not be dropped. Fold
the queue tests through a common helper so both queued notification paths keep
the same behavior.
2026-05-22 11:22:45 +02:00
Slyghtning
7a137df098
notifications: queue blocking fanout
Some notification types are work requests and must not be dropped when a
subscriber channel is temporarily full. Sending them synchronously from the
global notification handler can stall the stream while a slow subscriber holds
back reads.

Add a per-subscriber queue for blocking notification classes and deliver those
notifications from a worker tied to the subscriber context. Keep direct sends as
the fallback for subscribers that do not need queued delivery.

Use the queued path for static loop-in sweep requests and unfinished swap
notifications, and fix subscriber removal to compare channel identity now that
subscribers contain function fields.
2026-05-22 11:22:45 +02:00
Slyghtning
9fb4a5d606
staticaddr/loopin: persist risk decisions
Store the server's static loop-in confirmation-risk decision and the time it
was received. This lets recovered swaps reconstruct whether payment waiting had
already started and how much of the payment timeout remains.

Wire notification handling to persist accepted and rejected decisions before
caching and forwarding them. If the swap row is not present yet, the
notification is still cached so the per-swap waiter can replay and store the
decision later.

Recover accepted decisions by starting the payment deadline from the persisted
decision time, and recover rejected decisions by canceling the invoice and
failing the swap instead of waiting forever.
2026-05-22 11:22:44 +02:00
Slyghtning
a741aab390
staticaddr/loopin: list failed swaps by state
GetStaticAddressLoopInSwapsByStates passes a comma-separated
state list into a SQL LIKE membership check. The query wraps the
input with commas before matching latest update states as
comma-delimited tokens.

Wrapping that list in braces meant the first and last states
were not bounded by commas, so boundary entries in a state set
could be missed. In particular, Failed is the last final
static-address loop-in state, which made final-state queries skip
failed swaps.

Drop the braces from the serialized state list and extend the
SQL store test with a failed swap so the final-state boundary is
covered.
2026-05-22 11:22:44 +02:00
Slyghtning
e6404bb867
staticaddr/loopin: handle risk rejection notification
Add client handling for the server's static loop-in risk-rejected notification.
If the server aborts confirmation-risk waiting before payment, the client fails
the local swap instead of waiting for a payment deadline that will never start.

Cache rejected notifications by swap hash using the same replay path as accepted
notifications, and clear the opposite cached state when a final risk decision is
received. This keeps reconnect and subscription-order races from stranding the
client in the risk wait.
2026-05-22 11:22:43 +02:00
Slyghtning
aa77682e07
staticaddr/loopin: wait for risk acceptance notification
Wait for the server's static loop-in risk-accepted notification before starting
the client payment deadline. The server may intentionally hold the swap at the
confirmation-risk gate after HTLC signing, and the client deadline should not
run while that server-side wait is still in progress.

Cache risk-accepted notifications by swap hash inside the local notification
manager and replay them to the per-swap subscriber. This covers both reconnects
and the internal race where the global notification stream receives the server
event before the static loop-in FSM registers its waiter.
2026-05-22 11:22:43 +02:00
Slyghtning
a7bff02fd8
staticaddr: harden client deposit readiness
ListUnspentDeposits now reports only wallet UTXOs that have an active Deposited
record. That matches the static loop-in admission path and avoids exposing
wallet-seen outputs that are not ready for loop-in selection.

Make local notification fan-out non-blocking for best-effort categories so a
slow subscriber cannot stall the notification manager while it holds the
subscriber lock. Static loop-in sweep signing requests remain blocking because
they are work requests required for sweepbatcher presigning and must not be
dropped.
2026-05-22 11:22:43 +02:00
Slyghtning
7287da1559
staticaddr: cancel loop-ins when deposit inputs vanish
Keep replacement UTXOs as fresh deposits while preserving the original deposit
record and selected outpoint snapshot for pending swaps.

Before signing a static loop-in HTLC, check each original selected outpoint with
GetTxOut(..., includeMempool=true). Cancel the pending invoice only when that
check reports an original outpoint unavailable; lookup errors fail the action
without canceling so transient chain backend errors do not incorrectly abandon
the swap.

Keep recovered loop-ins using their stored outpoint snapshot and cover
replacement discovery and cancellation in tests.
2026-05-22 11:22:42 +02:00
Slyghtning
ab6dcdfb1f
staticaddr/deposit: async finalization cleanup
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. Withdrawal completion no longer blocks while deposit locks are held
just because the original request context was canceled.
2026-05-22 11:22:42 +02:00
Slyghtning
afb7c80a96
staticaddr/loopin: cancel orphan invoice when init fails early
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. This
keeps failed initialization attempts from leaving invoices that no local swap
can complete.
2026-05-22 11:22:42 +02:00
Slyghtning
e6e48978ef
cmd/loop: warn for auto-selected low-conf deposits
Remove the old "no confirmed deposits available" error now that mempool
deposits are listed immediately and can be selected for static loop-ins.

Reproduce the server static-address deposit selection order in the CLI using
the already-returned deposit metadata. This keeps the low-confirmation warning
focused on the deposits auto-selection would actually choose, so users only see
it when the swap payment may wait for the server confirmation-risk policy.
2026-05-22 11:22:42 +02:00
Slyghtning
3a1429a6a0
staticaddr: apply confirmation policy by flow
Allow static loop-ins to select unconfirmed deposits because their CSV timeout
has not started yet, while still preferring confirmed outputs during automatic
selection.

Keep confirmed-input requirements for channel opens and withdrawals now that
Deposited includes mempool outputs. Filter unconfirmed deposits out of automatic
selection for those flows and fail manual requests that reference them, so the
client does not build PSBTs or withdrawal attempts with unusable inputs.

Treat deposit.MinConfs as the legacy readiness threshold rather than the single
source of truth for all flows. Loop-in readiness is now governed by server
confirmation-risk policy, while withdrawals and channel opens keep their
confirmed-input checks.
2026-05-22 11:22:41 +02:00
Slyghtning
d561b74216
staticaddr/deposit: replay startup block to recovered deposits
The deposit manager consumes one block epoch before recovered deposit FSMs are
started. That left already-expired recovered deposits idle until another block
arrived.

Remember the startup height and deliver it to active deposit FSMs after
recovery and reconciliation have finished. Move the block notification fanout
into a helper so startup replay and normal block handling use the same path.

Add coverage that starts the manager with a recovered deposit at its expiry
height and verifies the expiry sweep is signed and published immediately.
2026-05-22 11:22:41 +02:00
Slyghtning
502d298643
staticaddr: track unconfirmed deposits
Surface static-address deposits as soon as they appear in the wallet instead
of waiting for the old six-confirmation readiness threshold.

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 outputs confirm, protect unconfirmed deposits from expiry,
and mark vanished unconfirmed outpoints as Replaced so RBFed-away deposits stop
showing up in RPCs.

Expose the new state through static-address RPCs by deriving availability and
summary totals from stored deposit state, reporting sensible expiry data for
unconfirmed outputs, and hiding Replaced records from normal listings.
2026-05-22 11:22:41 +02:00
Boris Nagaev
859ba4508e
Merge pull request #1119 from starius/static-autoloop
autoloop: support static loop-ins
2026-05-22 02:50:42 -05:00
Boris Nagaev
83534a283c
cmd/loop: record static autoloop CLI
Add recorded CLI coverage for selecting the static-address autoloop
loop-in source, displaying the resulting parameters, and showing a static
loop-in suggestion. Also record the non-experimental rejection so the
opt-in gate is covered.

Update existing liquidity fixtures with the default loop-in source field
emitted by the newer RPC shape.
2026-05-22 02:32:15 -05:00
Boris Nagaev
7fcc508193
liquidity: gate static autoloop
Static-address loop-ins in autoloop are still experimental. Reject
loop_in_source=static-address at the RPC boundary unless loopd was started
with --experimental, and pass the same opt-in into the liquidity manager so
persisted params cannot bypass the gate after restart.

The existing static swap accounting remains wired through the manager; the
gate only controls accepting and planning new static-address autoloops.
2026-05-22 02:32:15 -05:00
Boris Nagaev
8d6df2bf20
staticaddr: use dp autoloop selector
Replace the recursive full-deposit autoloop selector with a bounded-memory
DP implementation in staticaddr/loopin/autoloop_dp.go. The new selector
keeps the existing no-change semantics, first finds the best reachable
total, then applies the 25 percent band rule so earlier-expiring deposits
can win inside that near-optimal range.

The DP table is capped at 128 MiB and keeps exact satoshi sums alongside
compressed bucket weights, so planning stays memory-bounded without
allowing oversized candidates. The compressed weighting now rounds down
with a minimum of one bucket, which avoids rejecting valid sums after
multiple per-deposit rounding steps while leaving the exact-sum check
as the real safety boundary.
2026-05-22 02:20:36 -05:00
Boris Nagaev
616b0534a6
docs: update (autoloop supports static) 2026-05-22 02:20:36 -05:00
Boris Nagaev
8ea9adbd35
looprpc: map custom channel reason
Static autoloop testing surfaced a SuggestSwaps failure when the
planner disqualified a custom asset channel.

Add the missing AutoReason enum value and handle ReasonCustomChannelData.
2026-05-22 02:20:36 -05:00
Boris Nagaev
58ebb042ff
liquidity: add static autoloop planner
Wire static-address-backed loop-ins into the existing autoloop
planner and dispatch path. Loop-in rules can now be converted into
static candidates, prepared after global sorting, filtered with
static fee limits, and dispatched through the static manager.

This also fixes MaxAutoInFlight enforcement across all suggested
swap types and adds planner tests for missing static candidates
and mixed in-flight filtering.
2026-05-22 02:20:36 -05:00
Boris Nagaev
e467ac932b
looprpc: expose static autoloop output
Extend the public rpc surface for static autoloop integration
without turning the planner on yet. SuggestSwaps responses can
now carry static-address loop-in requests and the new planner
reason for missing static candidates is mapped over rpc.
2026-05-22 02:20:36 -05:00
Boris Nagaev
7cf0a87c2b
liquidity: count static loop-ins
Teach the liquidity manager to include persisted static loop-ins
in budget accounting, in-flight limits, and peer traffic backoff.
This adds the static fee model used for conservative accounting
and passes storage errors through the relevant planner helpers.

The daemon wiring now exposes static loop-ins to liquidity so the
manager can see the same ongoing swaps that the static-address
subsystem persists, while easy autoloop keeps working with the new
fallible traffic lookup path.
2026-05-22 02:20:36 -05:00
Boris Nagaev
94fc04a71a
staticaddr: add autoloop loop-in prep
Add the static-address helper that prepares full-deposit autoloop loop-ins
without dispatching them. The helper selects no-change deposit sets, records
explicit outpoints, and quotes the exact selected amount before the planner
tries to dispatch anything.

The tests cover the full-deposit selector, the quoted request construction,
and excluded outpoint handling so later liquidity work can rely on a stable
preparation surface.
2026-05-22 02:20:36 -05:00
Boris Nagaev
48a7bdc7d0
staticaddr/loopin: makeDeposit gets confheight arg
Test-only change. This is needed to reuse it in another test.
2026-05-22 02:20:36 -05:00
Boris Nagaev
562416e99b
loopd: validate static loop-in labels at rpc
Move static loop-in label validation to the rpc boundary and
remove the same check from the internal manager path.

This keeps external requests aligned with the existing swap rpc
surface while allowing internal autoloop callers to keep using
reserved labels for automated swaps. The tests cover both sides of
that contract: rpc requests still reject reserved labels, and the
manager path accepts them.
2026-05-22 02:20:36 -05:00
Boris Nagaev
ac58336104
looprpc: add autoloop loop-in source
Add a dedicated loop-in source enum to the liquidity parameters
rpc and wire it through the internal parameter model and CLI.

This keeps the source selection explicit before any static
autoloop planning lands, so operators can choose between the
legacy wallet-funded path and a future static-address-backed
path without relying on implicit fallback behavior.
2026-05-22 02:20:36 -05:00
Boris Nagaev
8d5cc2168a
cmd/loop: avoid escaped session text
Disable JSON HTML escaping for recorded session files and for the nested
session payloads rewritten by bless mode. This keeps CLI text such as
"> 1 sat/vByte" readable instead of turning it into "\u003e".

Keep the metadata field order aligned with existing fixtures so a bless
pass does not rewrite unrelated sessions just because the encoder changed.
2026-05-22 02:20:36 -05:00
Slyghtning
72a38c535b
Merge pull request #1133 from 0xfandom/refactor/1056-move-parameters-to-script
staticaddr: move address.Parameters to script package
2026-05-20 22:02:57 +02:00
Boris Nagaev
60d43898f0
Merge pull request #1072 from starius/cli-tests20
cmd/loop: CLI session recording and replay tests
2026-05-20 13:35:37 -05:00
Boris Nagaev
3abede2d8e
cmd/loop: fix openchannel help typo
Correct the duplicated article in the static openchannel
help text so the command summary reads cleanly. Refresh the
recorded help fixtures that surface that summary directly,
including the dedicated openchannel help output and the
parent static command listing.
2026-05-20 03:12:04 -05:00
Boris Nagaev
ca1ce698f0
cmd/loop: bless text-only session updates
Add an env-gated bless mode to recorded-session replay so
CLI-only text changes can refresh fixtures without a live
recording pass. The replay still uses the recorded gRPC
traffic, stdin, and environment, and it only rewrites
stdout, stderr, and run_error after the command preserves
the recorded success or failure shape.

Keep the updater strict by refusing to bless sessions when
replay leaves recorded gRPC events unconsumed, and add
focused tests for the rewrite rules. Document the bless
workflow next to the session fixtures, including the need
for -count=1 so the Go test cache does not skip updates.
2026-05-20 03:12:04 -05:00
Boris Nagaev
e6e3820a76
testdata: add sessions for newly added features 2026-05-20 03:12:04 -05:00
Boris Nagaev
7683da65ff
testdata: add static address and swaps sessions 2026-05-20 03:12:04 -05:00
Boris Nagaev
662f954e0f
testdata: add liquidity sessions 2026-05-20 03:12:03 -05:00
Boris Nagaev
541e0e00fc
testdata: add loop in/out and quote sessions 2026-05-20 03:12:03 -05:00
Boris Nagaev
074257e348
testdata: add instantout and l402 sessions 2026-05-20 03:12:03 -05:00
Boris Nagaev
5157dad741
testdata: add basic swap sessions 2026-05-20 03:12:03 -05:00
Boris Nagaev
9640e3bd4c
cmd/loop: add session recording guide 2026-05-20 03:12:03 -05:00
Boris Nagaev
c3009182b3
cmd/loop: add session replay tests 2026-05-20 03:12:03 -05:00
Boris Nagaev
137097915c
cmd/loop: add session recorder plumbing 2026-05-20 03:12:03 -05:00
Boris Nagaev
c3e102527a
cmd/loop: add session gRPC transport hook 2026-05-20 03:12:03 -05:00
Boris Nagaev
d0591e62b9
cmd/loop: add stdio hooks 2026-05-20 03:12:03 -05:00
Boris Nagaev
cdec0cacef
cmd/loop: add cli clock and hook 2026-05-20 03:12:03 -05:00
Boris Nagaev
3e9a99dd55
cmd/loop: factor newRootCommand 2026-05-20 03:12:03 -05:00
Boris Nagaev
74c7274b03
cmd/loop: add client conn cleanup 2026-05-20 03:12:03 -05:00
Boris Nagaev
3182be8bf1
cmd/loop: remove orphan flag access
abandonSwap used to access flag --id which does not exist.
2026-05-20 03:12:03 -05:00
Boris Nagaev
61945bd9f9
cmd/loop: print homedir in help messages as ~
Make the output homedir-independent to facilitate tests.
2026-05-20 03:12:03 -05:00
Slyghtning
ea03440f29
Merge pull request #1130 from hieblmi/fix-racae
sweepbatcher: harden AddSweep against ctx closure
2026-05-19 07:46:06 +02:00