Motivation
rgb-lightning-node currently requires a full bitcoind JSON-RPC connection in addition to an indexer (electrum/esplora). For most operators this is redundant: the indexer is already a complete chain source, and running an extra bitcoind purely to feed LDK doubles the storage footprint, the boot time, and the surface area for "what do I configure".
Removing it lets the node run against any maintained electrum/esplora endpoint (self-hosted, public, or an LSP-managed one), and shrinks the regtest/CI matrix accordingly. It also aligns the node with the deployment posture of most other RGB tooling, which is already indexer-only.
Proposal
Drop the bitcoind requirement entirely and route block + transaction sync through the configured indexer:
- LDK chain source: replace
lightning-block-sync (RPC mode) with lightning-transaction-sync, enabling both electrum and esplora-blocking features so a single binary supports both protocols.
- Fee estimation: poll the indexer (
estimate_fee for electrum, get_fee_estimates for esplora), interpolating across confirmation buckets.
- Transaction broadcast: through the indexer's
transaction_broadcast / esplora POST /tx.
- UTXO lookup for gossip verification: through the indexer (
blockchain.transaction.id_from_pos / esplora block-index lookup), with async resolution so peer-manager isn't blocked.
API / config surface changes
- Removed from
unlock and init payloads (and the OpenAPI spec): bitcoind_rpc_username, bitcoind_rpc_password, bitcoind_rpc_host, bitcoind_rpc_port.
- Unchanged:
indexer_url (already accepts tcp://host:port for electrum or https://host for esplora; auto-detected).
- Dockerfile: drops the
bitcoind service from the runtime image; compose.yaml still ships bitcoind for regtest because we still need a block source for the test stack, just not for the node itself.
- README: regtest and docker examples updated to remove the four bitcoind RPC fields.
Tradeoffs / behavioral notes
- Block-tip latency: previously near-synchronous via bitcoind RPC; now bounded by the chain-sync poll cadence (
tokio::time::sleep(Duration::from_secs(1)) between tx_sync.sync(...) calls). For most workloads this is invisible, but tests that mine N blocks and then immediately assert on counterparty channel state need to wait for the indexer to expose the new tip — wait_for_usable_channels is the right primitive for this.
- Required indexer features:
blockchain.transaction.id_from_pos (electrum) / block-index by height (esplora). These are standard in electrs and Mempool/BlockBook esplora; older indexers may not implement them.
- No more "bitcoind down" failure mode — replaced by "indexer down". The node already surfaces this clearly via
InvalidIndexer errors at unlock and warnings during sync.
- Operators who run their own bitcoind can keep doing so; they just point the node at their existing electrs/esplora next to it. No
bitcoind JSON-RPC creds needed in the node config.
Motivation
rgb-lightning-nodecurrently requires a fullbitcoindJSON-RPC connection in addition to an indexer (electrum/esplora). For most operators this is redundant: the indexer is already a complete chain source, and running an extrabitcoindpurely to feed LDK doubles the storage footprint, the boot time, and the surface area for "what do I configure".Removing it lets the node run against any maintained electrum/esplora endpoint (self-hosted, public, or an LSP-managed one), and shrinks the regtest/CI matrix accordingly. It also aligns the node with the deployment posture of most other RGB tooling, which is already indexer-only.
Proposal
Drop the
bitcoindrequirement entirely and route block + transaction sync through the configured indexer:lightning-block-sync(RPC mode) withlightning-transaction-sync, enabling bothelectrumandesplora-blockingfeatures so a single binary supports both protocols.estimate_feefor electrum,get_fee_estimatesfor esplora), interpolating across confirmation buckets.transaction_broadcast/ esploraPOST /tx.blockchain.transaction.id_from_pos/ esplora block-index lookup), with async resolution so peer-manager isn't blocked.API / config surface changes
unlockandinitpayloads (and the OpenAPI spec):bitcoind_rpc_username,bitcoind_rpc_password,bitcoind_rpc_host,bitcoind_rpc_port.indexer_url(already acceptstcp://host:portfor electrum orhttps://hostfor esplora; auto-detected).bitcoindservice from the runtime image;compose.yamlstill shipsbitcoindfor regtest because we still need a block source for the test stack, just not for the node itself.Tradeoffs / behavioral notes
tokio::time::sleep(Duration::from_secs(1))betweentx_sync.sync(...)calls). For most workloads this is invisible, but tests that mine N blocks and then immediately assert on counterparty channel state need to wait for the indexer to expose the new tip —wait_for_usable_channelsis the right primitive for this.blockchain.transaction.id_from_pos(electrum) / block-index by height (esplora). These are standard in electrs and Mempool/BlockBook esplora; older indexers may not implement them.InvalidIndexererrors at unlock and warnings during sync.bitcoindJSON-RPC creds needed in the node config.