39e244a11c
- Replace random_shuffle (removed in C++17) with std::shuffle in wallet.cpp - Add -std=c++17 to makefile.mingw (Windows daemon was missing it) - Add lz4.o, tor_embed_hooks.o, tor_embedded.o to makefile.mingw OBJS - Add build rules for new objects in makefile.mingw - Simplify Tor embedded build to use aggregate libtor.a Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
221 lines
6.7 KiB
Markdown
221 lines
6.7 KiB
Markdown
# Embedded Tor Integration Guide for Triangles
|
|
|
|
This guide explains how to compile Tor as a static library (`libtor.a`) and link
|
|
it directly into the Triangles wallet binary so that every node automatically
|
|
runs a Tor hidden service without needing an external Tor installation.
|
|
|
|
## Architecture Overview
|
|
|
|
```
|
|
trianglesd / triangles-qt
|
|
├── tor_embedded.cpp ← calls tor_run_main() in a background thread
|
|
├── tor_process.cpp ← fallback: launches external tor binary (already works)
|
|
├── onion_v3.cpp ← V3 onion address generation / SOCKS5 proxy logic
|
|
└── libtor.a ← aggregate static Tor library (built from official source)
|
|
```
|
|
|
|
When compiled with `ENABLE_TOR_EMBEDDED`, the wallet calls `tor_run_main()` from
|
|
`tor_api.h` on a dedicated thread. This gives the wallet a SOCKS5 proxy on
|
|
`127.0.0.1:19099` and a V3 hidden service on port 24112 (the P2P port).
|
|
|
|
When compiled **without** the flag, `tor_embedded.cpp` falls back to the external
|
|
`tor_process.cpp` which searches for and launches a system `tor` binary.
|
|
|
|
## Step 1: Add Tor as a Git Submodule
|
|
|
|
```bash
|
|
cd /path/to/triangles
|
|
git submodule add https://gitlab.torproject.org/tpo/core/tor.git src/tor/tor-src
|
|
cd src/tor/tor-src
|
|
git checkout release-0.4.9 # latest stable branch as of 2026
|
|
```
|
|
|
|
This puts the full Tor source at `src/tor/tor-src/`.
|
|
Current imported checkout in this repo: `release-0.4.9` at commit `1442ca4`.
|
|
There is also a helper build script at `src/tor/build-libtor.sh`.
|
|
|
|
## Step 2: Build libtor.a
|
|
|
|
Tor uses autotools. Build it as a static library:
|
|
|
|
```bash
|
|
cd src/tor/tor-src
|
|
|
|
# Install Tor build dependencies
|
|
sudo apt install autoconf automake libtool pkg-config \
|
|
libssl-dev libevent-dev zlib1g-dev
|
|
|
|
# Generate configure script
|
|
./autogen.sh
|
|
|
|
# Configure for static library build (disable unneeded modules)
|
|
./configure \
|
|
--enable-static-tor \
|
|
--disable-module-relay \
|
|
--disable-module-dirauth \
|
|
--disable-asciidoc \
|
|
--disable-manpage \
|
|
--disable-html-manual \
|
|
--disable-unittests \
|
|
--disable-tool-name-check \
|
|
--with-openssl-dir=/usr \
|
|
--with-libevent-dir=/usr \
|
|
--with-zlib-dir=/usr \
|
|
--prefix=/usr/local
|
|
|
|
make -j$(nproc)
|
|
```
|
|
|
|
Or from the repo root:
|
|
```bash
|
|
./src/tor/build-libtor.sh
|
|
```
|
|
|
|
After building, the static libraries are in `src/tor/tor-src/`:
|
|
- `libtor.a`
|
|
- `src/lib/libtor-*.a` (multiple component libs)
|
|
|
|
The header `src/feature/api/tor_api.h` provides the public C API:
|
|
```c
|
|
tor_main_configuration_t *tor_main_configuration_new(void);
|
|
int tor_main_configuration_set_command_line(tor_main_configuration_t *cfg,
|
|
int argc, char *argv[]);
|
|
int tor_run_main(const tor_main_configuration_t *);
|
|
void tor_main_configuration_free(tor_main_configuration_t *);
|
|
```
|
|
|
|
## Step 3: Build Triangles with Embedded Tor
|
|
|
|
### Linux (makefile.unix)
|
|
|
|
```bash
|
|
cd src
|
|
|
|
# Point to Tor's built libraries and headers
|
|
make -f makefile.unix \
|
|
USE_TOR_EMBEDDED=1
|
|
```
|
|
|
|
You may need to adjust the `-l` flags in the makefile depending on the exact
|
|
library names Tor produces. Check `src/tor/tor-src/` after building:
|
|
|
|
```bash
|
|
find tor/tor-src -name '*.a' | sort
|
|
```
|
|
|
|
On the imported `release-0.4.9` checkout in this repo, the simplest working
|
|
link path is the aggregate `libtor.a` plus the normal dependency libraries.
|
|
|
|
### Windows (triangles-qt.pro)
|
|
|
|
Add to `triangles-qt.pro`:
|
|
```qmake
|
|
qmake "USE_TOR_EMBEDDED=1" \
|
|
"TOR_SOURCE_ROOT=src/tor/tor-src"
|
|
```
|
|
|
|
Both build systems now default to:
|
|
- source root: `src/tor/tor-src`
|
|
- include path: `src/tor/tor-src/src/feature/api`
|
|
- library path: `src/tor/tor-src`
|
|
- embedded Tor library: `-ltor`
|
|
|
|
On Windows, the imported Tor `0.4.9.5` build also needed:
|
|
- `-llzma`
|
|
- `-lzstd`
|
|
- `-liphlpapi`
|
|
- `-lshlwapi` (already linked by Triangles)
|
|
|
|
## Step 4: Wire into init.cpp
|
|
|
|
The global hooks `StartEmbeddedTor()` and `StopEmbeddedTor()` need to be called
|
|
from `init.cpp`. Add these calls:
|
|
|
|
### In AppInit2() (after network init, before starting node):
|
|
```cpp
|
|
#include "tor/tor_embedded.h"
|
|
|
|
// Near the end of AppInit2, after network initialization:
|
|
if (!StartEmbeddedTor()) {
|
|
printf("WARNING: Embedded Tor failed to start. .onion connectivity unavailable.\n");
|
|
// Non-fatal: wallet works without Tor, just no .onion
|
|
}
|
|
```
|
|
|
|
### In Shutdown():
|
|
```cpp
|
|
StopEmbeddedTor();
|
|
```
|
|
|
|
## Step 5: Configure SOCKS Proxy for Outbound Connections
|
|
|
|
After Tor starts, the wallet needs to route `.onion` connections through the
|
|
SOCKS5 proxy. In `net.cpp`, after Tor is initialized:
|
|
|
|
```cpp
|
|
// If embedded Tor is running, use its SOCKS proxy for .onion addresses
|
|
CTorEmbedded* tor = CTorEmbedded::GetInstance();
|
|
if (tor->IsRunning()) {
|
|
// Set proxy for .onion connections
|
|
proxyType addrProxy(CService("127.0.0.1", tor->GetSocksPort()), 5);
|
|
SetNameProxy(addrProxy);
|
|
}
|
|
```
|
|
|
|
## Runtime Flags
|
|
|
|
The embedded Tor respects these command-line flags:
|
|
|
|
| Flag | Default | Description |
|
|
|------|---------|-------------|
|
|
| `-notor` | false | Disable Tor entirely |
|
|
| `-torsocks=PORT` | 19099 | SOCKS5 proxy port |
|
|
| `-torhsport=PORT` | 24112 | Hidden service virtual port |
|
|
|
|
## File Layout After Integration
|
|
|
|
```
|
|
src/tor/
|
|
├── tor-src/ ← git submodule (official Tor repo)
|
|
│ └── src/
|
|
│ ├── lib/libtor-*.a
|
|
│ └── feature/api/tor_api.h
|
|
│ └── libtor.a
|
|
├── tor_embedded.h ← CTorEmbedded class header
|
|
├── tor_embedded.cpp ← implementation (calls tor_run_main)
|
|
├── tor_process.h ← external Tor process manager (fallback)
|
|
├── tor_process.cpp
|
|
├── onion_v3.h ← V3 onion address utilities
|
|
├── onion_v3.cpp
|
|
├── anonymize.h ← data dir helpers
|
|
├── anonymize.cpp
|
|
└── LICENSE
|
|
```
|
|
|
|
## Reference: How VERGE (XVG) Does It
|
|
|
|
VERGE uses the same pattern. Their implementation is at:
|
|
- `src/torcontroller.cpp` (~100 lines)
|
|
- They use `tor_main()` (older API, pre-0.4.5)
|
|
- Git submodule at `src/tor/` pointing to `release-0.4.8` branch
|
|
- Build Tor as part of their `depends/` system
|
|
|
|
Key difference: modern Tor (0.4.5+) uses `tor_run_main()` with a configuration
|
|
object instead of raw `tor_main(int argc, char** argv)`.
|
|
|
|
## Troubleshooting
|
|
|
|
**Tor fails to bootstrap**: Check firewall rules. Tor needs outbound TCP to the
|
|
Tor network (ports 80, 443, 9001, 9030).
|
|
|
|
**Link errors with libtor**: Prefer the aggregate `libtor.a` from the top level
|
|
of the Tor build tree. On the imported Windows/MSYS2 build in this repo, the
|
|
minimal verified link set was:
|
|
```
|
|
-ltor -levent -lssl -lcrypto -lz -llzma -lzstd -lws2_32 -liphlpapi -lshlwapi
|
|
```
|
|
|
|
**OpenSSL version mismatch**: Both Tor and Triangles must link against the same
|
|
OpenSSL version (3.x). If Tor was built against a different OpenSSL, rebuild it
|
|
with the same `--with-openssl-dir`.
|