From 5990f12f33db32f9693dfe56eb1139db6fb2d07c Mon Sep 17 00:00:00 2001 From: benk10 Date: Mon, 21 Dec 2020 13:49:57 +0200 Subject: [PATCH] feature: Tor settings and tor_only mode (#765) * Fix #634 * Fix #317 * Reorganize tor pannel * Fix the test * Specify block explorer explicitly on rescan utxo * New Tor settings tab * Tor settings admin only (also open HWI Bridge settings) * Update tor.md * Docs and small fixes * delete leftover code --- docs/tor.md | 6 +- src/cryptoadvance/specter/cli/cli_server.py | 11 +- src/cryptoadvance/specter/helpers.py | 17 ++ src/cryptoadvance/specter/hwi_server.py | 8 +- src/cryptoadvance/specter/rpc.py | 29 +++- src/cryptoadvance/specter/server.py | 2 +- .../specter/server_endpoints/controller.py | 41 +---- .../specter/server_endpoints/settings.py | 92 +++++++++++ .../specter/server_endpoints/wallets.py | 8 +- src/cryptoadvance/specter/specter.py | 73 ++++++++- .../specter/templates/base.jinja | 2 +- .../templates/components/tor_address.jinja | 154 ------------------ .../specter/templates/includes/tool-tip.html | 101 ++++++++++++ .../settings/components/settings_menu.jinja | 5 +- .../templates/settings/tor_settings.jinja | 76 +++++++++ .../wallet/new_wallet/new_wallet_keys.jinja | 25 ++- .../wallet/settings/wallet_settings.jinja | 36 ++-- .../specter/util/price_providers.py | 6 +- src/cryptoadvance/specter/util/tor.py | 18 ++ src/cryptoadvance/specter/util/version.py | 15 +- src/cryptoadvance/specter/wallet.py | 38 +---- tests/test_controller.py | 3 + 22 files changed, 479 insertions(+), 287 deletions(-) delete mode 100644 src/cryptoadvance/specter/templates/components/tor_address.jinja create mode 100644 src/cryptoadvance/specter/templates/includes/tool-tip.html create mode 100644 src/cryptoadvance/specter/templates/settings/tor_settings.jinja diff --git a/docs/tor.md b/docs/tor.md index 9e8bcda28..020174e52 100644 --- a/docs/tor.md +++ b/docs/tor.md @@ -12,8 +12,12 @@ Make sure authentication is enabled to avoid access to your Specter by random st ### Security note Tor support, like Specter Desktop as a whole, should be treated as a work-in-progress that is not yet vetted as being fully secure. +### Setting up Tor using the Tor Browser +The easiest way to use Tor with Specter is to have the [Tor Browser](https://www.torproject.org/download/) open. Just install it on your computer, open it and it will expose a Tor proxy Specter can connect to. +To set this up, you'll just need to go to Specter's Settings -> Tor tab, then set the Tor Proxy field to: `socks5://127.0.0.1:9150` (you'll see it listed below the field as the Tor Browser default URL). Then click save and Specter should be working with Tor - just make sure to keep your Tor Browser running while using Specter. + ### Install Tor service -Install Tor on the same server that you'll be running Specter Desktop: +Alternatively, you can setup the Tor service. Install Tor on the same server that you'll be running Specter Desktop: * [Debian / Ubuntu](https://2019.www.torproject.org/docs/debian.html.en) * [macOS](https://2019.www.torproject.org/docs/tor-doc-osx.html.en) diff --git a/src/cryptoadvance/specter/cli/cli_server.py b/src/cryptoadvance/specter/cli/cli_server.py index 730a98dba..6fe65b8c0 100644 --- a/src/cryptoadvance/specter/cli/cli_server.py +++ b/src/cryptoadvance/specter/cli/cli_server.py @@ -9,6 +9,7 @@ from socket import gethostname import click from OpenSSL import SSL, crypto from stem.control import Controller +from urllib.parse import urlparse from ..server import create_app, init_app from ..util.tor import start_hidden_service, stop_hidden_services @@ -195,7 +196,15 @@ def server( # debug is false by default def run(debug=debug): try: - app.controller = Controller.from_port() + tor_control_address = urlparse(app.specter.proxy_url).netloc.split(":")[0] + if tor_control_address == "localhost": + tor_control_address = "127.0.0.1" + app.controller = Controller.from_port( + address=tor_control_address, + port=int(app.specter.tor_control_port) + if app.specter.tor_control_port + else "default", + ) except Exception: app.controller = None try: diff --git a/src/cryptoadvance/specter/helpers.py b/src/cryptoadvance/specter/helpers.py index 72b39f48a..ce25ac8ea 100644 --- a/src/cryptoadvance/specter/helpers.py +++ b/src/cryptoadvance/specter/helpers.py @@ -296,3 +296,20 @@ def notify_upgrade(app, flash): "info", ) return app.specter.version.current + + +def is_ip_private(ip): + # https://en.wikipedia.org/wiki/Private_network + priv_lo = re.compile("^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$") + priv_24 = re.compile("^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$") + priv_20 = re.compile("^192\.168\.\d{1,3}.\d{1,3}$") + priv_16 = re.compile("^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$") + + res = ( + ip == "localhost" + or priv_lo.match(ip) + or priv_24.match(ip) + or priv_20.match(ip) + or priv_16.match(ip) + ) + return res is not None diff --git a/src/cryptoadvance/specter/hwi_server.py b/src/cryptoadvance/specter/hwi_server.py index bfc969215..68ebd87f7 100644 --- a/src/cryptoadvance/specter/hwi_server.py +++ b/src/cryptoadvance/specter/hwi_server.py @@ -93,12 +93,10 @@ def api(): 500, ) data["forwarded_request"] = True - requests_session = requests.Session() + requests_session = app.specter.requests_session( + force_tor=".onion/" in app.specter.hwi_bridge_url + ) requests_session.headers.update({"origin": request.environ["HTTP_ORIGIN"]}) - if ".onion/" in app.specter.hwi_bridge_url: - requests_session.proxies = {} - requests_session.proxies["http"] = "socks5h://localhost:9050" - requests_session.proxies["https"] = "socks5h://localhost:9050" forwarded_request = requests_session.post( app.specter.hwi_bridge_url, data=json.dumps(data) ) diff --git a/src/cryptoadvance/specter/rpc.py b/src/cryptoadvance/specter/rpc.py index 7b2d5e339..3c667dd56 100644 --- a/src/cryptoadvance/specter/rpc.py +++ b/src/cryptoadvance/specter/rpc.py @@ -1,6 +1,7 @@ import logging import requests, json, os import os, sys, errno +from .helpers import is_ip_private logger = logging.getLogger(__name__) @@ -137,7 +138,12 @@ def detect_rpc_confs_via_env(): return rpc_arr -def autodetect_rpc_confs(datadir=get_default_datadir(), port=None): +def autodetect_rpc_confs( + datadir=get_default_datadir(), + port=None, + proxy_url="socks5h://localhost:9050", + only_tor=False, +): """Returns an array of valid and working configurations which got autodetected. autodetection checks env-vars and bitcoin-data-dirs @@ -152,7 +158,9 @@ def autodetect_rpc_confs(datadir=get_default_datadir(), port=None): available_conf_arr = [] if len(conf_arr) > 0: for conf in conf_arr: - rpc = BitcoinRPC(**conf) + rpc = BitcoinRPC( + **conf, proxy_url="socks5h://localhost:9050", only_tor=False + ) if port is not None: if int(rpc.port) != port: continue @@ -209,6 +217,8 @@ class BitcoinRPC: path="", timeout=None, session=None, + proxy_url="socks5h://localhost:9050", + only_tor=False, **kwargs, ): path = path.replace("//", "/") # just in case @@ -219,15 +229,18 @@ class BitcoinRPC: self.host = host self.path = path self.timeout = timeout + self.proxy_url = (proxy_url,) + self.only_tor = (only_tor,) self.r = None # session reuse speeds up requests if session is None: session = requests.Session() # check if we need to connect over Tor - if ".onion" in self.host: - # configure Tor proxies - session.proxies["http"] = "socks5h://localhost:9050" - session.proxies["https"] = "socks5h://localhost:9050" + if not is_ip_private(host): + if only_tor or ".onion" in self.host: + # configure Tor proxies + session.proxies["http"] = proxy_url + session.proxies["https"] = proxy_url self.session = session def wallet(self, name=""): @@ -240,6 +253,8 @@ class BitcoinRPC: path="{}/wallet/{}".format(self.path, name), timeout=self.timeout, session=self.session, + proxy_url=self.proxy_url, + only_tor=self.only_tor, ) @property @@ -270,6 +285,8 @@ class BitcoinRPC: self.path, self.timeout, self.session, + self.proxy_url, + self.only_tor, ) def multi(self, calls: list, **kwargs): diff --git a/src/cryptoadvance/specter/server.py b/src/cryptoadvance/specter/server.py index e10350ea5..af9b6a988 100644 --- a/src/cryptoadvance/specter/server.py +++ b/src/cryptoadvance/specter/server.py @@ -59,7 +59,7 @@ def init_app(app, hwibridge=False, specter=None): # version checker # checks for new versions once per hour - specter.version = VersionChecker() + specter.version = VersionChecker(specter=specter) specter.version.start() login_manager = LoginManager() diff --git a/src/cryptoadvance/specter/server_endpoints/controller.py b/src/cryptoadvance/specter/server_endpoints/controller.py index 901f8e25f..fb1c7b375 100644 --- a/src/cryptoadvance/specter/server_endpoints/controller.py +++ b/src/cryptoadvance/specter/server_endpoints/controller.py @@ -1,4 +1,4 @@ -import random, traceback +import random, traceback, socket from datetime import datetime from flask import ( @@ -74,45 +74,6 @@ def inject_debug(): return dict(debug=app.config["DEBUG"]) -@app.context_processor -def inject_tor(): - if app.config["DEBUG"]: - return dict(tor_service_id="", tor_enabled=False) - if ( - request.args.get("action", "") == "stoptor" - or request.args.get("action", "") == "starttor" - ): - if hasattr(current_user, "is_admin") and current_user.is_admin: - try: - current_hidden_services = ( - app.controller.list_ephemeral_hidden_services() - ) - except Exception: - current_hidden_services = [] - if ( - request.args.get("action", "") == "stoptor" - and len(current_hidden_services) != 0 - ): - stop_hidden_services(app) - if ( - request.args.get("action", "") == "starttor" - and len(current_hidden_services) == 0 - ): - try: - start_hidden_service(app) - except Exception as e: - flash( - "Failed to start Tor hidden service.\ -Make sure you have Tor running with ControlPort configured and try again.\ -Error returned: {}".format( - e - ), - "error", - ) - return dict(tor_service_id="", tor_enabled=False) - return dict(tor_service_id=app.tor_service_id, tor_enabled=app.tor_enabled) - - ################ Specter global routes #################### @app.route("/") @login_required diff --git a/src/cryptoadvance/specter/server_endpoints/settings.py b/src/cryptoadvance/specter/server_endpoints/settings.py index ea0e8bb87..141766e54 100644 --- a/src/cryptoadvance/specter/server_endpoints/settings.py +++ b/src/cryptoadvance/specter/server_endpoints/settings.py @@ -22,6 +22,7 @@ from ..helpers import ( ) from ..persistence import write_devices, write_wallet from ..user import hash_password +from ..util.tor import start_hidden_service, stop_hidden_services rand = random.randint(0, 1e32) # to force style refresh @@ -233,6 +234,97 @@ This may take a few hours to complete.", ) +@settings_endpoint.route("/tor", methods=["GET", "POST"]) +@login_required +def tor(): + """ + controls the tor related settings + GET for displaying the page, POST for updates + param action might be "save", "test_tor" or "toggle_hidden_service" + param proxy_url the Tor deamon url, usually something like socks5h://localhost:9050 + param only_tor "on" or something else ("off") + """ + if not current_user.is_admin: + flash("Only an admin is allowed to access this page.", "error") + return redirect("") + current_version = notify_upgrade(app, flash) + proxy_url = app.specter.proxy_url + only_tor = app.specter.only_tor + tor_control_port = app.specter.tor_control_port + if request.method == "POST": + action = request.form["action"] + proxy_url = request.form["proxy_url"] + only_tor = request.form.get("only_tor") == "on" + tor_control_port = request.form["tor_control_port"] + + if action == "save": + app.specter.update_proxy_url(proxy_url, current_user) + app.specter.update_only_tor(only_tor, current_user) + app.specter.update_tor_control_port(tor_control_port, current_user) + app.specter.check() + elif action == "test_tor": + try: + requests_session = requests.Session() + requests_session.proxies["http"] = proxy_url + requests_session.proxies["https"] = proxy_url + res = requests_session.get( + "http://expyuzz4wqqyqhjn.onion", # Tor Project onion website + ) + tor_connectable = res.status_code == 200 + if tor_connectable: + flash("Tor requests test completed successfully!", "info") + else: + flash("Failed to make test request over Tor.", "error") + except Exception as e: + flash("Failed to make test request over Tor. Error: %s" % e, "error") + tor_connectable = False + elif action == "toggle_hidden_service": + if not app.config["DEBUG"]: + if app.specter.config.get("auth", "none") == "none": + flash( + "Enabling Tor hidden service will expose your Specter for remote access.
It is therefore required that you set up authentication tab for Specter first to prevent unauthorized access.

Please go to Settings -> Authentication and set up an authentication method and retry.", + "error", + ) + else: + if hasattr(current_user, "is_admin") and current_user.is_admin: + try: + current_hidden_services = ( + app.controller.list_ephemeral_hidden_services() + ) + except Exception: + current_hidden_services = [] + if len(current_hidden_services) != 0: + stop_hidden_services(app) + flash("Tor hidden service turn off successfully", "info") + else: + try: + start_hidden_service(app) + flash("Tor hidden service turn on successfully", "info") + except Exception as e: + flash( + "Failed to start Tor hidden service. Make sure you have Tor running with ControlPort configured and try again. Error returned: {}".format( + e + ), + "error", + ) + else: + flash( + "Can't toggle hidden service while Specter is running in DEBUG mode", + "error", + ) + + return render_template( + "settings/tor_settings.jinja", + proxy_url=proxy_url, + only_tor=only_tor, + tor_control_port=tor_control_port, + tor_service_id=app.tor_service_id, + specter=app.specter, + current_version=current_version, + rand=rand, + ) + + @settings_endpoint.route("/auth", methods=["GET", "POST"]) @login_required def auth(): diff --git a/src/cryptoadvance/specter/server_endpoints/wallets.py b/src/cryptoadvance/specter/server_endpoints/wallets.py index 9d1ad010a..4a537c7ca 100644 --- a/src/cryptoadvance/specter/server_endpoints/wallets.py +++ b/src/cryptoadvance/specter/server_endpoints/wallets.py @@ -370,8 +370,8 @@ def new_wallet(wallet_type): if "utxo" in request.form.get("full_rescan_option"): explorer = None if "use_explorer" in request.form: - explorer = app.specter.get_default_explorer() - wallet.rescanutxo(explorer) + explorer = request.form["explorer_url"] + wallet.rescanutxo(explorer, app.specter.requests_session(explorer)) app.specter.info["utxorescan"] = 1 app.specter.utxorescanwallet = wallet.alias else: @@ -793,8 +793,8 @@ def settings(wallet_alias): elif action == "rescanutxo": explorer = None if "use_explorer" in request.form: - explorer = app.specter.get_default_explorer() - wallet.rescanutxo(explorer) + explorer = request.form["explorer_url"] + wallet.rescanutxo(explorer, app.specter.requests_session(explorer)) app.specter.info["utxorescan"] = 1 app.specter.utxorescanwallet = wallet.alias elif action == "abortrescanutxo": diff --git a/src/cryptoadvance/specter/specter.py b/src/cryptoadvance/specter/specter.py index 950c75053..d6c119ddb 100644 --- a/src/cryptoadvance/specter/specter.py +++ b/src/cryptoadvance/specter/specter.py @@ -6,6 +6,7 @@ import traceback import random import time import zipfile +import requests from io import BytesIO from .helpers import deep_update, clean_psbt, is_testnet from .util.checker import Checker @@ -24,7 +25,13 @@ import threading logger = logging.getLogger(__name__) -def get_rpc(conf, old_rpc=None, return_broken_instead_none=False): +def get_rpc( + conf, + old_rpc=None, + return_broken_instead_none=False, + proxy_url="socks5h://localhost:9050", + only_tor=False, +): """ Checks if config have changed, compares with old rpc and returns new one if necessary @@ -44,7 +51,7 @@ def get_rpc(conf, old_rpc=None, return_broken_instead_none=False): datadir=os.path.expanduser(conf["datadir"]) ) if len(rpc_conf_arr) > 0: - rpc = BitcoinRPC(**rpc_conf_arr[0]) + rpc = BitcoinRPC(**rpc_conf_arr[0], proxy_url=proxy_url, only_tor=only_tor) else: # if autodetect is disabled and port is not defined # we use default port 8332 @@ -109,6 +116,9 @@ class Specter: }, "auth": "none", "explorers": {"main": "", "test": "", "regtest": "", "signet": ""}, + "proxy_url": "socks5h://localhost:9050", # Tor proxy URL + "only_tor": False, + "tor_control_port": "", "hwi_bridge_url": "/hwi/api/", # unique id that will be used in wallets path in Bitcoin Core # empty by default for backward-compatibility @@ -150,7 +160,12 @@ class Specter: # update rpc if something doesn't work rpc = self.rpc if rpc is None or not rpc.test_connection(): - rpc = get_rpc(self.config["rpc"], self.rpc) + rpc = get_rpc( + self.config["rpc"], + self.rpc, + proxy_url=self.proxy_url, + only_tor=self.only_tor, + ) # if rpc is not available # do checks more often, once in 20 seconds @@ -334,7 +349,13 @@ class Specter: def test_rpc(self, **kwargs): conf = copy.deepcopy(self.config["rpc"]) conf.update(kwargs) - rpc = get_rpc(conf, return_broken_instead_none=True) + + rpc = get_rpc( + conf, + return_broken_instead_none=True, + proxy_url=self.proxy_url, + only_tor=self.only_tor, + ) if rpc is None: return {"out": "", "err": "autodetect failed", "code": -1} r = {} @@ -399,7 +420,12 @@ class Specter: self.config["rpc"][k] = kwargs[k] need_update = True if need_update: - self.rpc = get_rpc(self.config["rpc"], None) + self.rpc = get_rpc( + self.config["rpc"], + None, + proxy_url=self.proxy_url, + only_tor=self.only_tor, + ) self._save() self.check(check_all=True) return self.rpc is not None @@ -427,6 +453,24 @@ class Specter: else: user.set_explorer(self, explorer) + def update_proxy_url(self, proxy_url, user): + """ update the Tor proxy url """ + if self.config["proxy_url"] != proxy_url: + self.config["proxy_url"] = proxy_url + self._save() + + def update_only_tor(self, only_tor, user): + """ switch whatever to use Tor for all calls """ + if self.config["only_tor"] != only_tor: + self.config["only_tor"] = only_tor + self._save() + + def update_tor_control_port(self, tor_control_port, user): + """ set the control port of the tor daemon """ + if self.config["tor_control_port"] != tor_control_port: + self.config["tor_control_port"] = tor_control_port + self._save() + def update_hwi_bridge_url(self, url, user): """ update the hwi bridge url to use """ user = self.user_manager.get_user(user) @@ -587,6 +631,18 @@ class Specter: def explorer(self): return self.user_config.get("explorers", {}).get(self.chain, "") + @property + def proxy_url(self): + return self.user_config.get("proxy_url", "socks5h://localhost:9050") + + @property + def only_tor(self): + return self.user_config.get("only_tor", False) + + @property + def tor_control_port(self): + return self.user_config.get("tor_control_port", "") + @property def hwi_bridge_url(self): return self.user_config.get("hwi_bridge_url", "") @@ -629,6 +685,13 @@ class Specter: def wallet_manager(self): return self.user.wallet_manager + def requests_session(self, force_tor=False): + requests_session = requests.Session() + if self.only_tor or force_tor: + requests_session.proxies["http"] = self.proxy_url + requests_session.proxies["https"] = self.proxy_url + return requests_session + def specter_backup_file(self): memory_file = BytesIO() with zipfile.ZipFile(memory_file, "w") as zf: diff --git a/src/cryptoadvance/specter/templates/base.jinja b/src/cryptoadvance/specter/templates/base.jinja index 6a01b541e..cbc92070d 100644 --- a/src/cryptoadvance/specter/templates/base.jinja +++ b/src/cryptoadvance/specter/templates/base.jinja @@ -23,6 +23,7 @@ {% include "includes/qr-code.html" %} {% endif %} {% include "includes/message-box.html" %} + {% include "includes/tool-tip.html" %}
{% block sidebar %} {% include "includes/sidebar/sidebar.jinja" %} @@ -31,7 +32,6 @@ {% if current_user.is_authenticated and not hwi_bridge %}
{% include "components/price_bar.jinja" %} - {% include "components/tor_address.jinja" %} diff --git a/src/cryptoadvance/specter/templates/components/tor_address.jinja b/src/cryptoadvance/specter/templates/components/tor_address.jinja deleted file mode 100644 index 9258c8985..000000000 --- a/src/cryptoadvance/specter/templates/components/tor_address.jinja +++ /dev/null @@ -1,154 +0,0 @@ - - -
- - -
- \ No newline at end of file diff --git a/src/cryptoadvance/specter/templates/includes/tool-tip.html b/src/cryptoadvance/specter/templates/includes/tool-tip.html new file mode 100644 index 000000000..fc8579301 --- /dev/null +++ b/src/cryptoadvance/specter/templates/includes/tool-tip.html @@ -0,0 +1,101 @@ + + + \ No newline at end of file diff --git a/src/cryptoadvance/specter/templates/settings/components/settings_menu.jinja b/src/cryptoadvance/specter/templates/settings/components/settings_menu.jinja index bef579aa6..7015296c2 100644 --- a/src/cryptoadvance/specter/templates/settings/components/settings_menu.jinja +++ b/src/cryptoadvance/specter/templates/settings/components/settings_menu.jinja @@ -12,9 +12,10 @@ {{ settings_menu_item('bitcoin_core', 'Bitcoin Core', active_menuitem, isLeft=true) }} {% endif %} {{ settings_menu_item('general', 'General', active_menuitem, isLeft=(not current_user.is_admin)) }} - {{ settings_menu_item('auth', 'Authentication', active_menuitem, isRight=not current_user.is_admin) }} + {{ settings_menu_item('auth', 'Authentication', active_menuitem, isRight=false) }} + {{ settings_menu_item('hwi', 'HWI Bridge', active_menuitem, isRight=(not current_user.is_admin)) }} {% if current_user.is_admin %} - {{ settings_menu_item('hwi', 'HWI Bridge', active_menuitem, isRight=true) }} + {{ settings_menu_item('tor', 'Tor', active_menuitem, isRight=true) }} {% endif %} diff --git a/src/cryptoadvance/specter/templates/settings/tor_settings.jinja b/src/cryptoadvance/specter/templates/settings/tor_settings.jinja new file mode 100644 index 000000000..3345df22a --- /dev/null +++ b/src/cryptoadvance/specter/templates/settings/tor_settings.jinja @@ -0,0 +1,76 @@ +{% extends "base.jinja" %} +{% block main %} +
+

Tor settings - Specter Desktop {{ current_version }}

+ {% from 'settings/components/settings_menu.jinja' import settings_menu %} + {{ settings_menu('tor', current_user) }} +
+

+ + Tor configurations +

+ Use Tor proxy running at: + +
+

+ Default for Tor daemon: socks5://127.0.0.1:9050
+ Default for Tor Browser: socks5://127.0.0.1:9150 +

+ Tor control port: +

+ Restart Specter for change of the control port to take effect. +

+ +

+ Do outside calls only over Tor? + + Some optional Specter functionalities, like rescanning UTXO on a pruned node, or getting the Bitcoin price, might make calls to external APIs and services.

+ Toggle this on to ensure Specter routes all these external calls over Tor proxy.

+ Note: Some external sources may stop working if they block Tor call. +
+

+ Toggle this on to ensure Specter routes all calls external over Tor proxy. +

+
+ +

+
+   + +


+ {% if not debug %} +

Tor Hidden Service

+

Running Specter behind a Tor hidden service allows you to acccess Specter over Tor from anywhere.
+

+ {% if tor_service_id %} + {% if specter.config.auth == "none" %} +

+ ⚠️ Warning!
+ Your are running Specter over Tor with no authentication settings configured. + This means your Specter instance is accessible to anyone with the .onion URL. + This .onion URL is publicly exposed and indexed on the Tor network - it is not secret!

+ It is stronly adviced that you configure proper authentication while running Specter behind a Tor hidden service. + Please go to Settings -> Authentication and set up an authentication method. +

+ {% endif %} +

+ Specter hidden service is running at: + + {{ tor_service_id }}.onion + +

+ {% endif %} +
+ +

+ {% endif %} +
+
+{% endblock %} +{% block scripts %} +{% endblock %} diff --git a/src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja b/src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja index afb9055d7..db6e33539 100644 --- a/src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja +++ b/src/cryptoadvance/specter/templates/wallet/new_wallet/new_wallet_keys.jinja @@ -85,23 +85,22 @@
@@ -238,7 +237,7 @@ let utxocheckbox = document.getElementById("use_explorer"); if(utxocheckbox){ utxocheckbox.addEventListener('change', e=>{ - let el = document.getElementById("utxo-warning") + let el = document.getElementById("utxo-explorer") if(utxocheckbox.checked){ el.style.display = "inline-block"; }else{ diff --git a/src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja b/src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja index ecbba3ea7..68b574895 100644 --- a/src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja +++ b/src/cryptoadvance/specter/templates/wallet/settings/wallet_settings.jinja @@ -207,31 +207,29 @@ {% if specter.info['pruned'] %}
- - ⓘ
Careful with block explorers!
- This may have privacy implication!
- Information fetched from the block explorer contains a list of unspent transactions of your wallet from old (pruned) blocks.
- "They" will know what transactions you are interested in. -
+
+
+ Block explorer URL: + + + ⓘ
Careful with block explorers!
+ This may have privacy implication!
+ Information fetched from the block explorer contains a list of unspent transactions of your wallet from old (pruned) blocks.
+ "They" will know what transactions you are interested in. +
+