Network
Peer discovery, privacy networks, Dandelion++, and ZMQ notifications.
BTX Node connects to peers over IPv4, IPv6, Tor, I2P, and CJDNS. The default P2P port is 19335 and the default RPC port is 19334. This page covers peer management, privacy relay, and event notifications.
Peer discovery and connection
BTX Node discovers peers through DNS seeds, manual additions, and address gossip from connected peers. On first start, the node queries hardcoded DNS seeds to find an initial set of peers.
Manual peer management
# Add a peer
btx-cli addnode "192.168.1.10:19335" "add"
# Remove a manually added peer
btx-cli addnode "192.168.1.10:19335" "remove"
# List manually added peers
btx-cli getaddednodeinfo
# View all connected peers with details
btx-cli getpeerinfo
# Compact network summary
btx-cli -netinfo 4 Configuration file options
Add persistent peers in btx.conf:
# Connect to specific peers on startup
addnode=100.85.221.75:19335
addnode=100.115.222.45:19335
# Connect ONLY to these peers (no discovery)
connect=100.85.221.75:19335
connect=100.115.222.45:19335
# Seed nodes (used once for initial peer discovery)
seednode=100.123.243.104:19335
Use -listen=0 to prevent accepting inbound connections.
Use -maxconnections=N to limit total peer count.
Dandelion++ relay
Dandelion++ is a transaction relay protocol that hides the origin of transactions from network observers. It activates at block 250,000 on mainnet.
Dandelion++ works in two phases:
- Stem phase — the transaction is forwarded along a random path through a small number of hops. Each node on the stem independently decides whether to continue the stem or transition to the fluff phase.
- Fluff phase — the transaction is broadcast normally via standard gossip to all peers, making it appear to originate from the fluff node rather than the true sender.
No configuration is needed. Once the network reaches block 250,000, Dandelion++ activates automatically. Before that height, transactions use standard gossip relay.
Tor support
BTX Node supports Tor v3 onion services for both outbound connections and accepting inbound peers over the Tor network.
Running behind a Tor proxy
btxd -proxy=127.0.0.1:9050
This routes all outbound connections through Tor, including connections
to .onion addresses.
Automatic onion service
If Tor is running with a control port (typically 9051) and cookie authentication is configured, BTX Node automatically creates an ephemeral onion service when listening is enabled (default). This requires no manual configuration.
Tor control setup in /etc/tor/torrc:
ControlPort 9051
CookieAuthentication 1
CookieAuthFileGroupReadable 1
DataDirectoryGroupReadable 1
The btxd user must have read access to the Tor cookie file.
On Debian-based systems, add the user to the debian-tor group:
sudo usermod -a -G debian-tor btx Manual onion service
Add to /etc/tor/torrc:
HiddenServiceDir /var/lib/tor/btx-service/
HiddenServicePort 19335 127.0.0.1:19336 Then start btxd with the onion address:
btxd -proxy=127.0.0.1:9050 \
-externalip=YOUR_ONION_ADDRESS.onion \
-listen \
-bind=127.0.0.1:19336=onion Tor-only mode
btxd -proxy=127.0.0.1:9050 -onlynet=onion -listen
To see Tor debug information, add -debug=tor. Check your
local onion address with btx-cli getnetworkinfo (look in
localaddresses).
Troubleshooting
If Tor logs show "resolve failed / No more HSDir available", this is a
Tor transport issue, not a BTX consensus problem. Verify that Tor itself
has completed bootstrap (systemctl status tor) and that
outbound firewall rules permit Tor relay traffic. Set onion=0
if you do not need onion peers.
I2P support
BTX Node connects to the I2P network through the SAM v3.1 protocol. A running I2P router with SAM enabled is required.
Recommended I2P routers
- i2pd (C++) — SAM enabled by default
- Java I2P — enable SAM manually in the router console at
http://127.0.0.1:7657/configclients
Configuration
btxd -i2psam=127.0.0.1:7656 Additional options:
| Flag | Default | Description |
|---|---|---|
-i2pacceptincoming | 1 | Accept inbound I2P connections |
-onlynet=i2p | — | Restrict outbound to I2P only |
-debug=i2p | — | Enable I2P debug logging |
Persistent vs transient addresses
By default, BTX Node generates a persistent I2P address saved in
i2p_private_key in the data directory. This address is used
for both outbound connections and accepting inbound peers.
With -i2pacceptincoming=0, the node uses a random transient
address for each outbound connection, making fingerprinting harder but
adding connection setup latency.
Unlike Tor, I2P connections reveal the sender's address to the receiver. Combine I2P with Tor for defense in depth.
CJDNS support
CJDNS is an encrypted IPv6 mesh network using public-key cryptography
for address allocation. All participants use addresses from the
fc00::/8 range.
Setup
- Install CJDNS and generate a configuration: github.com/cjdelisle/cjdns
- Connect to at least one CJDNS peer.
-
Enable CJDNS in BTX Node:
btxd -cjdnsreachable
The -cjdnsreachable flag tells BTX Node that
fc00::/8 connections are CJDNS rather than RFC 4193
private IPv6, enabling proper address management and peer gossip.
Compared to Tor and I2P, CJDNS is fast and provides end-to-end encryption, but it does not hide sender/receiver identities from intermediate routers. Use it as a complementary overlay for network redundancy.
CJDNS-only mode
btxd -cjdnsreachable -onlynet=cjdns ZMQ pub/sub notifications
ZeroMQ provides a write-only publish/subscribe interface for real-time
block and transaction events. Build with -DWITH_ZMQ=ON.
Configuration
btxd \
-zmqpubhashblock=tcp://127.0.0.1:28332 \
-zmqpubhashtx=tcp://127.0.0.1:28332 \
-zmqpubrawblock=tcp://127.0.0.1:28333 \
-zmqpubrawtx=tcp://127.0.0.1:28333 \
-zmqpubsequence=tcp://127.0.0.1:28334 Available topics
| Topic | Description | Payload |
|---|---|---|
hashblock | Chain tip updated | 32-byte block hash (LE) |
rawblock | Chain tip updated | Serialized block |
hashtx | Transaction (mempool or block) | 32-byte tx hash (LE) |
rawtx | Transaction (mempool or block) | Serialized transaction |
hashwallettx | Wallet transaction | 32-byte tx hash (LE), topic includes -block or -mempool |
rawwallettx | Wallet transaction | Serialized tx, topic includes -block or -mempool |
sequence | Mempool/chain sequence | Hash + event type + sequence number |
All messages are ZMQ multipart with three parts: topic, payload, and a uint32 sequence number (LE) for detecting lost messages. Note that hashes are in little-endian format, not the big-endian display format used by RPCs and block explorers.
Per-topic high water mark
Control the outbound message buffer per topic with
-zmqpub<topic>hwm=N:
btxd -zmqpubhashtx=tcp://127.0.0.1:28332 -zmqpubhashtxhwm=10000 Security
ZMQ sockets have no authentication. Restrict access using firewall rules
or bind to 127.0.0.1. The ZMQ interface is write-only from
btxd's perspective and does not introduce any state into the node.
Example subscriber
A Python example subscriber is included at
contrib/zmq/zmq_sub.py. Install the
pyzmq package (pip install pyzmq) and
subscribe to one or more topic prefixes.
Firewall and port forwarding
To accept inbound P2P connections, open port 19335 (TCP) on your firewall or configure port forwarding on your router.
UFW (Ubuntu)
sudo ufw allow 19335/tcp comment "BTX P2P" firewalld (Fedora/RHEL)
sudo firewall-cmd --permanent --add-port=19335/tcp
sudo firewall-cmd --reload UPnP / NAT-PMP
Automatic port mapping is available with -upnp or
-natpmp if your router supports these protocols.
Build with -DWITH_MINIUPNPC=ON and/or
-DWITH_NATPMP=ON.
Port reference
| Service | Default Port | Protocol |
|---|---|---|
| P2P | 19335 | TCP |
| RPC | 19334 | TCP (localhost only by default) |
| ZMQ | 28332+ | TCP (user-configured) |
| Tor inbound | 19336 | TCP (localhost, Tor binding) |
The RPC port binds to 127.0.0.1 by default and should
never be exposed to the public internet. Use rpcauth in
btx.conf if remote RPC access is needed, and restrict
access with firewall rules.