From b2e3943d0408dde8a29235f1c65e5ec7d30bdc78 Mon Sep 17 00:00:00 2001 From: Robert Habermann Date: Sat, 6 Oct 2018 20:39:24 +0200 Subject: [PATCH 1/6] initial add --- home.admin/AAunlockLND.py | 161 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 home.admin/AAunlockLND.py diff --git a/home.admin/AAunlockLND.py b/home.admin/AAunlockLND.py new file mode 100644 index 000000000..8745d4bbd --- /dev/null +++ b/home.admin/AAunlockLND.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import base64 +import os +import signal +import subprocess +import sys +from optparse import OptionParser + +try: # make sure that (unsupported) Python2 can fail gracefully + import configparser +except ImportError: + pass + +if sys.version_info < (3, 5, 0): + print("Python2 not supported! Please run with Python3.5+") + sys.exit(1) + + +def sigint_handler(signum, frame): + print('CTRL+C pressed - exiting!') + sys.exit(0) + + +def _read_pwd(password_file): + # read and convert password from file + p = subprocess.run("sudo cat {}".format(password_file), + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=False, shell=True, timeout=None) + if not p.returncode == 0: + print("unable to read password from: {}".format(password_file)) + sys.exit(1) + passwd_bytes = p.stdout.split(b"\n")[0] + passwd_b64 = base64.encodebytes(passwd_bytes).decode('utf-8').split("\n")[0] + return passwd_b64 + + +def _read_macaroon(lnd_macaroon_file): + # read and convert macaroon from file + p = subprocess.run("sudo xxd -ps -u -c 1000 {}".format(lnd_macaroon_file), + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True, shell=True, timeout=None) + macaroon_hex_dump = p.stdout.split("\n")[0] + return macaroon_hex_dump + + +def check_locked(password_file, lnd_cert_file, lnd_macaroon_file, host="localhost", port="8080", verbose=False): + # check locked + if verbose: + print("Checking for lock with the following data:") + print("Password File: \033[93m{}\033[00m".format(password_file)) + print("TLS CERT File: \033[93m{}\033[00m".format(lnd_cert_file)) + print("Macaroon File: \033[93m{}\033[00m".format(lnd_macaroon_file)) + print("URL: \033[93mhttps://{}:{}\033[00m".format(host, port)) + + passwd_b64 = _read_pwd(password_file) + macaroon_hex_dump = _read_macaroon(lnd_macaroon_file) + + cmds = ["curl", "-s", + "-H", "'Grpc-Metadata-macaroon: {}'".format(macaroon_hex_dump), + "--cacert", "{}".format(lnd_cert_file), + "-d", "{{\"wallet_password\": \"{}\"}}".format(passwd_b64), + "https://{}:{}/v1/getinfo".format(host, port)] + + p = subprocess.run(cmds, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True, shell=False, timeout=None) + if not p.returncode == 0: + print("Something went wrong! Returncode\n{}\nStderr: {}".format(p.returncode, p.stderr)) + sys.exit(1) + + if p.stdout == "Not Found\n": + return True + else: + return False + + +def unlock(password_file, lnd_cert_file, lnd_macaroon_file, host="localhost", port="8080", verbose=False): + if verbose: + print("Trying to unlock with the following data:") + print("Password File: \033[93m{}\033[00m".format(password_file)) + print("TLS CERT File: \033[93m{}\033[00m".format(lnd_cert_file)) + print("Macaroon File: \033[93m{}\033[00m".format(lnd_macaroon_file)) + print("URL: \033[93mhttps://{}:{}\033[00m".format(host, port)) + + passwd_b64 = _read_pwd(password_file) + macaroon_hex_dump = _read_macaroon(lnd_macaroon_file) + + # unlock lnd by calling curl + cmds = ["curl", "-s", + "-H", "'Grpc-Metadata-macaroon: {}'".format(macaroon_hex_dump), + "--cacert", "{}".format(lnd_cert_file), + "-d", "{{\"wallet_password\": \"{}\"}}".format(passwd_b64), + "https://{}:{}/v1/unlockwallet".format(host, port)] + + p = subprocess.run(cmds, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + universal_newlines=True, shell=False, timeout=None) + if p.returncode == 0: + return True + else: + if verbose: + print("Something went wrong! Returncode\n{}\nStderr: {}".format(p.returncode, p.stderr)) + return False + + +def main(): + signal.signal(signal.SIGINT, sigint_handler) + + usage = "usage: %prog [Options]" + parser = OptionParser(usage=usage, version="%prog {}".format("0.1")) + + parser.add_option("-v", "--verbose", dest="verbose", action="store_true", + help="Print more output") + + parser.add_option("-H", dest="host", type="string", default="localhost", + help="Host (default: localhost)") + parser.add_option("-P", dest="port", type="string", default="8080", + help="Port (default: 8080)") + + parser.add_option("-p", dest="password_file", type="string", default="pwd", + help="File containing *cleartext* password (default: pwd)") + parser.add_option("-c", dest="cert", type="string", + help="TLS certificate file (e.g. ~/.lnd/tls.cert)"), + parser.add_option("-m", dest="macaroon", type="string", default="pwd", + help="Macaroon file (e.g. readonly.macaroon)") + options, args = parser.parse_args() + + password_file = os.path.abspath(options.password_file) + if not os.path.exists(password_file): + print("Password file does not exist - exiting: {}".format(password_file)) + sys.exit(1) + + if options.cert: + lnd_cert_file = options.cert + else: + lnd_cert_file = "/home/bitcoin/.lnd/tls.cert" + + if options.macaroon: + lnd_macaroon_file = options.macaroon + else: + lnd_macaroon_file = "/home/bitcoin/.lnd/data/chain/bitcoin/mainnet/readonly.macaroon" + + if check_locked(password_file, lnd_cert_file, lnd_macaroon_file, + host=options.host, port=options.port, verbose=options.verbose): + print("\033[93m{}\033[00m".format("Locked")) + else: + if options.verbose: + print("\033[92m{}\033[00m".format("Not Locked")) + sys.exit(1) + + if unlock(password_file, lnd_cert_file, lnd_macaroon_file, + host=options.host, port=options.port, verbose=options.verbose): + print("\033[92m{}\033[00m".format("Successfully unlocked.")) + else: + print("\033[91m{}\033[00m".format("Failed to unlock.")) + + +if __name__ == "__main__": + main() From ae338733af31cc577aa4090cf9e666d41b5e9893 Mon Sep 17 00:00:00 2001 From: Robert Habermann Date: Sat, 6 Oct 2018 20:55:53 +0200 Subject: [PATCH 2/6] fix typo --- home.admin/AAunlockLND.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) mode change 100644 => 100755 home.admin/AAunlockLND.py diff --git a/home.admin/AAunlockLND.py b/home.admin/AAunlockLND.py old mode 100644 new mode 100755 index 8745d4bbd..9f503f30c --- a/home.admin/AAunlockLND.py +++ b/home.admin/AAunlockLND.py @@ -49,10 +49,6 @@ def check_locked(password_file, lnd_cert_file, lnd_macaroon_file, host="localhos # check locked if verbose: print("Checking for lock with the following data:") - print("Password File: \033[93m{}\033[00m".format(password_file)) - print("TLS CERT File: \033[93m{}\033[00m".format(lnd_cert_file)) - print("Macaroon File: \033[93m{}\033[00m".format(lnd_macaroon_file)) - print("URL: \033[93mhttps://{}:{}\033[00m".format(host, port)) passwd_b64 = _read_pwd(password_file) macaroon_hex_dump = _read_macaroon(lnd_macaroon_file) @@ -79,10 +75,6 @@ def check_locked(password_file, lnd_cert_file, lnd_macaroon_file, host="localhos def unlock(password_file, lnd_cert_file, lnd_macaroon_file, host="localhost", port="8080", verbose=False): if verbose: print("Trying to unlock with the following data:") - print("Password File: \033[93m{}\033[00m".format(password_file)) - print("TLS CERT File: \033[93m{}\033[00m".format(lnd_cert_file)) - print("Macaroon File: \033[93m{}\033[00m".format(lnd_macaroon_file)) - print("URL: \033[93mhttps://{}:{}\033[00m".format(host, port)) passwd_b64 = _read_pwd(password_file) macaroon_hex_dump = _read_macaroon(lnd_macaroon_file) @@ -123,7 +115,7 @@ def main(): help="File containing *cleartext* password (default: pwd)") parser.add_option("-c", dest="cert", type="string", help="TLS certificate file (e.g. ~/.lnd/tls.cert)"), - parser.add_option("-m", dest="macaroon", type="string", default="pwd", + parser.add_option("-m", dest="macaroon", type="string", help="Macaroon file (e.g. readonly.macaroon)") options, args = parser.parse_args() @@ -142,6 +134,12 @@ def main(): else: lnd_macaroon_file = "/home/bitcoin/.lnd/data/chain/bitcoin/mainnet/readonly.macaroon" + if options.verbose: + print("Password File: \033[93m{}\033[00m".format(password_file)) + print("TLS CERT File: \033[93m{}\033[00m".format(lnd_cert_file)) + print("Macaroon File: \033[93m{}\033[00m".format(lnd_macaroon_file)) + print("URL: \033[93mhttps://{}:{}\033[00m".format(options.host, options.port)) + if check_locked(password_file, lnd_cert_file, lnd_macaroon_file, host=options.host, port=options.port, verbose=options.verbose): print("\033[93m{}\033[00m".format("Locked")) From 75a2a242ea885cd85c29e72fcdafe823d0d1114f Mon Sep 17 00:00:00 2001 From: Robert Habermann Date: Sat, 6 Oct 2018 21:02:11 +0200 Subject: [PATCH 3/6] add error hints --- home.admin/AAunlockLND.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/home.admin/AAunlockLND.py b/home.admin/AAunlockLND.py index 9f503f30c..a27842429 100755 --- a/home.admin/AAunlockLND.py +++ b/home.admin/AAunlockLND.py @@ -63,7 +63,9 @@ def check_locked(password_file, lnd_cert_file, lnd_macaroon_file, host="localhos stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=False, timeout=None) if not p.returncode == 0: - print("Something went wrong! Returncode\n{}\nStderr: {}".format(p.returncode, p.stderr)) + print("\033[91mSomething went wrong!\033[00m \033[93mIs lnd running? Wrong credentials?\033[00m") + # print("Returncode: {}".format(p.returncode)) + # print("Stderr: {}".format(p.stderr)) sys.exit(1) if p.stdout == "Not Found\n": @@ -93,7 +95,9 @@ def unlock(password_file, lnd_cert_file, lnd_macaroon_file, host="localhost", po return True else: if verbose: - print("Something went wrong! Returncode\n{}\nStderr: {}".format(p.returncode, p.stderr)) + print("\033[91mSomething went wrong!\033[00m \033[93mIs lnd running? Wrong credentials?\033[00m") + # print("Returncode: {}".format(p.returncode)) + # print("Stderr: {}".format(p.stderr)) return False From 7e02934f6d8ed1dcc5517a554b8043ba87cb252e Mon Sep 17 00:00:00 2001 From: Patrick Pachur Date: Sun, 7 Oct 2018 12:50:51 +0200 Subject: [PATCH 4/6] get bitcoind public ip from cli --- home.admin/00infoBlitz.sh | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/home.admin/00infoBlitz.sh b/home.admin/00infoBlitz.sh index cd6428573..4b39ec643 100755 --- a/home.admin/00infoBlitz.sh +++ b/home.admin/00infoBlitz.sh @@ -111,22 +111,7 @@ fi # get IP address & port local_ip=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/') public_ip=$(curl -s http://v4.ipv6-test.com/api/myip.php) -public_port=$(cat ${bitcoin_dir}/${network}.conf 2>/dev/null | grep port= | awk -F"=" '{print $2}') -if [ "${public_port}" = "" ]; then - if [ "${network}" = "litecoin" ]; then - if [ "${chain}" = "test" ]; then - public_port=19333 - else - public_port=9333 - fi - else - if [ "${chain}" = "test" ]; then - public_port=18333 - else - public_port=8333 - fi - fi -fi +public_port="$(${network}-cli -datadir=${bitcoin_dir} getnetworkinfo | jq -r '.localaddresses [0] .port')" # CHAIN NETWORK public_addr="??" @@ -221,4 +206,4 @@ ${color_yellow}${ln_external} if [ ${#onionAddress} -eq 0 ]; then # one extra space line at the end if nodeaddress is not TOR echo "" -fi \ No newline at end of file +fi From a7d21b45fa796767425f61556ed2f9848d4bc096 Mon Sep 17 00:00:00 2001 From: Patrick Pachur Date: Sun, 7 Oct 2018 12:57:59 +0200 Subject: [PATCH 5/6] refactor to reduce bitcoin-cli calls --- home.admin/00infoBlitz.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/home.admin/00infoBlitz.sh b/home.admin/00infoBlitz.sh index 4b39ec643..ab6122987 100755 --- a/home.admin/00infoBlitz.sh +++ b/home.admin/00infoBlitz.sh @@ -109,9 +109,10 @@ if [ -n ${btc_path} ]; then fi # get IP address & port +networkInfo=$(${network}-cli -datadir=${bitcoin_dir} getnetworkinfo) local_ip=$(ip addr | grep 'state UP' -A2 | tail -n1 | awk '{print $2}' | cut -f1 -d'/') public_ip=$(curl -s http://v4.ipv6-test.com/api/myip.php) -public_port="$(${network}-cli -datadir=${bitcoin_dir} getnetworkinfo | jq -r '.localaddresses [0] .port')" +public_port="$(echo ${networkInfo} | jq -r '.localaddresses [0] .port')" # CHAIN NETWORK public_addr="??" @@ -119,7 +120,7 @@ torInfo="" # Version networkVersion=$(${network}-cli -datadir=${bitcoin_dir} -version | cut -d ' ' -f6) # TOR or IP -onionAddress=$(${network}-cli -datadir=${bitcoin_dir} getnetworkinfo | grep '"address"' | cut -d '"' -f4) +onionAddress=$(echo ${networkInfo} | jq -r '.localaddresses [0] .address') if [ ${#onionAddress} -gt 0 ]; then # TOR address public_addr="${onionAddress}:${public_port}" From 4b341336b451d28b6a1f0aa06ecfead211684a27 Mon Sep 17 00:00:00 2001 From: Robert Habermann Date: Sun, 7 Oct 2018 15:27:31 +0200 Subject: [PATCH 6/6] update logging --- home.admin/AAunlockLND.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/home.admin/AAunlockLND.py b/home.admin/AAunlockLND.py index a27842429..e38f7c850 100755 --- a/home.admin/AAunlockLND.py +++ b/home.admin/AAunlockLND.py @@ -48,7 +48,7 @@ def _read_macaroon(lnd_macaroon_file): def check_locked(password_file, lnd_cert_file, lnd_macaroon_file, host="localhost", port="8080", verbose=False): # check locked if verbose: - print("Checking for lock with the following data:") + print("Checking for lock") passwd_b64 = _read_pwd(password_file) macaroon_hex_dump = _read_macaroon(lnd_macaroon_file) @@ -76,7 +76,7 @@ def check_locked(password_file, lnd_cert_file, lnd_macaroon_file, host="localhos def unlock(password_file, lnd_cert_file, lnd_macaroon_file, host="localhost", port="8080", verbose=False): if verbose: - print("Trying to unlock with the following data:") + print("Trying to unlock") passwd_b64 = _read_pwd(password_file) macaroon_hex_dump = _read_macaroon(lnd_macaroon_file) @@ -146,11 +146,11 @@ def main(): if check_locked(password_file, lnd_cert_file, lnd_macaroon_file, host=options.host, port=options.port, verbose=options.verbose): - print("\033[93m{}\033[00m".format("Locked")) - else: if options.verbose: - print("\033[92m{}\033[00m".format("Not Locked")) - sys.exit(1) + print("\033[93m{}\033[00m".format("Locked")) + else: + print("\033[92m{}\033[00m".format("Not Locked")) + sys.exit(1) if unlock(password_file, lnd_cert_file, lnd_macaroon_file, host=options.host, port=options.port, verbose=options.verbose):