Skip to main content

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:

  1. 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.
  2. 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:

FlagDefaultDescription
-i2pacceptincoming1Accept inbound I2P connections
-onlynet=i2pRestrict outbound to I2P only
-debug=i2pEnable 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

  1. Install CJDNS and generate a configuration: github.com/cjdelisle/cjdns
  2. Connect to at least one CJDNS peer.
  3. 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

TopicDescriptionPayload
hashblockChain tip updated32-byte block hash (LE)
rawblockChain tip updatedSerialized block
hashtxTransaction (mempool or block)32-byte tx hash (LE)
rawtxTransaction (mempool or block)Serialized transaction
hashwallettxWallet transaction32-byte tx hash (LE), topic includes -block or -mempool
rawwallettxWallet transactionSerialized tx, topic includes -block or -mempool
sequenceMempool/chain sequenceHash + 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

ServiceDefault PortProtocol
P2P19335TCP
RPC19334TCP (localhost only by default)
ZMQ28332+TCP (user-configured)
Tor inbound19336TCP (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.