loopd: raise minimum lnd version to v0.18.4-beta

LoopMinRequiredLndVersion was 0.17.0, a value that only ever tracked the
go.mod lnd dependency rounded down and was never updated as the client
started depending on newer lnd RPC APIs. The client today uses RPC
fields that do not exist in 0.17.0:

  - routerrpc.SendPaymentRequest.first_hop_custom_records and
    lnrpc.Route.custom_channel_data, used by asset loop outs in
    loopout.go: both added in lnd v0.18.4-beta.
  - walletrpc.EstimateFeeResponse.min_relay_fee_sat_per_kw, read by the
    sweep batcher fee floor via lndclient WalletKit.MinRelayFee
    (sweepbatcher/, loopd/sweep_htlc.go): added in lnd v0.18.3-beta. On
    older lnd it silently decodes to 0, disabling the min-relay floor.

Raise the floor to the highest of these (v0.18.4-beta) so loopd fails
fast at startup rather than misbehaving at runtime, and document in
AGENTS.md the rule to keep this value pinned to the lnd APIs the client
actually uses instead of tracking go.mod.
This commit is contained in:
Boris Nagaev 2026-06-16 01:00:49 -05:00
parent 950b5f1772
commit 914a3eeced
No known key found for this signature in database
2 changed files with 37 additions and 2 deletions

View file

@ -51,3 +51,24 @@ The project is a client daemon (`loopd`) that connects to a user's `lnd` node an
* **Cryptography:** Extensively uses Taproot and MuSig2 for efficiency, privacy, and complex spending conditions, especially in the `instantout` and `staticaddr` features.
* **Labeling (`labels/`):** A utility to create and validate labels for swaps, which helps distinguish between user-initiated and automated swaps (e.g., `[reserved]: autoloop-out`).
* **Assets (`assets/`):** Contains logic for interacting with `tapd` (Taproot Assets Protocol Daemon), allowing Loop to facilitate swaps involving assets other than Bitcoin.
**5. Minimum `lnd` Version (`loopd/run.go`):**
`loopd` enforces a minimum `lnd` version at startup through
`LoopMinRequiredLndVersion` in `loopd/run.go` (handed to `lndclient` as
`CheckVersion`). This is a hard gate: loopd refuses to start against an older
`lnd` node.
**Maintenance rule:** whenever you start using an `lnd` gRPC method or message
field that does not exist in older `lnd`, bump `LoopMinRequiredLndVersion` to the
`lnd` release that introduced that API, and record which API drove the bump in the
comment above the variable. Pin it to the *real* floor of the APIs the client uses
— do **not** just track the `go.mod` dependency. Historically this value only
tracked `go.mod` and drifted out of sync with the APIs actually called (it sat at
0.17.0 while the client already depended on 0.18.4 APIs). To find the introducing
release, grep the field/method across `lnd` version tags, e.g.
`git grep <field> <tag> -- <proto-file>`. As of the current floor (**v0.18.4-beta**)
the binding dependencies are the asset loop-out fields
`routerrpc.SendPaymentRequest.first_hop_custom_records` and
`lnrpc.Route.custom_channel_data` (lnd v0.18.4-beta), plus the sweep-batcher fee
floor `walletrpc.EstimateFeeResponse.min_relay_fee_sat_per_kw` (lnd v0.18.3-beta).

View file

@ -24,10 +24,24 @@ var (
// LoopMinRequiredLndVersion is the minimum required version of lnd that
// is compatible with the current version of the loop client. Also all
// listed build tags/subservers need to be enabled.
//
// IMPORTANT: bump this whenever the client starts using an lnd RPC
// method or message field that does not exist in older lnd, to the lnd
// release that introduced that API (see the maintenance note in
// AGENTS.md). The current floor of v0.18.4-beta is set by the highest
// such dependency the client has today:
// - routerrpc.SendPaymentRequest.first_hop_custom_records and
// lnrpc.Route.custom_channel_data, used by asset loop outs
// (loopout.go): both added in lnd v0.18.4-beta.
// - walletrpc.EstimateFeeResponse.min_relay_fee_sat_per_kw, read by
// the sweep batcher fee floor via lndclient WalletKit.MinRelayFee
// (sweepbatcher/, loopd/sweep_htlc.go): added in lnd v0.18.3-beta.
// On older lnd this field silently decodes to 0, disabling the
// sweeper's min-relay fee floor.
LoopMinRequiredLndVersion = &verrpc.Version{
AppMajor: 0,
AppMinor: 17,
AppPatch: 0,
AppMinor: 18,
AppPatch: 4,
BuildTags: []string{
"signrpc", "walletrpc", "chainrpc", "invoicesrpc",
},