Installation & Prerequisites
ElectrumR requires Rust 1.70+, a Bitcoin SV node with RPC access, and optionally direct access to the node's block files for maximum sync performance.
Install the required build dependencies for your operating system:
# Ubuntu/Debian $ sudo apt install build-essential clang libclang-dev pkg-config libssl-dev # Fedora/RHEL $ sudo dnf install gcc-c++ clang clang-devel pkgconf-pkg-config openssl-devel # Arch Linux $ sudo pacman -S base-devel clang pkgconf openssl # macOS $ brew install llvm pkg-config openssl
RocksDB opens a large number of files simultaneously. You must increase your file descriptor limit before running ElectrumR:
$ ulimit -n 200000
To make this permanent, add the following to /etc/security/limits.conf:
* soft nofile 200000 * hard nofile 200000
Build
Clone the repository and build the release binary:
$ git clone https://github.com/KeyvanJS/ElectrumR.git $ cd ElectrumR $ cargo build --release
Setup
Run the interactive setup script to auto-detect your hardware and generate a configuration:
$ ./setup.sh
The setup script detects your system's available RAM, CPU cores, and disk type. It prompts you for your Bitcoin node's RPC credentials and block directory path, then writes a start.sh script with optimized environment variables for your hardware.
Running
Start ElectrumR using the generated start script:
$ ./start.sh
If you prefer manual configuration, you can set environment variables directly and run the binary. See the Configuration Reference below for all available options.
To run the test suite:
$ cargo test # 131 tests
Configuration Reference
ElectrumR is configured entirely through environment variables. All variables are optional and have sensible defaults. Use the filter below to search for specific variables.
Core Configuration
| Variable | Default | Description |
|---|---|---|
DB_DIRECTORY |
./electrumr_db |
RocksDB data directory for all database files, undo data, and tx hashes. |
LOG_DIRECTORY |
$DB_DIRECTORY/logs |
Log output directory. Defaults to logs/ inside DB_DIRECTORY. |
DAEMON_URL |
http://127.0.0.1:8332 |
Bitcoin daemon JSON-RPC endpoint. |
RPC_USER |
(none) | RPC username for the Bitcoin daemon. |
RPC_PASSWORD |
(none) | RPC password for the Bitcoin daemon. |
COIN |
BitcoinSV |
Coin type. Determines genesis hash and consensus rules. |
NET |
mainnet |
Network (mainnet or testnet). |
BITCOIND_BLOCKS_DIR |
(none) | Path to bitcoind blocks/ dir for direct mmap-based .blk file reading. |
Network Services
| Variable | Default | Description |
|---|---|---|
TCP_PORT |
50001 |
Electrum TCP listen port. |
TCP_HOST |
0.0.0.0 |
TCP bind address. |
SSL_PORT |
(disabled) | SSL/TLS listen port. Requires SSL_CERTFILE and SSL_KEYFILE. |
SSL_HOST |
0.0.0.0 |
SSL bind address. |
WS_PORT |
(disabled) | WebSocket listen port. |
WS_HOST |
0.0.0.0 |
WebSocket bind address. |
WSS_PORT |
(disabled) | Secure WebSocket listen port. Requires SSL_CERTFILE/SSL_KEYFILE. |
WSS_HOST |
0.0.0.0 |
WSS bind address. |
SSL_CERTFILE |
(none) | PEM-encoded SSL certificate file. Required for SSL and WSS. |
SSL_KEYFILE |
(none) | PEM-encoded SSL private key file. Required for SSL and WSS. |
Memory Management
| Variable | Default | Description |
|---|---|---|
CACHE_MB |
1200 |
Cache size in MB. Used twice (block cache + UTXO LRU). See warning below. |
MAX_MEMORY_MB |
0 (auto) |
Max heap memory in MB. 0 = auto-detect 80% of system RAM. |
MEMORY_WARN_THRESHOLD |
60 |
Percent of limit that triggers warning. Batch size reduced 50%. |
MEMORY_CRITICAL_THRESHOLD |
75 |
Percent that triggers critical. Batch reduced 75%, early flush. |
MEMORY_EMERGENCY_THRESHOLD |
85 |
Percent that triggers emergency. Sync pauses, immediate flush. |
CACHE_MB is consumed twice — once as the RocksDB block cache and once as the UTXO LRU cache. Effective memory from this setting alone is 2 × CACHE_MB. On top of that, expect roughly 30 GB of additional overhead from UTXO cache entry structs (~6-8 GB at 94M entries), RocksDB internals (bloom filters, block index, memtables: ~10-20 GB), mmap'd block files (~7-8 GB), and write buffers.
Rule of thumb: Total RSS ≈ 2 × CACHE_MB + write buffers + ~30 GB overhead. Keep total under 80% of system RAM.
RocksDB Tuning
| Variable | Default | Description |
|---|---|---|
ROCKSDB_WRITE_BUFFER_MB |
128 |
Write buffer size (MB) for the main column family. |
ROCKSDB_MAX_WRITE_BUFFERS |
6 |
Max write buffers for the main CF. Absorbs write bursts. |
ROCKSDB_SHARD_WRITE_BUFFER_MB |
64 |
Write buffer size (MB) per shard CF (16 shards). |
ROCKSDB_SHARD_MAX_WRITE_BUFFERS |
4 |
Max write buffers per shard CF. |
ROCKSDB_COMPRESSION |
none |
SST compression: none, snappy, lz4, zstd. None = fastest. |
ROCKSDB_DISABLE_AUTO_COMPACTION |
false |
Disable auto-compaction. Not recommended. |
ROCKSDB_MAX_OPEN_FILES |
200000 |
Max open file descriptors. |
ROCKSDB_MAX_WAL_SIZE_MB |
1024 |
Max WAL size in MB. Bounds crash recovery replay time. |
Sync Pipeline
| Variable | Default | Description |
|---|---|---|
SYNC_BATCH_SIZE |
32 |
Blocks per batch. Auto-reduced to 1 for blocks >256 MB. |
SYNC_CHANNEL_DEPTH |
2 |
Channel buffer depth between pipeline stages. |
SYNC_FLUSH_INTERVAL |
25 |
Blocks between disk flushes. Memory pressure can override. |
SYNC_PREFETCH_ENABLED |
true |
Enable UTXO prefetch stage. |
SYNC_PREFETCH_CHANNEL_DEPTH |
= SYNC_CHANNEL_DEPTH |
Prefetch stage channel depth. |
SYNC_POLL_INTERVAL |
5 |
Seconds between daemon RPC polls (polling fallback mode). |
HISTORY_BATCH_SIZE |
25000 |
History entries accumulated before flushing to DB. |
ZMQ Block Notifications
| Variable | Default | Description |
|---|---|---|
ZMQ_ENDPOINT |
(none) | ZMQ PUB endpoint, e.g. tcp://127.0.0.1:28332. Enables ZMQ. |
ZMQ_ENABLED |
true if endpoint set |
Force disable with false/0 even when endpoint is configured. |
ZMQ_RECONNECT_DELAY_MS |
1000 |
Milliseconds between reconnect attempts after ZMQ failure. |
ZMQ_MAX_RECONNECT_ATTEMPTS |
10 |
Max reconnects before falling back to polling. |
Client Sessions
| Variable | Default | Description |
|---|---|---|
MAX_SESSIONS |
50000 |
Maximum concurrent Electrum client sessions. |
MAX_SEND |
10000000 |
Max bytes per response (~10 MB). |
MAX_RECV |
50000000 |
Max bytes per request (~50 MB). |
COST_SOFT_LIMIT |
1000.0 |
Soft cost limit per session. Exceeding = deprioritized. |
COST_HARD_LIMIT |
10000.0 |
Hard cost limit per session. Exceeding = disconnected. |
REQUEST_TIMEOUT |
30 |
Seconds before an individual request times out. |
SESSION_TIMEOUT |
600 |
Seconds of inactivity before session is closed (10 min). |
Peer Discovery & Tor
| Variable | Default | Description |
|---|---|---|
PEER_DISCOVERY |
on |
on = full discovery, self/self_only = self only, off. |
PEER_ANNOUNCE |
true |
Announce this server to discovered peers. |
TOR_PROXY_HOST |
localhost |
SOCKS5 proxy host for Tor peer connections. |
TOR_PROXY_PORT |
(none) | SOCKS5 proxy port. Tor connections only attempted when set. |
Logging & Debugging
| Variable | Default | Description |
|---|---|---|
LOG_LEVEL |
info |
Min log level: trace, debug, info, warn, error. |
LOG_FILE |
(none) | Log file path. Default: $DB_DIRECTORY/logs/electrumr.log.YYYY-MM-DD. |
LOG_JSON |
false |
Emit logs as JSON lines for log aggregation. |
DEBUG_MODE |
false |
Verbose diagnostics: thread IDs, file locations, internal state. |
Server Identity
| Variable | Default | Description |
|---|---|---|
BANNER_FILE |
(none) | Text file returned by server.banner. |
DONATION_ADDRESS |
"" |
Address returned by server.donation_address. |
Chain Safety
| Variable | Default | Description |
|---|---|---|
REORG_LIMIT |
200 |
Max reorg depth. Deeper reorgs are rejected (requires manual DB reset). |
Recovery & Diagnostics
| Variable | Default | Description |
|---|---|---|
FORCE_GHOST_SCAN |
(none) | Block height to force ghost UTXO scan on next startup. |
MAX_ERRORS |
100 |
Max errors before stopping (verify-internal binary only). |
Operations
Graceful Shutdown
Send a standard termination signal to initiate a graceful shutdown:
$ kill $(pgrep -f electrumr)
The shutdown sequence proceeds through 5 ordered steps:
- Broadcasts shutdown signal to all components
- SyncManager stops processing, flushes pending data
- UTXO cache saved to disk (~15s for 94M entries)
- Final statistics logged
- Clean exit
Do not use kill -9 — it bypasses graceful shutdown and loses the UTXO cache. Without cache persistence, restart cache hit rate starts near 0% and takes many blocks to warm up, causing 10-30x slower sync speed.
Database Reset
To perform a full database reset and resync from block 0:
$ pkill electrumr $ rm -rf /path/to/electrumr_db $ ./start.sh # Rebuilds from block 0
Monitoring
TUI Monitor
ElectrumR ships with a real-time terminal user interface (TUI) monitoring dashboard:
$ ./target/release/electrumr-monitor
The TUI monitor provides a real-time dashboard displaying current block height, sync progress, transactions per second, memory usage, cache hit rates, RocksDB statistics, and active client sessions. It connects to the running ElectrumR instance and updates continuously.
Stats Endpoint
ElectrumR exposes a Unix socket stats server for programmatic access to runtime metrics. This allows external monitoring tools, scripts, and dashboards to query the server's current state without disrupting operation.
ETA Calculation
Sync throughput varies significantly by block height due to increasing block sizes and transaction complexity. Use the following profile to estimate time to full sync:
| Block Height | Throughput |
|---|---|
| 0-100k | ~580 blocks/sec |
| 400k-500k | ~90 blocks/sec |
| 700k-800k | ~14-26 blocks/sec |
| 900k+ | ~6 blocks/sec |
Verification Tools
verify-internal
The internal consistency checker verifies that every u-key (UTXO by address) has a matching h-key (UTXO hash index) in the database. This catches any inconsistencies introduced by crashes, bugs, or incomplete flushes.
$ DB_DIRECTORY="/path/to/db" ./target/release/verify-internal
verify_bitcoind
The bitcoind cross-checker samples random UTXO outputs from the ElectrumR database and compares them against the Bitcoin node's gettxout RPC call. This confirms that ElectrumR's UTXO set matches the node's view of the chain.
$ python3 verify_bitcoind.py --samples 50
Both verification tools are safe to run while ElectrumR is syncing. They operate in read-only mode and do not modify the database.
Protocol Support
ElectrumR implements the Electrum protocol, supporting the following methods:
blockchain.headers.subscribeblockchain.scripthash.subscribeblockchain.scripthash.get_historyblockchain.scripthash.get_balanceblockchain.scripthash.listunspentblockchain.transaction.getblockchain.transaction.broadcastserver.version- And more...
Storage Schema
Key Formats
ElectrumR uses a compact binary key format for all database entries. Each key type is prefixed with a single-byte tag for efficient range scans:
UTXO by address: 'u' + hashX[11] + tx_idx[4] + tx_num[5] -> value[8] UTXO hash index: 'h' + tx_hash[32] + tx_idx[4] + tx_num[5] -> hashX[11] History: 'H' + hashX[11] + flush_id[2] -> tx_nums (5 bytes each) Undo: 'U' + height[4] -> undo entries (60 bytes each) Block index: 'B' + block_hash[32] -> file_num[4] + offset[8] + size[4] + height[4]
File-Based Storage
In addition to RocksDB, ElectrumR maintains several flat files for data that benefits from sequential access patterns:
meta/tx_hashes.dat # 32 bytes per tx, direct access by tx_num * 32 meta/tx_counts.dat # 8 bytes per block, cumulative tx count utxo_cache.bin # Persisted UTXO LRU cache (63 bytes per entry)