RTL/docker/README.md

183 lines
7.1 KiB
Markdown
Raw Normal View History

Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
# RTL regtest dev fixture
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
### NOT suitable for production. Development only. Every credential here is throwaway.
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
A self-contained regtest network for developing and testing RTL: `bitcoind`, three
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
LND nodes, a Core Lightning node, an Eclair node, and RTL wired to all five.
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
```
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
alice --[ 5,000,000 sat ]--> bob --[ 3,000,000 sat ]--> carol
cln --[ 4,000,000 sat ]--> alice
eclair --[ 3,500,000 sat ]--> bob
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
```
## Topology
```mermaid
flowchart TB
subgraph chain["Chain backend"]
bitcoind["bitcoind (regtest)<br/>RPC · ZMQ rawblock/rawtx · ZMQ hashblock"]
end
subgraph ln["Lightning nodes"]
alice["alice (LND)"]
bob["bob (LND)<br/>forwards payments"]
carol["carol (LND)"]
cln["cln (Core Lightning)"]
eclair["eclair (Eclair)"]
end
alice =="5M sat"==> bob
bob =="3M sat"==> carol
cln =="4M sat"==> alice
eclair =="3.5M sat"==> bob
alice -.-> bitcoind
bob -.-> bitcoind
carol -.-> bitcoind
cln -.-> bitcoind
eclair -.->|"dedicated 'eclair' wallet<br/>+ hashblock ZMQ"| bitcoind
rtl["RTL<br/>localhost:3000"]
rtl -->|"REST + macaroon"| alice
rtl -->|"REST + macaroon"| bob
rtl -->|"REST + macaroon"| carol
rtl -->|"clnrest + rune"| cln
rtl -->|"HTTP API + basic auth"| eclair
```
Thick arrows are channels (opener → peer), dotted arrows the chain backend each node
uses, and solid arrows how RTL reaches each node.
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
bob sits in the middle so it accrues forwarding history, which is what gives RTL's
routing screens something to show. Two nodes would leave them empty. The `cln`
(Core Lightning) node gives RTL's CLN screens a real backend — it talks to RTL over
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
clnrest with rune auth. The `eclair` node does the same for RTL's Eclair screens —
RTL talks to its HTTP API with basic auth.
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
LND, bitcoind and Eclair images come from [Polar](https://lightningpolar.com); the Core
Lightning image is the official [`elementsproject/lightningd`](https://hub.docker.com/r/elementsproject/lightningd).
All are multi-arch (amd64 + arm64) and nothing is built locally, so this works on
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
Apple Silicon. (The official `acinq/eclair` image is amd64-only and its versioned tags
are years stale, which is why Polar's build of the same source is used instead.)
2021-12-29 18:08:41 -05:00
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
## Requirements
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
Docker with Compose v2 (`docker compose`, not `docker-compose`).
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
## Quick start
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
From this directory:
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
```bash
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
docker compose up -d # bitcoind, alice, bob, carol, cln, eclair, rtl
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
./scripts/seed.sh # fund, connect, open channels, make payments
```
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
Then open <http://localhost:3000> — password `rtldev`. All five nodes (alice, bob,
carol, cln, eclair) appear in the node switcher.
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
Tear down, discarding all state:
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
```bash
docker compose down -v
```
2021-12-29 18:08:41 -05:00
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
## What the seed creates
2021-12-29 18:08:41 -05:00
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
| | |
|---|---|
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
| On-chain | 10,000,000 sats per node (LND) + 10,000,000 sats each on cln and eclair, confirmed |
| Channels | alice→bob 5,000,000 · bob→carol 3,000,000 · eclair→bob 3,500,000 sats (1,000,000 pushed each) · cln→alice 4,000,000 sats (no push) |
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
| Routed payments | 5 × alice→carol via bob (10k, 25k, 50k, 75k, 100k sats) |
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
| Direct payments | 2 × alice→bob (5k, 15k sats) · 2 × eclair→bob (8k, 18k sats) |
| Open invoices | 2 unpaid on carol (20k, 40k sats) · 1 unpaid on eclair (30k sats) |
| Personas | alice + bob + cln + eclair OPERATOR, carol MERCHANT |
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
## Determinism
Every amount and payment in `scripts/seed.sh` is fixed. A fresh run always produces
identical state, so screenshots taken before and after a change differ only by the
change. **Do not introduce randomness.**
The seed is deterministic but deliberately *not* idempotent — running it twice would
fund every node again and open a second set of channels. It refuses to run against an
already-seeded network. To start over:
```bash
docker compose down -v && docker compose up -d && ./scripts/seed.sh
2021-12-29 18:08:41 -05:00
```
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
## Helpers
```bash
bin/b-cli getblockcount # bitcoin-cli
bin/b-cli -rpcwallet=rtldev getbalance
bin/ln-cli alice getinfo # lncli, node name required
bin/ln-cli bob listchannels
bin/ln-cli bob fwdinghistory # forwarding history
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
bin/e-cli getinfo # eclair-cli
bin/e-cli channels
docker compose exec cln lightning-cli --network=regtest listpeerchannels # Core Lightning
2021-12-29 18:08:41 -05:00
```
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
Logs:
```bash
docker compose logs -f rtl
docker compose logs alice
2021-12-29 18:08:41 -05:00
```
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
## Notes and gotchas
**RTL's config.** `rtl/RTL-Config.regtest.json` is the tracked template. RTL rewrites
its config on startup, so an init container copies it into a volume rather than
bind-mounting it — a read-only mount makes RTL exit with `EROFS`, and a writable one
would let RTL modify a version-controlled file. The name is not `RTL-Config.json`
because `.gitignore` matches that bare filename at any depth.
**`lncli` needs `--lnddir=/home/lnd/.lnd`.** `docker compose exec` lands as root,
whose HOME is `/root`, but lnd's datadir is `/home/lnd/.lnd`. `bin/ln-cli` handles this.
**Changing bitcoind credentials.** `docker-compose.yml` carries an `-rpcauth` hash for
the `BITCOIN_RPC_USER` / `BITCOIN_RPC_PASSWORD` in `.env`. Changing them there is not
enough; regenerate the hash:
```bash
python3 - <<'EOF'
import hmac, hashlib
user, password, salt = "rtldev", "rtldev", "8a1f2c3d4e5b6a7c8d9e0f1a2b3c4d5e"
print(f"{user}:{salt}${hmac.new(salt.encode(), password.encode(), hashlib.sha256).hexdigest()}")
EOF
2021-12-29 18:08:41 -05:00
```
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
In `docker-compose.yml` the `$` must be written `$$` to escape Compose interpolation.
**Payments right after channel open will fail.** The channel graph has to reach alice
before she can route to carol. The seed waits for this; anything you script yourself
should too.
**Core Lightning auth uses a rune.** RTL talks to `cln` over clnrest and authenticates
with a rune, not a macaroon. `cln/create-rune.sh` — run from the `cln` healthcheck —
creates a master rune once the RPC is up and writes it as `LIGHTNING_RUNE="…"` to
`rtl.rune` in the shared `cln_data` volume; RTL reads it via the `runePath` in its config.
The healthcheck reports unhealthy until that file exists, so RTL (which waits on
`service_healthy`) starts only once the rune is ready. Because it runs on every
healthcheck tick (idempotent), a transient RPC-startup race just retries and self-heals
rather than wedging the stack. `--clnrest-host=0.0.0.0` is required for RTL (another
container) to reach clnrest; the default `127.0.0.1` would only be reachable from inside
the node.
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
**Eclair has no wallet of its own.** It drives a bitcoind wallet over RPC. The
`eclair-wallet-init` service creates a dedicated `eclair` wallet before the node starts;
without it eclair would attach to "the default loaded wallet" — the `rtldev` mining
wallet — and report the miner's balance as its own. RTL authenticates to eclair with
`lnApiPassword` (HTTP basic auth), no file mount needed. Eclair also confirms channels
at 8 blocks (`channel.min-depth-blocks`), not 6 — the seed mines accordingly. And its
`bitcoind.zmqblock` must point at a `zmqpubhashblock` endpoint — wired to the rawblock
one LND uses, eclair never sees new blocks and channels never confirm.
Rebuild the regtest dev fixture: bitcoind + 3 LND nodes + RTL The setup in docker/ has been unable to start since Feb 2021. The boltz service added in f817ae39 references BOLTZ_* variables that are not in .env (so its ports render as ":" and compose rejects the file with "invalid proto"), a ./boltz build context that has never existed in the repo, and boltz_data/boltz_shared volumes that are never declared. Because compose validates the whole project up front, this broke every service: "docker compose up -d bitcoind", the first command in the README, failed too. Rather than repair a five-year-old file pinned to bitcoind 0.19.0 and lnd 0.12.0-beta, this replaces it. What changed: - bitcoind 30.0 and 3x lnd 0.20.0-beta, using Polar's images. They are multi-arch, so nothing is built locally and this works on arm64. The old setup built bitcoind and lnd from local Dockerfiles. - Three nodes, not one: alice -> bob -> carol. bob forwards, so RTL's routing and forwarding screens have data. Two nodes leave them empty. - scripts/seed.sh funds the nodes, opens channels, and makes payments with fixed amounts. A fresh run reproduces identical state, so screenshots taken before and after a change differ only by the change. It is deliberately not idempotent and refuses to run against a seeded network, since re-running would double-fund it. - rtl/RTL-Config.regtest.json configures all three nodes. RTL rewrites its config on startup, so an init container stages a copy into a volume: a read-only bind mount makes RTL exit with EROFS, and a writable one would let RTL modify a tracked file. It is not named RTL-Config.json because .gitignore matches that bare name at any depth. - bin/ln-cli now takes a node name and passes --lnddir=/home/lnd/.lnd, because 'docker compose exec' lands as root while lnd's datadir is under /home/lnd. Both helpers use compose v2. - README rewritten to match. Boltz, Core Lightning and Eclair are left out of this pass. Polar publishes multi-arch clightning and eclair images, so adding them later needs compose services, config entries and seed adapters, but no image building. Verified from a clean 'down -v': all nodes sync, channels go active, 5/5 payments route through bob, bob records 5 forwards, and RTL serves the UI with all three nodes configured. Two independent from-scratch runs produced identical balances. The old bitcoind/ and lnd/ build contexts are now unreferenced but left in place for a follow-up.
2026-07-15 23:09:03 -07:00
## Not included
Add an Eclair node to the regtest docker fixture Completes backend coverage of RTL's three implementations in the docker/ dev fixture: an eclair node (polarlightning/eclair 0.13.1) joins the three LND nodes and the CLN node, wired to RTL over its HTTP API with basic auth, and the seed opens an eclair->bob channel (3.5M sats, 1M pushed), sends two direct payments and leaves one open invoice. Non-obvious plumbing this needed: - polarlightning/eclair instead of acinq/eclair: the official image is amd64-only (useless on Apple Silicon) and its newest versioned tag is years stale; Polar builds the same ACINQ source multi-arch. - Eclair has no on-chain wallet of its own -- it drives a bitcoind wallet. A new eclair-wallet-init container creates a dedicated "eclair" wallet before the node starts; without it eclair attaches to "the default loaded wallet", i.e. the rtldev mining wallet. - bitcoind now also publishes a zmqpubhashblock endpoint (28336): eclair's bitcoind.zmqblock consumes the hashblock topic, not the rawblock one LND uses. Wired to rawblock, eclair never sees new blocks and channels hang in WAIT_FOR_FUNDING_CONFIRMED. - Eclair confirms channels at 8 blocks (channel.min-depth-blocks), not 6, and 'open' returns before the funding tx is broadcast -- the seed waits for the mempool and mines 8 blocks for this channel. Adds a bin/e-cli helper (eclair-cli with the API password), updates the README, and verified end-to-end: seed completes, the channel reaches NORMAL, both payments settle, and RTL's /rtl/api/ecl endpoints return the node, channel and invoice data.
2026-07-18 00:23:08 -07:00
The Boltz swap service.