Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion COMPAT.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ backends**: in-process **Electrum** (confirmed + unconfirmed, libre-relay-class
admission) and optional **Esplora-compatible REST** for the same role (history,
UTXO, broadcast, block/tx fetch by id). Optional **Core-class JSON-RPC subset**
(see [`docs/rpc.md`](./docs/rpc.md)) — not full Core wallet / mining parity.
**Scripthash index (`--shindex`) defaults off**. Electrum/Esplora **start without it**; address/scripthash methods fail closed (`scripthash index disabled`). Txid/outpoint/block/broadcast/fees work. Matrix: [`docs/lightning.md`](./docs/lightning.md).
**Scripthash index (`--shindex`) defaults off**. Electrum/Esplora **start without it**; address/scripthash methods fail closed (`scripthash index disabled`). Txid/outpoint/block/broadcast/fees work. Which wallets use that surface: [`docs/wallets.md`](./docs/wallets.md). Lightning chain sources: [`docs/lightning.md`](./docs/lightning.md).
On/off costs and start/IBD/tip behavior: [`OPERATOR.md`](./OPERATOR.md)
(Scripthash index). Disable later leaves SH files on disk; follow does not
wait on SH materialize.
Expand Down
1 change: 1 addition & 0 deletions OPERATOR.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Start with the task you need to do:
| Try regtest, use the CLI, monitor the node (logs, health probes, metrics), configure relay and P2P | [Node operations](docs/operator/operations.md) |
| Tune store IO and memory, upgrade the schema, manage optional indexes | [Storage and indexes](docs/operator/storage.md) |
| Configure Electrum, Esplora, RPC, SV2 templates, or client benchmarking | [Client interfaces](docs/operator/interfaces.md) |
| Point a wallet or Lightning node at this node | [Wallets](docs/wallets.md), [Lightning backends](docs/lightning.md) |
| Run signet/mainnet, or tune a constrained host or uplink | [Labs and constrained hosts](docs/operator/field-notes.md) |

Product compatibility: [`COMPAT.md`](COMPAT.md). Current on-disk format and
Expand Down
6 changes: 6 additions & 0 deletions changelog.d/wallet-backends.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Added

- **Wallet and Lightning backend guide.** `docs/wallets.md` lists which
wallets speak Electrum, Esplora, or the RPC cookie, including Wasabi's
full-node path. `docs/lightning.md` covers CLN, ldk-node, and LND
`rpcpolling` versus Neutrino and ZMQ.
1 change: 1 addition & 0 deletions docs/ORIENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Before the first edit in a crate, read `crates/<name>/AGENTS.md` when that file
| `rearden-grok[bot]` operator VM (ignore unless that identity) | [`../rearden-vm-HOST.md`](../rearden-vm-HOST.md) |
| Intentional Core / Electrum / Esplora differences | [`../COMPAT.md`](../COMPAT.md) |
| JSON-RPC surface | [`rpc.md`](./rpc.md) |
| Which wallet or Lightning node connects | [`wallets.md`](./wallets.md), [`lightning.md`](./lightning.md) |
| Open, push, or poll a PR | [`../.agents/skills/ship-pr/SKILL.md`](../.agents/skills/ship-pr/SKILL.md) (one worktree; fail-fast `pr-checks-watch.sh`) |
| Minor, patch, or major release | [`../.agents/skills/release/SKILL.md`](../.agents/skills/release/SKILL.md) |
| Core functional harness | [`../.agents/skills/core-functional/SKILL.md`](../.agents/skills/core-functional/SKILL.md) |
Expand Down
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ into `AGENTS.md`.
| [`mempool-fee-estimation.md`](./mempool-fee-estimation.md) | Fee estimator notes. |
| [`errata.md`](./errata.md) | Known one-off store/confirm quirks. Retired confirm dual-path names. |
| [`peer-clients.md`](./peer-clients.md) | Hornet Node and satd: what to steal (tests/ideas) and what not to copy. Ranked items stay here; do not copy into quality.md. |
| [`lightning.md`](./lightning.md) | CLN and LDK as Bitcoin backends: five `bcli` calls, Esplora/Electrum chain sync, `--sh-index` API matrix. Not LND. |
| [`lightning.md`](./lightning.md) | CLN, ldk-node, and LND as Bitcoin backends: `bcli` calls, Esplora/Electrum chain sync, LND `rpcpolling`, `--sh-index` API matrix. |
| [`wallets.md`](./wallets.md) | Which on-chain wallets connect, and the server string or RPC cookie for each. Lightning stays in `lightning.md`. |
| [`external_findings/`](./external_findings/) | Numbered audit reports + regression pointers. Do not flatten into CHANGELOG. |

## Root (stay at root)
Expand Down
102 changes: 92 additions & 10 deletions docs/lightning.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
# Lightning backends (CLN and LDK)
# Lightning backends

