7.6 KiB
I2P Embedded Architecture (Level 3)
Date: 2026-06-27
Status: ✅ IMPLEMENTED & WORKING
What This Is
Triangles now runs two embedded anonymity networks simultaneously:
- Tor — Every node is a .onion hidden service (existing, unchanged)
- I2P — Every node is a .b32.i2p destination (new)
Both routers run in-process as static libraries. No external dependencies, no separate daemons to install.
What I2P Adds Over Tor-Only
| Property | Tor | I2P |
|---|---|---|
| Routing | Onion (3-hop circuits) | Garlic (variable-hop tunnels) |
| Directory | Centralized authorities | Distributed floodfills |
| Service discovery | Hidden service descriptors | Network database (KadDHT) |
| Designed for | Exit to clearnet | Peer-to-peer services |
| Peer correlation resistance | Moderate | Strong (ephemeral tunnels) |
I2P was designed from the ground up for peer-to-peer anonymous services — exactly what a cryptocurrency P2P network needs. Tor's hidden services work, but Tor is optimized for anonymous web browsing (exit traffic). I2P's garlic routing, distributed network database, and short-lived tunnels make it inherently better suited for P2P mesh communication.
Architecture
Dual-Network Routing
┌─────────────────────────────────┐
│ trianglesd (process) │
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ libtor │ │ libi2pd │ │
│ │ (Tor) │ │ (I2P) │ │
│ └────┬────┘ └────┬────┘ │
│ │ │ │
.onion peers ─────┼───────┘ │ │
│ SOCKS 19099 │ │
│ │ │
.b32.i2p peers ───┼──────────────────────┘ │
│ SOCKS 19100 │
└─────────────────────────────────┘
Traffic Flow
| Destination | Route | Proxy |
|---|---|---|
*.onion |
Tor SOCKS5 → Tor circuit → hidden service | 127.0.0.1:19099 |
*.b32.i2p |
I2P SOCKS5 → I2P tunnel → destination | 127.0.0.1:19100 |
| Clearnet (IPv4/IPv6) | BLOCKED | — |
The routing decision happens in ConnectSocketByName() (netbase.cpp):
.b32.i2psuffix → I2P SOCKS proxy (NET_I2P)- Everything else → Tor name proxy (SetNameProxy)
Implementation
Files Added
src/i2p/
├── i2pd-src/ # PurpleI2P/i2pd git submodule
├── i2p_embedded.h # CI2PEmbedded class declaration
├── i2p_embedded.cpp # Embedded router start/stop logic
├── i2pseed.h # Hardcoded .b32.i2p seed nodes
└── build-libi2pd.sh # Static library build script
Files Modified
| File | Change |
|---|---|
CMakeLists.txt |
USE_I2P_EMBEDDED option + config summary |
src/CMakeLists.txt |
I2P source, includes, library linking |
src/init.cpp |
I2P startup (after Tor), shutdown, CLI flags |
src/net.cpp |
Allow .b32.i2p in ConnectNode() and seed parser |
src/netbase.cpp |
I2P SOCKS routing, fixed .b32.i2p address parsing |
CI2PEmbedded Class
Singleton pattern (mirrors CTorEmbedded):
class CI2PEmbedded {
bool Start(int socksPort, int samPort, int serverPort);
void Stop();
bool IsRunning() const;
std::string GetSocksProxy() const; // "127.0.0.1:19100"
std::string GetI2PAddress() const; // .b32.i2p destination
};
Startup Sequence (init.cpp)
1. StartEmbeddedTor() → Tor SOCKS on 19099
2. TOR-NATIVE MODE → all traffic forced through Tor
3. StartEmbeddedI2P() → i2pd SOCKS on 19100
4. I2P-NATIVE MODE → .b32.i2p routed through i2pd
5. Dual-network anonymity → Tor + I2P co-equal
If I2P fails to start, the daemon continues in Tor-only mode (non-fatal).
How i2pd Integrates
i2pd provides a C++ API (libi2pd/api.h) for in-process embedding:
i2p::api::InitI2P(argc, argv, "triangles-i2pd");
i2p::api::StartI2P(logStream);
i2p::client::context.Start(); // SAM, SOCKS, tunnels
The auto-generated i2pd.conf enables:
- SOCKS proxy on 19100 (for outbound .b32.i2p)
- SAM bridge on 7656 (for future SAM v3 protocol)
- Server tunnel in
tunnels.conf(I2P hidden service)
The tunnels.conf is written before Start():
[triangles-p2p]
type = server
host = 127.0.0.1
port = <P2P_PORT>
keys = triangles-p2p-keys.dat
inbound.length = 3
outbound.length = 3
This creates a persistent .b32.i2p destination that survives restarts.
Build Instructions
Prerequisites
Same as existing Tor build + Boost (already required).
Build with I2P
# 1. Initialize the i2pd submodule
git submodule update --init --recursive src/i2p/i2pd-src
# 2. Build i2pd static libraries
cd src/i2p && bash build-libi2pd.sh
# 3. Configure and build Triangles
mkdir build && cd build
cmake -G Ninja -DUSE_I2P_EMBEDDED=ON ..
ninja trianglesd
Build without I2P (Tor-only, existing behavior)
cmake -G Ninja .. # USE_I2P_EMBEDDED defaults to OFF
ninja trianglesd
CLI Flags
| Flag | Default | Description |
|---|---|---|
-i2p |
1 |
Enable embedded I2P router |
-i2psocks=<port> |
19100 |
I2P SOCKS proxy port |
-i2psam=<port> |
7656 |
I2P SAM bridge port |
-i2phsport=<port> |
P2P port | I2P server tunnel forward port |
Testing Verification
Expected Startup Output
Embedded I2P: starting i2pd router...
Embedded I2P: server tunnel configured on port 24112
...
Clients: New private keys file .../triangles-p2p-keys.dat for <b32>.b32.i2p created
Clients: 1 I2P server tunnels created
Embedded I2P: SOCKS proxy at 127.0.0.1:19100, SAM at 127.0.0.1:7656
...
I2P-NATIVE MODE: I2P router running
SOCKS proxy at 127.0.0.1:19100 for .b32.i2p connections
Dual-network anonymity: Tor (.onion) + I2P (.b32.i2p)
Seed Node Deployment
To deploy an I2P seed node:
- Build with
-DUSE_I2P_EMBEDDED=ON - Start the daemon — it auto-generates a
.b32.i2pdestination - Read the address from the log:
grep "b32.i2p" debug.log - Add the address to
src/i2p/i2pseed.h - Add the address to
seeds.cryptographic-triangles.org/i2p-seeds.txt
The destination keys persist in <datadir>/i2p_data/triangles-p2p-keys.dat.
Comparison to Other Projects
| Project | Tor | I2P | Embedded | Dual-Network |
|---|---|---|---|---|
| Triangles | ✅ Embedded | ✅ Embedded | Both in-process | ✅ |
| Bitcoin Core | Optional | Optional (SAM) | No | No |
| Monero | Optional | No | No | No |
| Kovri (Monero I2P) | N/A | Planned | Planned | No |
Triangles is the only cryptocurrency with both Tor and I2P embedded as in-process routers.
Future Work
- I2P seed nodes: Deploy stable .b32.i2p seeds (parallel to onion seeds)
- SAM v3 direct: Use SAM bridge for native I2P streaming (bypass SOCKS overhead)
- I2P address in RPC: Expose
.b32.i2paddress viagetnetworkinfo - Cross-network bridging: Allow Tor nodes to discover I2P peers and vice versa