From c00e41f76438b67a44bfafd9bf14b2bf1d8d69a7 Mon Sep 17 00:00:00 2001 From: benk10 Date: Fri, 19 Mar 2021 13:31:01 +0200 Subject: [PATCH] Feature: Setup Bitcoin Core from Specter (#1007) * Package bitcoind with specter WIP * fixes * Setup wizard * Fix non default datadir * Update bitcoind.py * Data folder config * UI and text fixes * Tor setup (macOS) * Tor setup Windows and Linux support * Wizard! * action btns * About page update * Tor controller * Update specter.py * tor_controller getter * Fix wizard bug * Fix wallet json export backup * remove docker dependency for main * refactoring docker-requirement out of the way * fix import * Fix bitcoind docker issue * Update tor_daemon.py * latest pruned node * Tor options and fixes * Fix bitcoind for wondows * Windows process stop fixes * Moar windows fix attempts * Fix exit windows * Update src/cryptoadvance/specter/cli/cli_server.py Co-authored-by: Kim Neunert * Cleanups * Cleanups * Add Bitcoin Core Tor support * Update specter bitcoind and tord * Small UI update Co-authored-by: Kim Neunert Co-authored-by: Kim Neunert --- pyinstaller/electron/main.js | 39 +- pyinstaller/electron/package-lock.json | 284 +------ pyinstaller/electron/package.json | 1 - requirements.in | 1 + requirements.txt | 10 + src/cryptoadvance/specter/bitcoind.py | 240 +----- src/cryptoadvance/specter/bitcoind_docker.py | 193 +++++ src/cryptoadvance/specter/cli/cli_bitcoind.py | 4 +- src/cryptoadvance/specter/cli/cli_server.py | 21 +- src/cryptoadvance/specter/config.py | 1 + .../specter/server_endpoints/controller.py | 137 ++- .../specter/server_endpoints/settings.py | 100 ++- .../specter/server_endpoints/wallets.py | 4 +- src/cryptoadvance/specter/specter.py | 136 ++- .../specter/static/bitcoin-release-pubkey.asc | 784 ++++++++++++++++++ .../specter/static/img/party.png | Bin 0 -> 35241 bytes .../pruned-node-today-release-pubkey.asc | 12 + .../static/torbrowser-release-pubkey.asc | 332 ++++++++ .../specter/templates/base.jinja | 14 +- .../templates/includes/address-label.html | 6 +- .../specter/templates/node_setup_wizard.jinja | 365 ++++++++ .../settings/bitcoin_core_settings.jinja | 58 +- .../templates/settings/tor_settings.jinja | 95 +++ .../export_wallet_account_map.jinja | 3 +- src/cryptoadvance/specter/tor_daemon.py | 51 ++ .../specter/util/bitcoind_setup_tasks.py | 199 +++++ .../specter/util/error_handling.py | 15 + .../specter/util/file_download.py | 23 + src/cryptoadvance/specter/util/rpcauth.py | 55 ++ src/cryptoadvance/specter/util/sha256sum.py | 11 + src/cryptoadvance/specter/util/tor.py | 28 +- .../specter/util/tor_setup_tasks.py | 132 +++ tests/conftest.py | 4 +- tests/test_bitcoind.py | 4 +- 34 files changed, 2828 insertions(+), 534 deletions(-) create mode 100644 src/cryptoadvance/specter/bitcoind_docker.py create mode 100644 src/cryptoadvance/specter/static/bitcoin-release-pubkey.asc create mode 100644 src/cryptoadvance/specter/static/img/party.png create mode 100644 src/cryptoadvance/specter/static/pruned-node-today-release-pubkey.asc create mode 100644 src/cryptoadvance/specter/static/torbrowser-release-pubkey.asc create mode 100644 src/cryptoadvance/specter/templates/node_setup_wizard.jinja create mode 100644 src/cryptoadvance/specter/tor_daemon.py create mode 100644 src/cryptoadvance/specter/util/bitcoind_setup_tasks.py create mode 100644 src/cryptoadvance/specter/util/error_handling.py create mode 100644 src/cryptoadvance/specter/util/file_download.py create mode 100644 src/cryptoadvance/specter/util/rpcauth.py create mode 100644 src/cryptoadvance/specter/util/sha256sum.py create mode 100644 src/cryptoadvance/specter/util/tor_setup_tasks.py diff --git a/pyinstaller/electron/main.js b/pyinstaller/electron/main.js index 00866b68a..6443a7994 100644 --- a/pyinstaller/electron/main.js +++ b/pyinstaller/electron/main.js @@ -67,18 +67,6 @@ let webPreferences = { app.commandLine.appendSwitch('ignore-certificate-errors'); -try { - require( - '@deadcanaries/granax')({}, { - 'SocksPort': 9050, - 'ControlPort': 9051 - }).on('error', function () { - // Tor is probably running, ignore... - }) -} catch(e) { - // Tor is probably running, ignore... -} - let platformName = '' switch (process.platform) { case 'darwin': @@ -181,8 +169,13 @@ function initMainWindow(specterURL) { }); mainWindow.on('close', function (event) { - event.preventDefault(); - mainWindow.hide(); + if(platformName == 'win64') { + quitSpecterd() + app.quit() + } else { + event.preventDefault(); + mainWindow.hide(); + } }); mainWindow.webContents.on("did-fail-load", function() { @@ -276,9 +269,11 @@ function startSpecterd(specterdPath) { specterdArgs = specterdArgs.concat(specterdExtraArgs) } specterdProcess = spawn(specterdPath, specterdArgs); - specterdProcess.stdout.on('data', (_) => { - if (mainWindow) { - createWindow(appSettings.specterURL) + specterdProcess.stdout.on('data', (data) => { + if(data.toString().includes('Serving Flask app "cryptoadvance.specter.server"')) { + if (mainWindow) { + createWindow(appSettings.specterURL) + } } }); specterdProcess.stderr.on('data', function(_) { @@ -298,6 +293,13 @@ function startSpecterd(specterdPath) { }); } +app.on('window-all-closed', function(){ + if(platformName == 'win64') { + quitSpecterd() + app.quit() + } +}); + app.on('before-quit', () => { if (!quitted) { quitted = true @@ -337,7 +339,8 @@ function quitSpecterd() { if (specterdProcess) { try { if (platformName == 'win64') { - exec('taskkill -F -T -PID ' + specterdProcess.pid); + exec('taskkill /F /T /PID ' + specterdProcess.pid); + exec('taskkill /IM specterd.exe '); process.kill(-specterdProcess.pid) } specterdProcess.kill('SIGINT') diff --git a/pyinstaller/electron/package-lock.json b/pyinstaller/electron/package-lock.json index d15375e6b..17996d588 100644 --- a/pyinstaller/electron/package-lock.json +++ b/pyinstaller/electron/package-lock.json @@ -4,44 +4,12 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "7zip": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/7zip/-/7zip-0.0.6.tgz", - "integrity": "sha1-nK+xca+CMpSQNTtIFvAzR6oVCjA=", - "optional": true - }, "7zip-bin": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.0.3.tgz", "integrity": "sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA==", "dev": true }, - "@deadcanaries/granax": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/@deadcanaries/granax/-/granax-3.2.5.tgz", - "integrity": "sha512-umsEYedNQWLSlkDnGynR8bY0pVWq2hKN1JLtV9Jit7srYHqdo+XIEsUNejq1nNBiX83WhUZVe4gOqvg8ovdMMQ==", - "requires": { - "7zip": "0.0.6", - "async": "^2.3.0", - "latest-torbrowser-version": "^2.0.2", - "merge": "^1.2.1", - "mkdirp": "^0.5.1", - "mv": "^2.1.1", - "ncp": "^2.0.0", - "progress": "^2.0.3", - "rimraf": "^2.6.3" - }, - "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } - } - } - }, "@develar/schema-utils": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", @@ -336,7 +304,8 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -361,11 +330,6 @@ "bluebird": "^3.5.5" } }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" - }, "boolean": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.2.tgz", @@ -411,6 +375,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -551,19 +516,6 @@ "supports-color": "^7.1.0" } }, - "cheerio": { - "version": "1.0.0-rc.3", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", - "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.1", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash": "^4.15.0", - "parse5": "^3.0.1" - } - }, "chromium-pickle-js": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", @@ -652,7 +604,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", @@ -709,22 +662,6 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -828,37 +765,6 @@ } } }, - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -1093,11 +999,6 @@ "once": "^1.4.0" } }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" - }, "env-paths": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", @@ -1226,11 +1127,6 @@ "trim-repeated": "^1.0.0" } }, - "follow-redirects": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", - "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==" - }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -1257,11 +1153,6 @@ "universalify": "^0.1.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1285,18 +1176,6 @@ "assert-plus": "^1.0.0" } }, - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "global-agent": { "version": "2.1.12", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.1.12.tgz", @@ -1405,31 +1284,6 @@ "lru-cache": "^6.0.0" } }, - "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -1467,19 +1321,11 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "ini": { "version": "1.3.8", @@ -1707,32 +1553,6 @@ "json-buffer": "3.0.0" } }, - "latest-torbrowser-version": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/latest-torbrowser-version/-/latest-torbrowser-version-2.0.3.tgz", - "integrity": "sha512-+6fkERFLxo2QiNn7x0txjEF199tG4CGVI9X101d7IuZAapO/hGOC+nHD9BEPNNaMqmvIUkT/o3CdZ+NS5wX/iQ==", - "requires": { - "async": "^2.6.0", - "cheerio": "^1.0.0-rc.2", - "follow-redirects": "^1.2.4", - "semver": "^5.4.1" - }, - "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, "latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -1751,7 +1571,9 @@ "lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true, + "optional": true }, "lowercase-keys": { "version": "1.0.1", @@ -1804,11 +1626,6 @@ } } }, - "merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==" - }, "mime": { "version": "2.4.6", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", @@ -1838,6 +1655,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -1845,12 +1663,14 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, "requires": { "minimist": "^1.2.5" } @@ -1865,31 +1685,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "mv": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", - "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", - "requires": { - "mkdirp": "~0.5.1", - "ncp": "~2.0.0", - "rimraf": "~2.4.0" - }, - "dependencies": { - "rimraf": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", - "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", - "requires": { - "glob": "^6.0.1" - } - } - } - }, - "ncp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", - "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=" - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -1933,14 +1728,6 @@ "pify": "^3.0.0" } }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "requires": { - "boolbase": "~1.0.0" - } - }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -1987,24 +1774,11 @@ } } }, - "parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", - "requires": { - "@types/node": "*" - } - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -2043,7 +1817,8 @@ "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true }, "proto-list": { "version": "1.2.4", @@ -2193,29 +1968,6 @@ "lowercase-keys": "^1.0.0" } }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, "roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -2451,6 +2203,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -2671,7 +2424,8 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true }, "uuid": { "version": "3.4.0", diff --git a/pyinstaller/electron/package.json b/pyinstaller/electron/package.json index 6d43ca143..3bb62a745 100644 --- a/pyinstaller/electron/package.json +++ b/pyinstaller/electron/package.json @@ -43,7 +43,6 @@ } }, "dependencies": { - "@deadcanaries/granax": "^3.2.5", "electron-context-menu": "^2.3.0", "electron-default-menu": "^1.0.2", "extract-zip": "^2.0.1", diff --git a/requirements.in b/requirements.in index 79917aa13..b107387bf 100644 --- a/requirements.in +++ b/requirements.in @@ -18,3 +18,4 @@ embit==0.1.2 psutil==5.7.3 pyopenssl==20.0.1 flask_wtf==0.14.3 +pgpy==0.5.3 diff --git a/requirements.txt b/requirements.txt index fde12e045..e7cf33a36 100644 --- a/requirements.txt +++ b/requirements.txt @@ -87,6 +87,7 @@ cryptography==3.3.2 \ --hash=sha256:e18e6ab84dfb0ab997faf8cca25a86ff15dfea4027b986322026cc99e0a892da # via # noiseprotocol + # pgpy # pyopenssl daemonize==2.5.0 \ --hash=sha256:9b6b91311a9d934ff3f5f766666635ca280d3de8e7137e4cd7d3f052543b989f \ @@ -207,6 +208,10 @@ noiseprotocol==0.3.1 \ pbkdf2==1.3 \ --hash=sha256:ac6397369f128212c43064a2b4878038dab78dab41875364554aaf2a684e6979 # via mnemonic +pgpy==0.5.3 \ + --hash=sha256:a49c269cedcaf82ac6999bcae5fd3f543ecb1c759f9d48a15ad8d8fa4ac03987 \ + --hash=sha256:cba6fbbb44a896a8a4f5807b3d8d4943a8f7a6607be11587f4a27734c711c1dd + # via -r requirements.in protobuf==3.13.0 \ --hash=sha256:0bba42f439bf45c0f600c3c5993666fcb88e8441d011fad80a11df6f324eef33 \ --hash=sha256:1e834076dfef9e585815757a2c7e4560c7ccc5962b9d09f831214c693a91b463 \ @@ -243,6 +248,10 @@ psutil==5.7.3 \ pyaes==1.6.1 \ --hash=sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f # via hwi +pyasn1==0.4.8 \ + --hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \ + --hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba + # via pgpy pycparser==2.20 \ --hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 \ --hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705 @@ -279,6 +288,7 @@ six==1.12.0 \ # -r requirements.in # cryptography # flask-cors + # pgpy # protobuf # pyopenssl stem==1.8.0 \ diff --git a/src/cryptoadvance/specter/bitcoind.py b/src/cryptoadvance/specter/bitcoind.py index add87c96b..1bcd67453 100644 --- a/src/cryptoadvance/specter/bitcoind.py +++ b/src/cryptoadvance/specter/bitcoind.py @@ -1,5 +1,4 @@ -""" Stuff to control a bitcoind-instance. Either directly by access to a bitcoind-executable or - via docker. +""" Stuff to control a bitcoind-instance. """ import atexit import logging @@ -11,8 +10,8 @@ import subprocess import tempfile import time import json +import platform -import docker from .util.shell import which from .rpc import RpcError @@ -80,8 +79,13 @@ class Btcd_conn: class BitcoindController: """ A kind of abstract class to simplify running a bitcoind with or without docker """ - def __init__(self, rpcport=18443): - self.rpcconn = Btcd_conn(rpcport=rpcport) + def __init__( + self, rpcport=18443, network="regtest", rpcuser="bitcoin", rpcpassword="secret" + ): + self.rpcconn = Btcd_conn( + rpcuser=rpcuser, rpcpassword=rpcpassword, rpcport=rpcport + ) + self.network = network def start_bitcoind( self, cleanup_at_exit=False, cleanup_hard=False, datadir=None, extra_args=[] @@ -103,7 +107,8 @@ class BitcoindController: ) self.wait_for_bitcoind(self.rpcconn) - self.mine(block_count=100) + if self.network == "regtest": + self.mine(block_count=100) return self.rpcconn def version(self): @@ -160,23 +165,24 @@ class BitcoindController: try: rpcconn.get_rpc() # that call will also check the connection return True - except ConnectionRefusedError: + except ConnectionRefusedError as e: return False - except TypeError: + except TypeError as e: return False - except Exception: + except Exception as e: + print(f"couldn't reach bitcoind - message returned: {e}") return False @staticmethod def wait_for_bitcoind(rpcconn): - """ tries to reach the bitcoind via rpc. Will timeout after 10 seconds """ + """ tries to reach the bitcoind via rpc. Will timeout after 30 seconds """ i = 0 while True: if BitcoindController.check_bitcoind(rpcconn): break time.sleep(0.5) i = i + 1 - if i > 20: + if i > 60: raise Exception( "Timeout while trying to reach bitcoind at rpcport {} !".format( rpcconn @@ -197,11 +203,13 @@ class BitcoindController: run_docker=True, datadir=None, bitcoind_path="bitcoind", + network="regtest", extra_args=[], ): """ returns a bitcoind-command to run bitcoind """ - btcd_cmd = "{} ".format(bitcoind_path) - btcd_cmd += " -regtest " + btcd_cmd = '"{}" '.format(bitcoind_path) + if network != "mainnet": + btcd_cmd += " -{} ".format(network) btcd_cmd += " -fallbackfee=0.0002 " btcd_cmd += " -port={} -rpcport={} -rpcbind=0.0.0.0 -rpcbind=0.0.0.0".format( rpcconn.rpcport - 1, rpcconn.rpcport @@ -214,7 +222,7 @@ class BitcoindController: btcd_cmd += " -noprinttoconsole" if datadir == None: datadir = tempfile.mkdtemp(prefix="bitcoind_datadir") - btcd_cmd += " -datadir={} ".format(datadir) + btcd_cmd += ' -datadir="{}" '.format(datadir) if extra_args: btcd_cmd += " {}".format(" ".join(extra_args)) logger.debug("constructed bitcoind-command: %s", btcd_cmd) @@ -222,10 +230,19 @@ class BitcoindController: class BitcoindPlainController(BitcoindController): - """ A class controlling the bicoind-process directly on the machine """ + """ A class controlling the bitcoind-process directly on the machine """ - def __init__(self, bitcoind_path="bitcoind", rpcport=18443): - super().__init__(rpcport=rpcport) + def __init__( + self, + bitcoind_path="bitcoind", + rpcport=18443, + network="regtest", + rpcuser="bitcoin", + rpcpassword="secret", + ): + super().__init__( + rpcport=rpcport, network=network, rpcuser=rpcuser, rpcpassword=rpcpassword + ) self.bitcoind_path = bitcoind_path self.rpcconn.ipaddress = "localhost" @@ -240,11 +257,15 @@ class BitcoindPlainController(BitcoindController): run_docker=False, datadir=datadir, bitcoind_path=self.bitcoind_path, + network=self.network, extra_args=extra_args, ) logger.debug("About to execute: {}".format(bitcoind_cmd)) # exec will prevent creating a child-process and will make bitcoind_proc.terminate() work as expected - self.bitcoind_proc = subprocess.Popen("exec " + bitcoind_cmd, shell=True) + self.bitcoind_proc = subprocess.Popen( + ("exec " if platform.system() != "Windows" else "") + bitcoind_cmd, + shell=True, + ) logger.debug( "Running bitcoind-process with pid {}".format(self.bitcoind_proc.pid) ) @@ -278,6 +299,8 @@ class BitcoindPlainController(BitcoindController): for p in alive: logger.info("bitcoind did not terminated in time, killing!") p.kill() + if platform.system() == "Windows": + subprocess.run("Taskkill /IM bitcoind.exe /F") def stop_bitcoind(self): self.cleanup_bitcoind() @@ -292,187 +315,6 @@ class BitcoindPlainController(BitcoindController): return True -class BitcoindDockerController(BitcoindController): - """ A class specifically controlling a docker-based bitcoind-container """ - - def __init__(self, rpcport=18443, docker_tag="latest"): - self.btcd_container = None - super().__init__(rpcport=rpcport) - self.docker_tag = docker_tag - - if self.detect_bitcoind_container(rpcport) != None: - rpcconn, btcd_container = self.detect_bitcoind_container(rpcport) - logger.debug("Detected old container ... deleting it") - btcd_container.stop() - btcd_container.remove() - - def _start_bitcoind( - self, cleanup_at_exit, cleanup_hard=False, datadir=None, extra_args=[] - ): - if datadir != None: - # ignored - pass - bitcoind_path = self.construct_bitcoind_cmd(self.rpcconn, extra_args=extra_args) - dclient = docker.from_env() - logger.debug("Running (in docker): {}".format(bitcoind_path)) - ports = { - "{}/tcp".format(self.rpcconn.rpcport - 1): self.rpcconn.rpcport - 1, - "{}/tcp".format(self.rpcconn.rpcport): self.rpcconn.rpcport, - } - logger.debug("portmapping: {}".format(ports)) - image = dclient.images.get( - "registry.gitlab.com/cryptoadvance/specter-desktop/python-bitcoind:{}".format( - self.docker_tag - ) - ) - self.btcd_container = dclient.containers.run( - image, - bitcoind_path, - ports=ports, - detach=True, - ) - - def cleanup_docker_bitcoind(*args): - logger.info("Cleaning up bitcoind-docker-container") - self.btcd_container.stop() - self.btcd_container.remove() - - if cleanup_at_exit: - logger.debug( - "Register function cleanup_docker_bitcoind for SIGINT and SIGTERM" - ) - # This is for CTRL-C --> SIGINT - signal.signal(signal.SIGINT, cleanup_docker_bitcoind) - # This is for kill $pid --> SIGTERM - signal.signal(signal.SIGTERM, cleanup_docker_bitcoind) - - logger.debug( - "Waiting for container {} to come up".format(self.btcd_container.id) - ) - self.wait_for_container() - rpcconn, _ = self.detect_bitcoind_container(self.rpcconn.rpcport) - if rpcconn == None: - raise Exception( - "Couldn't find container or it died already. Check the logs!" - ) - else: - self.rpcconn = rpcconn - return - - def stop_bitcoind(self): - if self.btcd_container != None: - self.btcd_container.reload() - if self.btcd_container.status == "running": - _, container = self.detect_bitcoind_container(self.rpcconn.rpcport) - if container == self.btcd_container: - self.btcd_container.stop() - logger.info("Stopped btcd_container {}".format(self.btcd_container)) - self.btcd_container.remove() - return - raise Exception("Ambigious Container running") - - def check_existing(self): - """ Checks whether self.btcd_container is up2date and not ambigious """ - if self.btcd_container != None: - self.btcd_container.reload() - if self.btcd_container.status == "running": - rpcconn, container = self.detect_bitcoind_container( - self.rpcconn.rpcport - ) - if container == self.btcd_container: - return rpcconn - raise Exception("Ambigious Container running") - return None - - @staticmethod - def search_bitcoind_container(all=False): - """ returns a list of containers which are running bitcoind """ - d_client = docker.from_env() - return [ - c - for c in d_client.containers.list(all) - if (c.attrs["Config"].get("Cmd") or [""])[0] == "bitcoind" - ] - - @staticmethod - def detect_bitcoind_container(with_rpcport): - """checks all the containers for a bitcoind one, parses the arguments and initializes - the object accordingly - returns rpcconn, btcd_container - """ - d_client = docker.from_env() - potential_btcd_containers = BitcoindDockerController.search_bitcoind_container() - if len(potential_btcd_containers) == 0: - logger.debug( - "could not detect container. Candidates: {}".format( - d_client.containers.list() - ) - ) - all_candidates = BitcoindDockerController.search_bitcoind_container( - all=True - ) - logger.debug( - "could not detect container. All Candidates: {}".format(all_candidates) - ) - if len(all_candidates) > 0: - logger.debug("100 chars of logs of first candidate") - logger.debug(all_candidates[0].logs()[0:100]) - return None - for btcd_container in potential_btcd_containers: - rpcport = int( - [ - arg - for arg in btcd_container.attrs["Config"]["Cmd"] - if "rpcport" in arg - ][0].split("=")[1] - ) - if rpcport != with_rpcport: - logger.debug( - "checking port {} against searched port {}".format( - type(rpcport), type(with_rpcport) - ) - ) - continue - rpcpassword = [ - arg - for arg in btcd_container.attrs["Config"]["Cmd"] - if "rpcpassword" in arg - ][0].split("=")[1] - rpcuser = [ - arg for arg in btcd_container.attrs["Config"]["Cmd"] if "rpcuser" in arg - ][0].split("=")[1] - if "CI" in os.environ: # this is a predefined variable in gitlab - # This works on Linux (direct docker) and gitlab-CI but not on MAC - ipaddress = btcd_container.attrs["NetworkSettings"]["IPAddress"] - else: - # This works on most machines but not on gitlab-CI - ipaddress = "127.0.0.1" - rpcconn = Btcd_conn( - rpcuser=rpcuser, - rpcpassword=rpcpassword, - rpcport=rpcport, - ipaddress=ipaddress, - ) - logger.info("detected container {}".format(btcd_container.id)) - return rpcconn, btcd_container - logger.debug("No matching container found") - return None - - def wait_for_container(self): - """ waits for the docker-container to come up. Times out after 10 seconds """ - i = 0 - while True: - ip_address = self.btcd_container.attrs["NetworkSettings"]["IPAddress"] - if ip_address.startswith("172"): - self.rpcconn.ipaddress = ip_address - break - self.btcd_container.reload() - time.sleep(0.5) - i = i + 1 - if i > 20: - raise Exception("Timeout while starting bitcoind-docker-container!") - - def fetch_wallet_addresses_for_mining(data_folder): """parses all the wallet-jsons in the folder (default ~/.specter/wallets/regtest) and returns an array with the addresses diff --git a/src/cryptoadvance/specter/bitcoind_docker.py b/src/cryptoadvance/specter/bitcoind_docker.py new file mode 100644 index 000000000..55e0af1c9 --- /dev/null +++ b/src/cryptoadvance/specter/bitcoind_docker.py @@ -0,0 +1,193 @@ +import logging + +# the docker-dependency is special as it's only used with pytest --docker or +# if you manually start bitcoind --docker +# If this fails, you need to pip install the test-requirements +import docker +import os +from .bitcoind import BitcoindController, Btcd_conn +import signal +import time + +logger = logging.getLogger(__name__) + + +class BitcoindDockerController(BitcoindController): + """ A class specifically controlling a docker-based bitcoind-container """ + + def __init__(self, rpcport=18443, docker_tag="latest"): + self.btcd_container = None + super().__init__(rpcport=rpcport) + self.docker_tag = docker_tag + + if self.detect_bitcoind_container(rpcport) != None: + rpcconn, btcd_container = self.detect_bitcoind_container(rpcport) + logger.debug("Detected old container ... deleting it") + btcd_container.stop() + btcd_container.remove() + + def _start_bitcoind( + self, cleanup_at_exit, cleanup_hard=False, datadir=None, extra_args=[] + ): + if datadir != None: + # ignored + pass + bitcoind_path = self.construct_bitcoind_cmd(self.rpcconn, extra_args=extra_args) + dclient = docker.from_env() + logger.debug("Running (in docker): {}".format(bitcoind_path)) + ports = { + "{}/tcp".format(self.rpcconn.rpcport - 1): self.rpcconn.rpcport - 1, + "{}/tcp".format(self.rpcconn.rpcport): self.rpcconn.rpcport, + } + logger.debug("portmapping: {}".format(ports)) + image = dclient.images.get( + "registry.gitlab.com/cryptoadvance/specter-desktop/python-bitcoind:{}".format( + self.docker_tag + ) + ) + self.btcd_container = dclient.containers.run( + image, + bitcoind_path, + ports=ports, + detach=True, + ) + + def cleanup_docker_bitcoind(*args): + logger.info("Cleaning up bitcoind-docker-container") + self.btcd_container.stop() + self.btcd_container.remove() + + if cleanup_at_exit: + logger.debug( + "Register function cleanup_docker_bitcoind for SIGINT and SIGTERM" + ) + # This is for CTRL-C --> SIGINT + signal.signal(signal.SIGINT, cleanup_docker_bitcoind) + # This is for kill $pid --> SIGTERM + signal.signal(signal.SIGTERM, cleanup_docker_bitcoind) + + logger.debug( + "Waiting for container {} to come up".format(self.btcd_container.id) + ) + self.wait_for_container() + rpcconn, _ = self.detect_bitcoind_container(self.rpcconn.rpcport) + if rpcconn == None: + raise Exception( + "Couldn't find container or it died already. Check the logs!" + ) + else: + self.rpcconn = rpcconn + return + + def stop_bitcoind(self): + if self.btcd_container != None: + self.btcd_container.reload() + if self.btcd_container.status == "running": + _, container = self.detect_bitcoind_container(self.rpcconn.rpcport) + if container == self.btcd_container: + self.btcd_container.stop() + logger.info("Stopped btcd_container {}".format(self.btcd_container)) + self.btcd_container.remove() + return + raise Exception("Ambigious Container running") + + def check_existing(self): + """ Checks whether self.btcd_container is up2date and not ambigious """ + if self.btcd_container != None: + self.btcd_container.reload() + if self.btcd_container.status == "running": + rpcconn, container = self.detect_bitcoind_container( + self.rpcconn.rpcport + ) + if container == self.btcd_container: + return rpcconn + raise Exception("Ambigious Container running") + return None + + @staticmethod + def search_bitcoind_container(all=False): + """ returns a list of containers which are running bitcoind """ + d_client = docker.from_env() + return [ + c + for c in d_client.containers.list(all) + if (c.attrs["Config"].get("Cmd") or [""])[0] == "bitcoind" + ] + + @staticmethod + def detect_bitcoind_container(with_rpcport): + """checks all the containers for a bitcoind one, parses the arguments and initializes + the object accordingly + returns rpcconn, btcd_container + """ + d_client = docker.from_env() + potential_btcd_containers = BitcoindDockerController.search_bitcoind_container() + if len(potential_btcd_containers) == 0: + logger.debug( + "could not detect container. Candidates: {}".format( + d_client.containers.list() + ) + ) + all_candidates = BitcoindDockerController.search_bitcoind_container( + all=True + ) + logger.debug( + "could not detect container. All Candidates: {}".format(all_candidates) + ) + if len(all_candidates) > 0: + logger.debug("100 chars of logs of first candidate") + logger.debug(all_candidates[0].logs()[0:100]) + return None + for btcd_container in potential_btcd_containers: + rpcport = int( + [ + arg + for arg in btcd_container.attrs["Config"]["Cmd"] + if "rpcport" in arg + ][0].split("=")[1] + ) + if rpcport != with_rpcport: + logger.debug( + "checking port {} against searched port {}".format( + type(rpcport), type(with_rpcport) + ) + ) + continue + rpcpassword = [ + arg + for arg in btcd_container.attrs["Config"]["Cmd"] + if "rpcpassword" in arg + ][0].split("=")[1] + rpcuser = [ + arg for arg in btcd_container.attrs["Config"]["Cmd"] if "rpcuser" in arg + ][0].split("=")[1] + if "CI" in os.environ: # this is a predefined variable in gitlab + # This works on Linux (direct docker) and gitlab-CI but not on MAC + ipaddress = btcd_container.attrs["NetworkSettings"]["IPAddress"] + else: + # This works on most machines but not on gitlab-CI + ipaddress = "127.0.0.1" + rpcconn = Btcd_conn( + rpcuser=rpcuser, + rpcpassword=rpcpassword, + rpcport=rpcport, + ipaddress=ipaddress, + ) + logger.info("detected container {}".format(btcd_container.id)) + return rpcconn, btcd_container + logger.debug("No matching container found") + return None + + def wait_for_container(self): + """ waits for the docker-container to come up. Times out after 10 seconds """ + i = 0 + while True: + ip_address = self.btcd_container.attrs["NetworkSettings"]["IPAddress"] + if ip_address.startswith("172"): + self.rpcconn.ipaddress = ip_address + break + self.btcd_container.reload() + time.sleep(0.5) + i = i + 1 + if i > 20: + raise Exception("Timeout while starting bitcoind-docker-container!") diff --git a/src/cryptoadvance/specter/cli/cli_bitcoind.py b/src/cryptoadvance/specter/cli/cli_bitcoind.py index 7ada9c7b6..37116ed97 100644 --- a/src/cryptoadvance/specter/cli/cli_bitcoind.py +++ b/src/cryptoadvance/specter/cli/cli_bitcoind.py @@ -98,7 +98,7 @@ def bitcoind( # In order to avoid these dependencies for production use, we're importing them here: import docker - from ..bitcoind import BitcoindDockerController, BitcoindPlainController + from ..bitcoind import BitcoindPlainController if config is None: config = DEFAULT_CONFIG @@ -159,6 +159,8 @@ def bitcoind( Path(config_obj["BTCD_REGTEST_DATA_DIR"]).mkdir(parents=True, exist_ok=True) else: echo("starting container") + from ..bitcoind_docker import BitcoindDockerController + my_bitcoind = BitcoindDockerController(docker_tag=docker_tag) try: my_bitcoind.start_bitcoind( diff --git a/src/cryptoadvance/specter/cli/cli_server.py b/src/cryptoadvance/specter/cli/cli_server.py index 631ed204b..99f9eaea6 100644 --- a/src/cryptoadvance/specter/cli/cli_server.py +++ b/src/cryptoadvance/specter/cli/cli_server.py @@ -13,6 +13,7 @@ from urllib.parse import urlparse from ..server import create_app, init_app from ..util.tor import start_hidden_service, stop_hidden_services +from ..specter_error import SpecterError logger = logging.getLogger(__name__) @@ -197,18 +198,6 @@ def server( # debug is false by default def run(debug=debug): - try: - 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: # if we have certificates if "ssl_context" in kwargs: @@ -245,8 +234,12 @@ def server( app.run(debug=debug, **kwargs) stop_hidden_services(app) finally: - if app.controller is not None: - app.controller.close() + try: + if app.specter.tor_controller is not None: + app.specter.tor_controller.close() + except SpecterError as se: + # no reason to break startup here + logger.error("Could not initialize tor-system") # check if we should run a daemon or not if daemon or restart: diff --git a/src/cryptoadvance/specter/config.py b/src/cryptoadvance/specter/config.py index 19dcf404d..9968360fc 100644 --- a/src/cryptoadvance/specter/config.py +++ b/src/cryptoadvance/specter/config.py @@ -66,6 +66,7 @@ class BaseConfig(object): SPECTER_SSL_CERT_SERIAL_NUMBER = int( os.getenv("SPECTER_SSL_CERT_SERIAL_NUMBER", random.randrange(1, 100000)) ) + INTERNAL_BITCOIND_VERSION = os.getenv("INTERNAL_BITCOIND_VERSION", "0.21.0") class DevelopmentConfig(BaseConfig): diff --git a/src/cryptoadvance/specter/server_endpoints/controller.py b/src/cryptoadvance/specter/server_endpoints/controller.py index ec5f112d2..692589ba3 100644 --- a/src/cryptoadvance/specter/server_endpoints/controller.py +++ b/src/cryptoadvance/specter/server_endpoints/controller.py @@ -1,4 +1,4 @@ -import random, traceback, socket +import random, traceback, socket, threading, os from datetime import datetime from binascii import unhexlify from flask import make_response @@ -18,7 +18,13 @@ from ..helpers import ( from ..specter import Specter from ..specter_error import SpecterError from ..util.tor import start_hidden_service, stop_hidden_services - +from ..util.bitcoind_setup_tasks import ( + setup_bitcoind_thread, + setup_bitcoind_directory_thread, +) +from ..util.tor_setup_tasks import ( + setup_tor_thread, +) from pathlib import Path env_path = Path(".") / ".flaskenv" @@ -104,6 +110,133 @@ def about(): return render_template("base.jinja", specter=app.specter, rand=rand) +@app.route("/node_setup_wizard/", defaults={"step": 0}, methods=["GET", "POST"]) +@app.route("/node_setup_wizard/", methods=["GET", "POST"]) +@login_required +def node_setup_wizard(step): + app.specter.config["bitcoind_setup"]["error"] = "" + app.specter.config["bitcoind_setup"]["stage"] = "" + app.specter.config["bitcoind_setup"]["stage_progress"] = -1 + app.specter.config["torbrowser_setup"]["error"] = "" + app.specter.config["torbrowser_setup"]["stage"] = "" + app.specter.config["torbrowser_setup"]["stage_progress"] = -1 + app.specter._save() + + return render_template( + "node_setup_wizard.jinja", step=step, specter=app.specter, rand=rand + ) + + +@app.route("/setup_bitcoind", methods=["POST"]) +@login_required +def setup_bitcoind(): + bitcoind_setup_status = app.specter.config.get( + "bitcoind_setup", {"stage_progress": -1} + ) + if ( + not os.path.isfile(app.specter.bitcoind_path) + and bitcoind_setup_status["stage_progress"] == -1 + ): + app.specter.config["rpc"]["datadir"] = request.form.get( + "bitcoin_core_datadir", app.specter.config["rpc"]["datadir"] + ) + app.specter.config["bitcoind_setup"]["stage_progress"] = 0 + app.specter.config["bitcoind_setup"]["error"] = "" + app.specter._save() + t = threading.Thread( + target=setup_bitcoind_thread, + args=(app.specter, app.config["INTERNAL_BITCOIND_VERSION"]), + ) + t.start() + elif os.path.isfile(app.specter.bitcoind_path): + return {"error": "bitcoind already installed"} + elif bitcoind_setup_status["stage_progress"] != -1: + return {"error": "bitcoind installation is still under progress"} + return {"success": "Starting Bitcoin Core setup!"} + + +@app.route("/setup_bitcoind_directory", methods=["POST"]) +@login_required +def setup_bitcoind_directory(): + bitcoind_setup_status = app.specter.config.get( + "bitcoind_setup", {"stage_progress": -1} + ) + if ( + os.path.isfile(app.specter.bitcoind_path) + and bitcoind_setup_status["stage_progress"] == -1 + ): + app.specter.config["bitcoind_setup"]["stage_progress"] = 0 + app.specter.config["bitcoind_setup"]["error"] = "" + app.specter._save() + quicksync = request.form["quicksync"] == "true" + pruned = request.form["nodetype"] == "pruned" + t = threading.Thread( + target=setup_bitcoind_directory_thread, + args=(app.specter, quicksync, pruned), + ) + t.start() + elif not os.path.isfile(app.specter.bitcoind_path): + return {"error": "bitcoind in not installed but required for this step"} + elif bitcoind_setup_status["stage_progress"] != -1: + return {"error": "bitcoind installation is still under progress"} + return {"success": "Starting Bitcoin Core setup!"} + + +@app.route("/setup_tor", methods=["POST"]) +@login_required +def setup_tor(): + tor_setup_status = app.specter.config.get( + "torbrowser_setup", {"stage_progress": -1} + ) + if ( + not os.path.isfile(app.specter.torbrowser_path) + and tor_setup_status["stage_progress"] == -1 + ): + app.specter.config["torbrowser_setup"]["stage_progress"] = 0 + app.specter.config["torbrowser_setup"]["error"] = "" + app.specter._save() + t = threading.Thread( + target=setup_tor_thread, + args=(app.specter,), + ) + t.start() + elif os.path.isfile(app.specter.torbrowser_path): + return {"error": "tor is already installed"} + elif tor_setup_status["stage_progress"] != -1: + return {"error": "tor installation is still under progress"} + return {"success": "Starting Tor setup!"} + + +@app.route("/get_node_setup_status") +@login_required +@app.csrf.exempt +def get_node_setup_status(): + return app.specter.config.get( + "bitcoind_setup", + { + "installed": os.path.isfile(app.specter.bitcoind_path), + "stage_progress": -1, + "stage": "none", + "error": "", + }, + ) + + +@app.route("/get_tor_setup_status") +@login_required +@app.csrf.exempt +def get_tor_setup_status(): + return app.specter.config.get( + "torbrowser_setup", + { + "installed": os.path.isfile(app.specter.torbrowser_path), + "stage_progress": -1, + "stage": "none", + "error": "", + }, + ) + + # TODO: Move all these below to REST API ################ Utils #################### diff --git a/src/cryptoadvance/specter/server_endpoints/settings.py b/src/cryptoadvance/specter/server_endpoints/settings.py index e0195753f..bb04e5cdf 100644 --- a/src/cryptoadvance/specter/server_endpoints/settings.py +++ b/src/cryptoadvance/specter/server_endpoints/settings.py @@ -1,5 +1,6 @@ -import json, os, time, random, requests, secrets - +import json, os, time, random, requests, secrets, platform, tarfile, zipfile, sys, shutil +import pgpy +from pathlib import Path from flask import ( Flask, Blueprint, @@ -23,6 +24,8 @@ 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 +from ..util.sha256sum import sha256sum +from ..util.error_handling import handle_exception rand = random.randint(0, 1e32) # to force style refresh @@ -58,6 +61,8 @@ def bitcoin_core(): protocol = "http" autodetect = rpc["autodetect"] datadir = rpc["datadir"] + external_node = rpc["external_node"] + node_view = "external" if external_node else "internal" err = None if "protocol" in rpc: @@ -65,14 +70,13 @@ def bitcoin_core(): test = None if request.method == "POST": action = request.form["action"] - if current_user.is_admin: - autodetect = "autodetect" in request.form - if autodetect: - datadir = request.form["datadir"] - user = request.form["username"] - password = request.form["password"] - port = request.form["port"] - host = request.form["host"].rstrip("/") + autodetect = "autodetect" in request.form + if autodetect: + datadir = request.form["datadir"] + user = request.form["username"] + password = request.form["password"] + port = request.form["port"] + host = request.form["host"].rstrip("/") # protocol://host if "://" in host: @@ -93,6 +97,7 @@ def bitcoin_core(): autodetect=autodetect, datadir=datadir, ) + node_view = "external" if "tests" in test: # If any test has failed, we notify the user that the test has not passed @@ -102,6 +107,7 @@ def bitcoin_core(): flash("Test passed", "info") elif action == "save": if current_user.is_admin: + node_view = "external" success = app.specter.update_rpc( user=user, password=password, @@ -114,6 +120,38 @@ def bitcoin_core(): if not success: flash("Failed connecting to the node", "error") app.specter.check() + # Internal Node actions + elif action == "useinternal": + app.specter.update_use_external_node(False) + external_node = False + node_view = "internal" + elif action == "useexternal": + app.specter.update_use_external_node(True) + external_node = True + node_view = "external" + elif action == "stopbitcoind": + node_view = "internal" + try: + app.specter.bitcoind.stop_bitcoind() + app.specter.set_bitcoind_pid(False) + time.sleep(5) + flash("Specter stopped Bitcoin Core successfully") + except Exception: + try: + flash("Stopping Bitcoin Core, this might take a few moments.") + app.specter.rpc.stop() + except Exception as e: + flash(f"Failed to stop Bitcoin Core {e}", "error") + elif action == "startbitcoind": + node_view = "internal" + app.specter.bitcoind.start_bitcoind( + datadir=os.path.expanduser(app.specter.config["rpc"]["datadir"]) + ) + app.specter.set_bitcoind_pid(app.specter.bitcoind.bitcoind_proc.pid) + time.sleep(15) + flash("Specter has started Bitcoin Core") + + app.specter.check() return render_template( "settings/bitcoin_core_settings.jinja", @@ -127,6 +165,10 @@ def bitcoin_core(): protocol=protocol, specter=app.specter, current_version=current_version, + bitcoind_exists=os.path.isfile(app.specter.bitcoind_path), + is_running=app.specter.is_bitcoind_running(), + node_view=node_view, + external_node=external_node, error=err, rand=rand, ) @@ -254,6 +296,9 @@ def tor(): if not current_user.is_admin: flash("Only an admin is allowed to access this page.", "error") return redirect("") + app.specter.config["torbrowser_setup"]["stage"] = "" + app.specter.config["torbrowser_setup"]["stage_progress"] = -1 + app.specter._save() current_version = notify_upgrade(app, flash) proxy_url = app.specter.proxy_url only_tor = app.specter.only_tor @@ -269,13 +314,36 @@ def tor(): 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 == "starttor": + try: + app.specter.tor_daemon.start_tor_daemon() + flash("Specter has started Tor") + except Exception as e: + flash(f"Failed to start Tor, error: {e}", "error") + elif action == "stoptor": + try: + app.specter.tor_daemon.stop_tor_daemon() + time.sleep(1) + flash("Specter stopped Tor successfully") + except Exception as e: + flash(f"Failed to stop Tor, error: {e}", "error") + elif action == "uninstalltor": + try: + if app.specter.is_tor_dameon_running(): + app.specter.tor_daemon.stop_tor_daemon() + shutil.rmtree(os.path.join(app.specter.data_folder, "tor-binaries")) + os.remove(os.path.join(app.specter.data_folder, "torrc")) + flash(f"Tor uninstalled successfully") + except Exception as e: + flash(f"Failed to stop Tor, error: {e}", "error") 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 + # "http://expyuzz4wqqyqhjn.onion", # Tor Project onion website (seems to be down) + "https://protonirockerxow.onion", # Proton mail onion website ) tor_connectable = res.status_code == 200 if tor_connectable: @@ -283,7 +351,7 @@ def tor(): 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") + flash("Failed to make test request over Tor.\nError: %s" % e, "error") tor_connectable = False elif action == "toggle_hidden_service": if not app.config["DEBUG"]: @@ -296,9 +364,10 @@ def tor(): if hasattr(current_user, "is_admin") and current_user.is_admin: try: current_hidden_services = ( - app.controller.list_ephemeral_hidden_services() + app.specter.tor_controller.list_ephemeral_hidden_services() ) - except Exception: + except Exception as e: + handle_exception(e) current_hidden_services = [] if len(current_hidden_services) != 0: stop_hidden_services(app) @@ -310,6 +379,7 @@ def tor(): app.specter.toggle_tor_status() flash("Tor hidden service turn on successfully", "info") except Exception as e: + handle_exception(e) flash( "Failed to start Tor hidden service. Make sure you have Tor running with ControlPort configured and try again. Error returned: {}".format( e @@ -328,6 +398,8 @@ def tor(): only_tor=only_tor, tor_control_port=tor_control_port, tor_service_id=app.tor_service_id, + torbrowser_installed=os.path.isfile(app.specter.torbrowser_path), + torbrowser_running=app.specter.is_tor_dameon_running, specter=app.specter, current_version=current_version, rand=rand, diff --git a/src/cryptoadvance/specter/server_endpoints/wallets.py b/src/cryptoadvance/specter/server_endpoints/wallets.py index 4c2af3dff..ac0241cf3 100644 --- a/src/cryptoadvance/specter/server_endpoints/wallets.py +++ b/src/cryptoadvance/specter/server_endpoints/wallets.py @@ -118,7 +118,9 @@ def new_wallet(wallet_type): action = request.form["action"] if action == "importwallet": try: - wallet_data = json.loads(request.form["wallet_data"].replace("'", "h")) + wallet_data = json.loads( + request.form["wallet_data"].replace("\\'", "").replace("'", "h") + ) ( wallet_name, recv_descriptor, diff --git a/src/cryptoadvance/specter/specter.py b/src/cryptoadvance/specter/specter.py index d7a0789ec..e7ce3f09f 100644 --- a/src/cryptoadvance/specter/specter.py +++ b/src/cryptoadvance/specter/specter.py @@ -6,11 +6,15 @@ import traceback import random import time import zipfile +import platform +import secrets import requests from io import BytesIO from .helpers import migrate_config, deep_update, clean_psbt, is_testnet from .util.checker import Checker -from .rpc import autodetect_rpc_confs, get_default_datadir, RpcError +from .rpc import autodetect_rpc_confs, detect_rpc_confs, get_default_datadir, RpcError +from .bitcoind import BitcoindPlainController +from .tor_daemon import TorDaemonController from urllib3.exceptions import NewConnectionError from requests.exceptions import ConnectionError from .rpc import BitcoinRPC @@ -20,7 +24,11 @@ from .user_manager import UserManager from .persistence import write_json_file, read_json_file from .user import User from .util.price_providers import update_price +from .util.tor import get_tor_daemon_suffix import threading +from urllib.parse import urlparse +from stem.control import Controller +from .specter_error import SpecterError logger = logging.getLogger(__name__) @@ -113,6 +121,7 @@ class Specter: "port": "", "host": "localhost", # localhost "protocol": "http", # https for the future + "external_node": True, }, "auth": { "method": "none", @@ -135,14 +144,63 @@ class Specter: "alt_symbol": "BTC", "price_provider": "", "validate_merkle_proofs": False, + "bitcoind": False, + "bitcoind_internal_version": "", + "bitcoind_setup": { + "stage_progress": -1, + }, + "torbrowser_setup": { + "stage_progress": -1, + }, } + self.torbrowser_path = os.path.join( + self.data_folder, f"tor-binaries/tor{get_tor_daemon_suffix()}" + ) + + self.bitcoind_path = os.path.join( + self.data_folder, "bitcoin-binaries/bin/bitcoind" + ) + + if platform.system() == "Windows": + self.bitcoind_path += ".exe" + + self._bitcoind = None + self._tor_daemon = None # health check: loads config, tests rpc # also loads and checks wallets for all users try: self.check(check_all=True) + rpc_conf = next( + ( + conf + for conf in detect_rpc_confs( + datadir=os.path.expanduser(self.config["rpc"]["datadir"]) + ) + if conf["port"] == 8332 + ), + None, + ) + if not rpc_conf: + if not self.config["rpc"]["user"]: + self.config["rpc"]["user"] = "bitcoin" + self._save() + if not self.config["rpc"]["password"]: + self.config["rpc"]["password"] = secrets.token_urlsafe(16) + self._save() + + if os.path.isfile(self.torbrowser_path): + self.tor_daemon.start_tor_daemon() + + if not self.config["rpc"].get("external_node", True): + self.bitcoind.start_bitcoind( + datadir=os.path.expanduser(self.config["rpc"]["datadir"]) + ) + self.set_bitcoind_pid(self.bitcoind.bitcoind_proc.pid) + time.sleep(15) except Exception as e: logger.error(e) + self.update_tor_controller() self.checker = Checker(lambda: self.check(check_all=True), desc="health") self.checker.start() self.price_checker = Checker( @@ -443,6 +501,17 @@ class Specter: self.check(check_all=True) return self.rpc is not None + def set_bitcoind_pid(self, pid): + """ set the control pid of the bitcoind daemon """ + if self.config.get("bitcoind", False) != pid: + self.config["bitcoind"] = pid + self._save() + + def update_use_external_node(self, use_external_node): + """ set whatever specter should connect to internal or external node """ + self.config["rpc"]["external_node"] = use_external_node + self._save() + def update_auth(self, method, rate_limit, registration_link_timeout): """ simply persisting the current auth-choice """ auth = self.config["auth"] @@ -493,6 +562,71 @@ class Specter: if self.config["tor_control_port"] != tor_control_port: self.config["tor_control_port"] = tor_control_port self._save() + self.update_tor_controller() + + def update_tor_controller(self): + try: + tor_control_address = urlparse(self.proxy_url).netloc.split(":")[0] + if tor_control_address == "localhost": + tor_control_address = "127.0.0.1" + self._tor_controller = Controller.from_port( + address=tor_control_address, + port=int(self.tor_control_port) if self.tor_control_port else "default", + ) + self._tor_controller.authenticate( + password=self.config.get("torrc_password", "") + ) + except Exception as e: + logger.warning(f"Failed to connect to Tor control port. Error: {e}") + self._tor_controller = None + + @property + def tor_daemon(self): + if os.path.isfile(self.torbrowser_path) and os.path.join( + self.data_folder, "torrc" + ): + if not self._tor_daemon: + self._tor_daemon = TorDaemonController( + tor_daemon_path=self.torbrowser_path, + tor_config_path=os.path.join(self.data_folder, "torrc"), + ) + return self._tor_daemon + raise SpecterError( + "Tor daemon files missing. Make sure Tor is installed within Specter" + ) + + @property + def bitcoind(self): + if os.path.isfile(self.bitcoind_path): + if not self._bitcoind: + self._bitcoind = BitcoindPlainController( + bitcoind_path=self.bitcoind_path, + rpcport=8332, + network="mainnet", + rpcuser=self.config["rpc"]["user"], + rpcpassword=self.config["rpc"]["password"], + ) + return self._bitcoind + raise SpecterError( + "Bitcoin Core files missing. Make sure Bitcoin Core is installed within Specter" + ) + + def is_tor_dameon_running(self): + return self._tor_daemon and self._tor_daemon.is_running() + + def is_bitcoind_running(self): + return self._bitcoind and self._bitcoind.check_existing() + + @property + def tor_controller(self): + if self._tor_controller: + return self._tor_controller + self.update_tor_controller() + if self._tor_controller: + return self._tor_controller + raise SpecterError( + "Failed to connect to the Tor daemon. Make sure ControlPort is properly configured." + ) def update_hwi_bridge_url(self, url, user): """ update the hwi bridge url to use """ diff --git a/src/cryptoadvance/specter/static/bitcoin-release-pubkey.asc b/src/cryptoadvance/specter/static/bitcoin-release-pubkey.asc new file mode 100644 index 000000000..3618f0c2d --- /dev/null +++ b/src/cryptoadvance/specter/static/bitcoin-release-pubkey.asc @@ -0,0 +1,784 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +S9Pb9RpTJvsxc4FTeX7vTHtCosUVKvvK +=D7TT +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/cryptoadvance/specter/static/img/party.png b/src/cryptoadvance/specter/static/img/party.png new file mode 100644 index 0000000000000000000000000000000000000000..1ee811baf0977bae56d7c0f20d6c497d0370ac32 GIT binary patch literal 35241 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
    bFpYr`1>*SI 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 FV1hL~wax$l literal 0 HcmV?d00001 diff --git a/src/cryptoadvance/specter/static/pruned-node-today-release-pubkey.asc b/src/cryptoadvance/specter/static/pruned-node-today-release-pubkey.asc new file mode 100644 index 000000000..9fb89b0e4 --- /dev/null +++ b/src/cryptoadvance/specter/static/pruned-node-today-release-pubkey.asc @@ -0,0 +1,12 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mE8EX3YN+BMFK4EEAAoCAwRhTEFptcVn6WAE4PbCTCeeHRmqQ5Yd49wCdycs9Sje +2B/rBPEGADac9PRmIXhjtWn3pifZ/sG2hFzl7G3VGIDttElTdGVwYW4gU25pZ2ly +ZXYgKFNwZWN0ZXIgcmVsZWFzZSBzaWduaW5nIGtleSkgPHNuaWdpcmV2LnN0ZXBh +bkBnbWFpbC5jb20+iJYEExMIAD4WIQRvFuNU+DOT1uUuwl827TV6skuRXwUCX3YN ++AIbAwUJAeEzgAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRA27TV6skuRX9P2 +AP9LUiI/IapEK0YcRFczaBGyRC2/p8AvrKKrK/8hY6evfgEAo00jrdk10duMaY7N +kpfNcQIQy6Qhv3HDg8AcY1RgUyk= +=9s5S +-----END PGP PUBLIC KEY BLOCK----- + diff --git a/src/cryptoadvance/specter/static/torbrowser-release-pubkey.asc b/src/cryptoadvance/specter/static/torbrowser-release-pubkey.asc new file mode 100644 index 000000000..b768015ba --- /dev/null +++ b/src/cryptoadvance/specter/static/torbrowser-release-pubkey.asc @@ -0,0 +1,332 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +qAtUENvs4LC7dEE= +=Jqal +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/cryptoadvance/specter/templates/base.jinja b/src/cryptoadvance/specter/templates/base.jinja index 17541b8fc..4c4f829a3 100644 --- a/src/cryptoadvance/specter/templates/base.jinja +++ b/src/cryptoadvance/specter/templates/base.jinja @@ -35,6 +35,9 @@ + + + {% if specter.config.auth.method != "none" %} @@ -69,7 +72,11 @@

    Specter Desktop is a convenient wallet interface to better use your Bitcoin Core node. It’s good for singlesig wallets, but comes with a special focus on multisignature setups for different hardware wallets and air-gapped signing devices.

    -


    +

    + {% if not specter.chain %} +
    Get started! +

    + {% else %}

    Getting Started


    @@ -78,8 +85,8 @@
    - -

    Connect Specter to your Bitcoin Core node.

    +
    +

    Connect Specter with Bitcoin Core node.

    @@ -175,6 +182,7 @@

    + {% endif %} Having issues? Try reading the FAQ

    Still having issues?
    Feel free to open an issue on the GitHub or ask in the Specter Community telegram chat diff --git a/src/cryptoadvance/specter/templates/includes/address-label.html b/src/cryptoadvance/specter/templates/includes/address-label.html index 95af9ff0a..1fe8b61f3 100644 --- a/src/cryptoadvance/specter/templates/includes/address-label.html +++ b/src/cryptoadvance/specter/templates/includes/address-label.html @@ -228,9 +228,9 @@ if (jsonResponse.label) { self.label.innerText = jsonResponse.label; } - return - }; - showError('Failed to fetch address label data.') + return; + } + showError('Failed to fetch address label data.'); } catch(e) { console.log("Caught error: ", e); showError(e); diff --git a/src/cryptoadvance/specter/templates/node_setup_wizard.jinja b/src/cryptoadvance/specter/templates/node_setup_wizard.jinja new file mode 100644 index 000000000..5b1c77af1 --- /dev/null +++ b/src/cryptoadvance/specter/templates/node_setup_wizard.jinja @@ -0,0 +1,365 @@ +{% extends "base.jinja" %} + +{% block main %} + + {% from "components/bitcoin_svg.jinja" import bitcoin_svg %} + + + + + + +
    + +

    +

    +{% endblock %} + + +{% block scripts %} + +{% endblock %} diff --git a/src/cryptoadvance/specter/templates/settings/bitcoin_core_settings.jinja b/src/cryptoadvance/specter/templates/settings/bitcoin_core_settings.jinja index aa8c8a30e..53d8c674d 100644 --- a/src/cryptoadvance/specter/templates/settings/bitcoin_core_settings.jinja +++ b/src/cryptoadvance/specter/templates/settings/bitcoin_core_settings.jinja @@ -7,7 +7,48 @@

    Bitcoin Core settings - Specter Desktop {{ current_version }}

    {% from 'settings/components/settings_menu.jinja' import settings_menu %} {{ settings_menu('bitcoin_core', current_user) }} -
    + + +
    + {% if external_node %} + +

    + {% endif %} + {% if bitcoind_exists %} +

    Built in Bitcoin Node Status: {% if is_running %}Running{% else %}Down{% endif %}


    + Bitcoin Core Version: {{specter.config.bitcoind_internal_version}} +

    + {% if not external_node %} + {% if is_running %} + + {% else %} + +

    + If this is your first time starting the node, and you haven't used the QuickSync, your node will start with Initial Block Downloading (IBD) to sync with the network.
    + This process of IBD syncing may take several days. If you'd like the QuickSync option, please click on it before starting your node, or if it's running, stop it and the click the QuickSync.
    + (Warning: QuickSync will override any existing data of your Bitcoin Node!) +

    + {% endif %} + {% else %} +

    Please switch node type to start the built in node.

    + {% endif %} +

    + {% else %} +
    +

    Setup Bitcoin Core Node


    + Setup new Bitcoin node +
    + {% endif %} +
    + +
    + {% if not external_node %} + +

    + {% endif %}

    Bitcoin JSON-RPC configuration


    @@ -140,6 +181,7 @@ {% block scripts %} {% endblock %} diff --git a/src/cryptoadvance/specter/templates/wallet/settings/components/export_wallet_account_map.jinja b/src/cryptoadvance/specter/templates/wallet/settings/components/export_wallet_account_map.jinja index 41cf24dd2..8deeec7d7 100644 --- a/src/cryptoadvance/specter/templates/wallet/settings/components/export_wallet_account_map.jinja +++ b/src/cryptoadvance/specter/templates/wallet/settings/components/export_wallet_account_map.jinja @@ -24,7 +24,8 @@