How **Core Lightning** and **ldk-node** (LDK) use this node as the Bitcoin
chain source. Not a Core wallet. Not LND (ZMQ / Neutrino). 0.x — do not put
mainnet channel funds here until this file says the contract is boring.
How Core Lightning, ldk-node, and LND use this node as the Bitcoin chain
source. On-chain wallets are [`wallets.md`](./wallets.md). This is not a
Core wallet. 0.x — do not put mainnet channel funds here until this file
says the contract is boring.

Operator flags: [`OPERATOR.md`](../OPERATOR.md). RPC JSON:
[`rpc.md`](./rpc.md). Electrum/Esplora surface: [`COMPAT.md`](../COMPAT.md).
Fee math: [`mempool-fee-estimation.md`](./mempool-fee-estimation.md).
Cookie file for TCP clients: [`wallets.md`](./wallets.md#tcp-rpc-cookie).

## Status (spike 2026-09-20)
## Status

| Client | Path | Today |
|--------|------|--------|
| **CLN** stock `bcli` | `bitcoin-cli` → Core RPC | Methods exist on unix `{datadir}/rpc.sock`. Wrapper: [`scripts/lightning/bitcoin-cli`](../scripts/lightning/bitcoin-cli) (`-datadir=` → `--datadir`). Cookie/TCP `rpcauth` is not the product listen. |
| **CLN** `sauron` | Esplora HTTP | Channel watches use tip, tx, outspend, and broadcast. Point the plugin at `--esplora-listen`. No `--sh-index`. |
| **ldk-node Esplora** | `--esplora-listen` REST | Tip, `/tx/*` (raw/status/outspend/merkleblock-proof), `/fee-estimates`, `POST /tx` work **without** `--sh-index`. Address/scripthash: 503 `scripthash index disabled`. |
| **ldk-node Electrum** | `--electrum-listen` TCP | Headers, `transaction.get` / broadcast, `estimatefee` work **without** `--sh-index`. `blockchain.scripthash.*`: JSON-RPC `scripthash index disabled`. TLS is reverse-proxy only (**Q-63**). |
| **ldk-node bitcoind REST** | `--rpc-listen --rest` `GET /rest/block/` | Block bytes, headers, and hash-by-height. TCP `/rest/` is unauthenticated and off unless `--rest` is set. The BDK wallet still needs Esplora or Electrum with `--sh-index`. |
| **LND** | bitcoind + ZMQ or BIP157 | ZMQ stays out. Optional `--block-filter-index` serves BIP158 basic for sealed heights and advertises `NODE_COMPACT_FILTERS` once filters first reach the tip. |
| **LND** `bitcoind` + `rpcpolling` | TCP JSON-RPC, cookie file | Chain, tx, fee, and broadcast methods exist. ZMQ is not required on this path. Taproot detection falls through to `getdeploymentinfo`, which already lists buried taproot. See [LND](#lnd). |
| **LND** Neutrino | BIP157 to a v2 peer | `--block-filter-index` serves basic filters and advertises `NODE_COMPACT_FILTERS` once they first reach the tip. Neutrino does not speak BIP324. This node is v2-only, so Neutrino cannot connect. |
| **LND** default `bitcoind` | ZMQ `rawblock` + `rawtx` | ZMQ is not served. Use `bitcoind.rpcpolling=true` instead. |
| **Eclair** | Core wallet + ZMQ | Needs a wallet-enabled Core node (`getnewaddress` and the watch-only wallet) plus ZMQ. Both are absent here. |
| **Zeus** embedded LND, Lightning Terminal, Loop, Pool, Faraday, tapd | Whatever LND is using | Same as the LND row they configure. |
| **Phoenix, Breez** | Operator backends | The apps talk to their operators' Electrum and Lightning services. They have no home-node setting. |

`--sh-index` is **not** required to start Electrum/Esplora or for channel
watches (txid / outpoint). SH-only methods fail closed.
Expand Down Expand Up @@ -98,14 +106,88 @@ BDK on-chain wallet still needs `/address/*` and `/scripthash/*` → **`--sh-ind
| `blockchain.estimatefee` | done (10-minute product; `-1` if insufficient) |
| `blockchain.scripthash.*` | done **only with SH** |

## LND

Two chain sources exist in current LND. One can use this node. One cannot.

### `bitcoind` with RPC polling

Set `bitcoind.rpcpolling=true`. LND then learns about blocks and
transactions by polling JSON-RPC. It does not open ZMQ. Authenticate with
`bitcoind.rpccookie` pointed at the file from
[`wallets.md`](./wallets.md#tcp-rpc-cookie). There is no `--rpcuser` /
`--rpcpassword`, and LND will not find ZMQ endpoints in a `bitcoin.conf`
because this node does not write one. Pass the cookie path and
`bitcoind.rpchost=127.0.0.1` explicitly.

```text
bitcoin.node=bitcoind
bitcoind.rpchost=127.0.0.1
bitcoind.rpccookie=/run/rbitcoin/rpc.cookie
bitcoind.rpcpolling=true
```

Start the node with `--rpc-listen` and `--rpc-cookie-file` on that path.
`--sh-index` is not involved. `getrawtransaction` answers from the archive
without a `txindex` flag.

What LND's startup check actually reads (current `chainreg/taproot_check.go`):

1. `getblockchaininfo`. This response has no `softforks` object.
2. Because that map is absent, LND does not treat the call as "no taproot".
It calls `getdeploymentinfo`.
3. `deployments.taproot` is present (buried, same object as
`getdeploymentinfo`). LND treats the key as support. It also accepts
`script_flags` containing `TAPROOT`; we do not emit `script_flags`, and
the deployments key is enough for this check.

`getnetworkinfo.version` is `190000`. LND's health check uses `uptime`
when that integer is at least `150000`, which it is. Raising the integer
toward a current Core release would advertise wallet RPC that this node
does not have. See [`rpc.md`](./rpc.md#getnetworkinfoversion).

`estimatesmartfee` accepts `estimate_mode` `economical` and `conservative`
and returns the same 10-minute feerate either way. `initialblockdownload`
means relay is inhibited (`--min-chain-work` / `--max-tip-age`), not
"headers are still downloading."

This path is read from LND's source and from this node's RPC. It has not
been run as a channel smoke.

### Neutrino

`--block-filter-index` is the server half: BIP158 basic filters, P2P
`getcfilters` / `getcfheaders` / `getcfcheckpt`, and `NODE_COMPACT_FILTERS`
once the filter watermark first reaches the tip. Peers that connected
before that advertisement do not learn the bit; a later connection does.

Neutrino's BIP324 handshake is still upstream work
([lightninglabs/neutrino#319](https://github.com/lightninglabs/neutrino/issues/319)).
Until that client speaks v2, it cannot peer with this node. Serving v1
P2P to make Neutrino connect is out of scope.

### Default ZMQ mode

`bitcoind.zmqpubrawblock` and `bitcoind.zmqpubrawtx` have nothing to
connect to. ZMQ is not a 1.0 surface ([`road-to-1.0.md`](./road-to-1.0.md)).
`rpcpolling` is the configuration that matches the RPC we already serve.

## Eclair

Current Eclair requires Bitcoin Core's wallet RPC and ZMQ
(`zmqpubhashblock`, `zmqpubrawtx`), plus `rpcuser` / `rpcpassword`. The
wallet calls and ZMQ are both absent. An Esplora or Electrum URL is not a
chain backend Eclair reads.

## Gaps this plan still implements

1. Optional `scripts/lightning/run-cln.sh` / `run-ldk.sh` if those binaries exist (skip 0 otherwise).
2. Remaining LDK dialect holes found by those smokes.

## Not this node

Core wallet RPC, ZMQ, LND’s ZMQ chain source, in-binary Electrum TLS,
cookie/`rpcauth` as the LN listen. BIP158 basic filters are optional
(`--block-filter-index`). Core REST block/header/tx routes are on the RPC
listener.
Core wallet RPC, ZMQ, in-binary Electrum TLS, and v1 P2P. BIP158 basic
filters are optional (`--block-filter-index`). Core REST block/header/tx
routes are on the RPC listener when `--rest` is set. TCP JSON-RPC accepts
a cookie file when `--rpc-cookie-file` is set; that is the LND and Wasabi
credential, not `rpcauth`.
5 changes: 5 additions & 0 deletions docs/operator/interfaces.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Client interfaces

Which wallet or Lightning node to point here, and the server string it
expects: [`docs/wallets.md`](../wallets.md) and
[`docs/lightning.md`](../lightning.md). This file is the listener
behavior.

## Electrum

Internet-facing Electrum is supported as a **wallet-client backend** (Electrum,
Expand Down
4 changes: 3 additions & 1 deletion docs/rpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,12 @@ still wait for durable SH when shindex is on.
|-----|-----------------|
| `{datadir}/rpc.sock` (filesystem) | TLS in-process / mTLS |
| `{datadir}/rpc.token` Bearer on TCP | multi-user tokens |
| Harness `.cookie` + Basic on the test proxy only | `rpcallowip` |
| TCP HTTP Basic from `--rpc-cookie-file` (operator-written; the node never creates it). The functional harness still uses its own cookie on the test proxy | `rpcallowip` |

## Related

- [`COMPAT.md`](../COMPAT.md) — product surface
- [`OPERATOR.md`](../OPERATOR.md) — flags and shindex tradeoffs
- [`mempool-fee-estimation.md`](./mempool-fee-estimation.md) — fee product
- [`wallets.md`](./wallets.md) — which wallets use Electrum, Esplora, or this RPC
- [`lightning.md`](./lightning.md) — CLN, LDK, LND chain sources
Loading
Loading