spawn-lnd
spawn-lnd is a Rust library for spawning Docker-backed Bitcoin Core and LND
regtest nodes for integration tests.
The crate is library-first. It owns Docker lifecycle, daemon startup, wallet
initialization, credential extraction, and readiness checks, then returns
connection data that works with lnd_grpc_rust.
Installation
Add the library to your crate as a dev-dependency:
Most integration tests also need Tokio:
connect_nodes() returns raw lnd_grpc_rust clients, so you can call LND RPC
methods through those clients. Add lnd_grpc_rust as a dev-dependency only if
your test code needs to name generated protobuf types directly, such as
lnrpc::GetInfoRequest, routerrpc::SendPaymentRequest, or invoice/payment
response enums.
Default Images
- Bitcoin Core:
lightninglabs/bitcoin-core:30 - LND:
lightninglabs/lnd:v0.20.1-beta
Example
use SpawnLnd;
async
Tests
Docker-backed tests require a local Docker Engine that can pull:
lightninglabs/bitcoin-core:30lightninglabs/lnd:v0.20.1-betahello-world:latest
Run normal unit and gated smoke tests without Docker:
Run Docker-backed smoke tests:
RUN_DOCKER_TESTS=1
RUN_DOCKER_TESTS=1
RUN_DOCKER_TESTS=1
RUN_DOCKER_TESTS=1
RUN_DOCKER_TESTS=1
RUN_DOCKER_TESTS=1
RUN_DOCKER_TESTS=1
RUN_DOCKER_TESTS=1
Check for leftover managed Docker resources:
Remove all managed containers and networks:
Keep containers for debugging failed tests:
SPAWN_LND_KEEP_CONTAINERS=1 RUN_DOCKER_TESTS=1
Startup failures include a bounded Docker log tail in the typed error when a container was created before readiness failed.
Lifecycle Control
Clusters expose stop, start, and restart helpers for existing containers:
cluster.stop_lnd.await?;
cluster.start_lnd.await?;
cluster.restart_lnd.await?;
cluster.stop_bitcoind.await?;
cluster.start_bitcoind.await?;
cluster.restart_bitcoind.await?;
These APIs preserve container filesystem state. They do not remove or recreate nodes, so LND identity/wallet material and Bitcoin Core regtest data remain in the existing containers.
Configuration
The builder supports node aliases, image overrides, chain grouping, debug cleanup behavior, startup retry policy, and an optional managed Docker network subnet:
use ;
let config = builder
.nodes
.cluster_subnet
.startup_retry_policy
.build?;
By default, spawn-lnd chooses an explicit private subnet for each managed
cluster network, retrying alternatives if Docker reports an overlap. It then
assigns stable container IPs inside that network so Bitcoin Core and LND keep
the same bridge addresses across container restarts.
Environment overrides:
SPAWN_LND_BITCOIND_IMAGESPAWN_LND_LND_IMAGESPAWN_LND_NODES_PER_BITCOINDSPAWN_LND_KEEP_CONTAINERSSPAWN_LND_STARTUP_RETRY_ATTEMPTSSPAWN_LND_STARTUP_RETRY_INTERVAL_MSSPAWN_LND_CLUSTER_SUBNET
Startup Flags
Bitcoin Core uses compose-style regtest flags:
-regtest-printtoconsole-rpcbind=0.0.0.0-rpcallowip=0.0.0.0/0-fallbackfee=0.00001-server-txindex-blockfilterindex-coinstatsindex-rpcuser=<generated>-rpcpassword=<generated>
LND uses:
--bitcoin.regtest--bitcoin.node=bitcoind--bitcoind.rpcpolling--bitcoind.rpchost=<bitcoind-bridge-ip>:18443--bitcoind.rpcuser=<generated>--bitcoind.rpcpass=<generated>--accept-keysend--allow-circular-route--debuglevel=info--noseedbackup--listen=0.0.0.0:9735--rpclisten=0.0.0.0:10009