mirror of
https://github.com/Such-Software/smirk-backend-core.git
synced 2026-10-17 07:21:32 +02:00
electrum: make the fallback privacy tradeoff visible to operators
Falling back to public Electrum is a PRIVACY decision, not just an availability one: the queries carry user addresses. It is easy to miss because the failover is silent and correct, so the only symptom is that balances keep working. Our own LTC Fulcrum was dead for 11 days with every lookup going to third parties, and nothing surfaced it. - startup: log how many third-party fallbacks are configured and how to fail closed instead, so the posture is visible in the operator's own logs - .env.example: state the tradeoff at the setting, with both choices spelled out rather than a default presented as obviously correct - OPERATOR_SETUP: same note where an operator configures chains Also expands the shipped fallback lists (BTC 3 -> 8, LTC 4 -> 7), which is both more resilience and a wider spread of which server sees any given query.
This commit is contained in:
+21
-2
@@ -130,7 +130,25 @@ FEATURE_UTXO_MULTI_ADDRESS=false
|
|||||||
# ── Bitcoin (Electrum/Fulcrum only; the backend runs no Core RPC node) ─────
|
# ── Bitcoin (Electrum/Fulcrum only; the backend runs no Core RPC node) ─────
|
||||||
BTC_NETWORK=mainnet
|
BTC_NETWORK=mainnet
|
||||||
BTC_ELECTRUM_URL=
|
BTC_ELECTRUM_URL=
|
||||||
BTC_ELECTRUM_FALLBACKS=
|
#
|
||||||
|
# ── PRIVACY: read this before setting fallbacks ───────────────────────────────
|
||||||
|
# These are THIRD-PARTY servers. When your own Electrum/Fulcrum is unreachable,
|
||||||
|
# the backend fails over to them, and the queries it sends carry YOUR USERS'
|
||||||
|
# ADDRESSES. The failover is silent and correct, so the only symptom is that
|
||||||
|
# balances keep working: a dead Fulcrum can go unnoticed for days while every
|
||||||
|
# lookup goes to someone else's server. (That is not hypothetical; it happened
|
||||||
|
# to us for 11 days.)
|
||||||
|
#
|
||||||
|
# Two honest choices, both defensible:
|
||||||
|
# * LEAVE THESE SET for availability. Balances survive your node dying. Watch
|
||||||
|
# for the "third-party Electrum fallback(s) configured" line at startup.
|
||||||
|
# * LEAVE THEM EMPTY to fail closed. Balances break when your node breaks, and
|
||||||
|
# every query stays on infrastructure you control. This is the right default
|
||||||
|
# for a privacy-first or air-gapped deployment.
|
||||||
|
#
|
||||||
|
# More entries = more resilience and a wider spread of who sees a given query.
|
||||||
|
# They are tried in order after the primary.
|
||||||
|
BTC_ELECTRUM_FALLBACKS=ssl://electrum.blockstream.info:50002,ssl://electrum.emzy.de:50002,ssl://electrum.bitaroo.net:50002,ssl://fulcrum.sethforprivacy.com:50002,ssl://electrum.diynodes.com:50002,ssl://bitcoin.lu.ke:50002,ssl://electrum.jochen-hoenicke.de:50006,ssl://btc.electroncash.dk:60002
|
||||||
# Require CA-verified TLS (webpki + hostname) for ssl:// electrum servers. Applies
|
# Require CA-verified TLS (webpki + hostname) for ssl:// electrum servers. Applies
|
||||||
# to BOTH BTC and LTC. Default false: public electrum servers are self-signed by
|
# to BOTH BTC and LTC. Default false: public electrum servers are self-signed by
|
||||||
# convention and their data is treated as hostile regardless, so accepting any
|
# convention and their data is treated as hostile regardless, so accepting any
|
||||||
@@ -141,7 +159,8 @@ ELECTRUM_STRICT_TLS=false
|
|||||||
# ── Litecoin (Electrum/Fulcrum only; the backend runs no Core RPC node) ────
|
# ── Litecoin (Electrum/Fulcrum only; the backend runs no Core RPC node) ────
|
||||||
LTC_NETWORK=mainnet
|
LTC_NETWORK=mainnet
|
||||||
LTC_ELECTRUM_URL=
|
LTC_ELECTRUM_URL=
|
||||||
LTC_ELECTRUM_FALLBACKS=
|
# Same privacy tradeoff as BTC_ELECTRUM_FALLBACKS above; read that note.
|
||||||
|
LTC_ELECTRUM_FALLBACKS=ssl://electrum-ltc.bysh.me:50002,ssl://electrum.ltc.xurious.com:50002,ssl://backup.electrum-ltc.org:443,ssl://electrum1.cipig.net:20063,ssl://electrum2.cipig.net:20063,ssl://electrum3.cipig.net:20063,ssl://ltc.rentonisk.com:50002
|
||||||
|
|
||||||
# ── Monero (daemon + light wallet server) ─────────────────────────────────
|
# ── Monero (daemon + light wallet server) ─────────────────────────────────
|
||||||
XMR_LWS_URL=http://127.0.0.1:8443
|
XMR_LWS_URL=http://127.0.0.1:8443
|
||||||
|
|||||||
@@ -53,6 +53,28 @@ flag is on but whose source is unconfigured reports `enabled: false` via
|
|||||||
| XMR / WOW | `{XMR,WOW}_LWS_URL`, `{XMR,WOW}_LWS_ADMIN_URL`, `{XMR,WOW}_LWS_ADMIN_KEY`, `{XMR,WOW}_DAEMON_URL`. |
|
| XMR / WOW | `{XMR,WOW}_LWS_URL`, `{XMR,WOW}_LWS_ADMIN_URL`, `{XMR,WOW}_LWS_ADMIN_KEY`, `{XMR,WOW}_DAEMON_URL`. |
|
||||||
| Grin | `GRIN_OWNER_API_URL` + `GRIN_OWNER_API_SECRET`, `GRIN_WALLET_PASSWORD`, `GRIN_FOREIGN_API_URL`, and the node's `GRIN_NODE_*`. |
|
| Grin | `GRIN_OWNER_API_URL` + `GRIN_OWNER_API_SECRET`, `GRIN_WALLET_PASSWORD`, `GRIN_FOREIGN_API_URL`, and the node's `GRIN_NODE_*`. |
|
||||||
|
|
||||||
|
> **Electrum fallbacks are a privacy decision.**
|
||||||
|
>
|
||||||
|
> `{BTC,LTC}_ELECTRUM_FALLBACKS` are third-party servers. If your own
|
||||||
|
> Electrum/Fulcrum becomes unreachable, the backend fails over to them and the
|
||||||
|
> queries it sends carry **your users' addresses**.
|
||||||
|
>
|
||||||
|
> The failover is silent and correct, which is the trap: the only symptom is that
|
||||||
|
> balances keep working. Our own Litecoin Fulcrum was dead for 11 days before
|
||||||
|
> anyone noticed, with every lookup going to public servers in the meantime.
|
||||||
|
>
|
||||||
|
> Decide deliberately:
|
||||||
|
>
|
||||||
|
> - **Keep fallbacks** for availability. Balances survive your node dying. The
|
||||||
|
> backend logs `third-party Electrum fallback(s) configured` at startup so the
|
||||||
|
> choice is visible in your logs, and you should alert on your own Electrum
|
||||||
|
> being down rather than relying on users to notice.
|
||||||
|
> - **Leave them empty** to fail closed. Balances break when your node breaks,
|
||||||
|
> and every query stays on infrastructure you control. This is the right
|
||||||
|
> default for a privacy-first or air-gapped instance.
|
||||||
|
>
|
||||||
|
> There is no third option where a dead node is both invisible and private.
|
||||||
|
|
||||||
## 4. Run
|
## 4. Run
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|||||||
@@ -1151,6 +1151,29 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Electrum fallbacks are a PRIVACY decision, not just an availability one.
|
||||||
|
//
|
||||||
|
// When the operator's own Fulcrum is unreachable the client fails over to
|
||||||
|
// these servers, and the queries it sends carry USER ADDRESSES. On an
|
||||||
|
// instance whose whole pitch is "run your own backend and send us
|
||||||
|
// nothing", that is a posture change the operator should make knowingly.
|
||||||
|
//
|
||||||
|
// It is easy to miss: the failover is silent and correct, so the only
|
||||||
|
// symptom is that balances keep working. A dead Fulcrum went unnoticed
|
||||||
|
// for 11 days on our own fleet for exactly that reason.
|
||||||
|
for (coin, cfg) in [("BTC", &self.chains.btc), ("LTC", &self.chains.ltc)] {
|
||||||
|
if cfg.electrum_fallbacks.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tracing::info!(
|
||||||
|
"{coin}: {} third-party Electrum fallback(s) configured. If your own \
|
||||||
|
Electrum server becomes unreachable, address queries will go to \
|
||||||
|
them instead. Set {coin}_ELECTRUM_FALLBACKS= (empty) to fail \
|
||||||
|
closed and keep every query on infrastructure you control.",
|
||||||
|
cfg.electrum_fallbacks.len()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Public tips escrow on-chain and deliver by share URL, so an instance
|
// Public tips escrow on-chain and deliver by share URL, so an instance
|
||||||
// with FEATURE_TIPS on but no chain to escrow on, or no TIP_SHARE_BASE_URL
|
// with FEATURE_TIPS on but no chain to escrow on, or no TIP_SHARE_BASE_URL
|
||||||
// to build share links from, would advertise a tips subsystem it cannot
|
// to build share links from, would advertise a tips subsystem it cannot
|
||||||
|
|||||||
Reference in New Issue
Block a user