# Release-integrity / Whonix recon — eigenwallet/core @ 0e17c7f7cd8f0657af176c8852aa4c9949586051 Clone: `git clone --depth 1 https://github.com/eigenwallet/core.git` (34 MB, HEAD commit date 2026-08-28T14:30:24+02:00) Machine: Linux x86_64. All commands below are copy-paste reproducible. ## 1. Bounty #180 asks for: detect /usr/share/whonix/marker, use the SYSTEM Tor proxy instead of the built-in Tor client. ## 2. What the code does today — the transport has no external-proxy path ``` $ grep -rIn --include=*.rs -e "TorClient" -e "socks5" -e "proxy" -e "whonix" . | grep -vi test | head -20 ./libp2p-rendezvous-node/src/tor.rs:4:use arti_client::{TorClient, config::TorClientConfigBuilder}; ./libp2p-rendezvous-node/src/tor.rs:10:pub async fn create_tor_client(data_dir: &Path) -> Result>> { ./libp2p-rendezvous-node/src/tor.rs:31: let config = TorClientConfigBuilder::from_directories(&state_dir, &cache_dir); ./libp2p-rendezvous-node/src/tor.rs:42: let tor_client = TorClient::with_runtime(runtime) ./libp2p-rendezvous-node/src/tor.rs:52:pub async fn bootstrap_tor_client(tor_client: Arc>) -> Result<()> { ./libp2p-tor/src/lib.rs:54:use arti_client::{TorClient, TorClientBuilder}; ./libp2p-tor/src/lib.rs:141: client: Arc>, ./libp2p-tor/src/lib.rs:156: /// Creates a new `TorClientBuilder`. ./libp2p-tor/src/lib.rs:160: pub fn builder() -> TorClientBuilder { ./libp2p-tor/src/lib.rs:163: TorClient::with_runtime(runtime) ./libp2p-tor/src/lib.rs:192: /// Builds a `TorTransport` from an Arti `TorClientBuilder` but does not bootstrap it. ./libp2p-tor/src/lib.rs:195: /// Could return error emitted during creation of the `TorClient`. ./libp2p-tor/src/lib.rs:197: builder: &TorClientBuilder, ./libp2p-tor/src/lib.rs:205: /// Builds a `TorTransport` from an existing Arti `TorClient`. ./libp2p-tor/src/lib.rs:207: client: Arc>, ./monero-rpc-pool/src/config.rs:4:use crate::TorClientArc; ./monero-rpc-pool/src/config.rs:11: pub tor_client: Option, ./monero-rpc-pool/src/config.rs:36: tor_client: impl Into>, ./monero-rpc-pool/src/config.rs:54: tor_client: impl Into>, ./monero-rpc-pool/src/lib.rs:4:use arti_client::TorClient; ``` ### Doc drift (verified by absence) ``` $ grep -rn "tor_socks5_port" --include=*.rs . (no output above = zero hits in the whole repo) ``` But the generated CLI docs still advertise the flag: ``` $ grep -n "tor-socks5-port" dev-docs/cli/README.md 73: --tor-socks5-port Your local Tor socks5 proxy port [default: 9050] 100: --tor-socks5-port Your local Tor socks5 proxy port [default: 9050] ``` Conclusion: `--tor-socks5-port [default: 9050]` is documented but does not exist in the source. Today a user inside Whonix cannot route onion dials through the host Tor; the only two states are (a) built-in arti TorClient, (b) plain TCP+DNS. ## 3. No SOCKS client dependency is available to build an external-proxy transport ``` $ grep -n "^name = \"\(tokio-socks\|socks\|libp2p-socks\|socks5\)\"" -A1 Cargo.lock (no output above = no SOCKS crate in the lockfile) ``` ## 4. Exact change points ``` $ grep -rIn "from_client\|bootstrap_tor_client\|create_tor_client" --include=*.rs libp2p-tor swap/src | head -20 libp2p-tor/src/lib.rs:202: Ok(Self::from_client(client, conversion_mode)) libp2p-tor/src/lib.rs:206: pub fn from_client( swap/src/asb/network.rs:68: libp2p_tor::TorTransport::from_client(tor_client, AddressConversion::DnsOnly); swap/src/cli/api.rs:7:use crate::common::tor::{bootstrap_tor_client, create_tor_client}; swap/src/cli/api.rs:594: match create_tor_client(&base_data_dir).await.inspect_err(|err| { swap/src/cli/api.rs:624: let bootstrap_tor_client_task = AbortOnDropHandle::new(tokio::spawn({ swap/src/cli/api.rs:630: bootstrap_tor_client(tor_client.clone(), tauri_handle.clone()) swap/src/cli/api.rs:642: bootstrap_tor_client_task, swap/src/cli/api.rs:654: bootstrap_tor_client_task, swap/src/cli/api.rs:893: bootstrap_tor_client_task.await?; swap/src/cli/transport.rs:96: TorTransport::from_client(Arc::clone(client), AddressConversion::IpAndDns); swap/src/cli/transport.rs:115: let mut transport = TorTransport::from_client(client, AddressConversion::IpAndDns); swap/src/common/tor.rs:15:pub async fn create_tor_client( swap/src/common/tor.rs:67:pub async fn bootstrap_tor_client( ``` - `swap/src/common/tor.rs` — `create_tor_client` (builds arti `TorClientConfigBuilder`), `bootstrap_tor_client`. - `swap/src/cli/api.rs` (~l.600-660) — decides whether a built-in Tor client exists (`enable_monero_tor`) and spawns the bootstrap task. - `swap/src/cli/transport.rs` (`new()`, ~l.80-120) — `OptionalTransport::some/none` over TCP+DNS: the single place where 'route over Tor' vs 'plain' is chosen. ## 5. Minimal patch shape 1. `pub fn whonix_detected() -> bool` : `Path::new("/usr/share/whonix/marker").exists()` **or** `TOR_SOCKS_PORT` set in the environment (Whonix best practices, /Programmatically Detecting Whonix). 2. If detected: skip `bootstrap_tor_client` entirely (that is the tor-over-tor), and hand `transport::new` a SOCKS5 transport to `127.0.0.1:${TOR_SOCKS_PORT:-9050}` with `socks5h` (remote DNS, so onion names are resolved by the host Tor, not locally). 3. Surface it: one GUI/CLI log line 'using system Tor at 127.0.0.1:9050 (Whonix detected)'. ## 6. Test procedure (reproducible without Whonix) - `sudo touch /usr/share/whonix/marker` (or `TOR_SOCKS_PORT=9050`), start the daemon, assert the log shows no arti bootstrap and that the onion dial goes through 9050 (`ss -tnp | grep 9050`). - Negative test: marker absent, no `TOR_SOCKS_PORT` -> built-in arti bootstrap happens exactly as before (no regression).