From 6f5d222e48732e79bdde1b33652bc55a341c45fb Mon Sep 17 00:00:00 2001 From: Luke Childs Date: Wed, 6 Jan 2021 20:29:57 +0700 Subject: [PATCH 01/24] Fix typo in lnd_connect_uri.md --- lnd_connect_uri.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lnd_connect_uri.md b/lnd_connect_uri.md index 805dc16..089241f 100644 --- a/lnd_connect_uri.md +++ b/lnd_connect_uri.md @@ -7,7 +7,7 @@ Zap-iOS can open URLs with the scheme `lndconnect:` to directly connect to remot [foo] means optional, \ are placeholders ``` -lndconnect://:?[cert=&]macaroon= +lndconnect://:?[cert=&]macaroon= ``` ### Javascript reference implementation From 59fd1e858995228fb9c1330eb435364ebfcc7c54 Mon Sep 17 00:00:00 2001 From: roshii Date: Tue, 20 Sep 2022 13:43:22 +0200 Subject: [PATCH 02/24] update dependencies --- config.go | 10 +- go.mod | 11 +- go.sum | 333 ++++++++++-------------------------------------------- 3 files changed, 71 insertions(+), 283 deletions(-) diff --git a/config.go b/config.go index 3cd1694..da18374 100644 --- a/config.go +++ b/config.go @@ -11,7 +11,7 @@ import ( "path/filepath" "strings" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" "github.com/jessevdk/go-flags" "github.com/lightningnetwork/lnd/tor" ) @@ -93,10 +93,10 @@ type config struct { // line options. // // The configuration proceeds as follows: -// 1) Start with a default config with sane settings -// 2) Pre-parse the command line to check for an alternative config file -// 3) Load configuration file overwriting defaults with any specified options -// 4) Parse CLI options and overwrite/add any specified options +// 1. Start with a default config with sane settings +// 2. Pre-parse the command line to check for an alternative config file +// 3. Load configuration file overwriting defaults with any specified options +// 4. Parse CLI options and overwrite/add any specified options func loadConfig() (*config, error) { defaultCfg := config{ LndConnect: &lndConnectConfig{ diff --git a/go.mod b/go.mod index a78ceca..1335ea6 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,11 @@ go 1.16 require ( github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f - github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce - github.com/glendc/go-external-ip v0.0.0-20200601212049-c872357d968e - github.com/jessevdk/go-flags v1.4.0 - github.com/lightningnetwork/lnd v0.13.0-beta.rc3 - github.com/mattn/go-colorable v0.1.8 // indirect + github.com/btcsuite/btcd/btcutil v1.1.2 + github.com/glendc/go-external-ip v0.1.0 + github.com/jessevdk/go-flags v1.5.0 + github.com/lightningnetwork/lnd/tor v1.1.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e ) -replace go.etcd.io/etcd => go.etcd.io/etcd v0.5.0-alpha.5.0.20201125193152-8a03d2e9614b +require github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/go.sum b/go.sum index 28091ff..7ce1ef1 100644 --- a/go.sum +++ b/go.sum @@ -1,348 +1,137 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -git.schwanenlied.me/yawning/bsaes.git v0.0.0-20180720073208-c0276d75487e/go.mod h1:BWqTsj8PgcPriQJGl7el20J/7TuT1d/hSyFDXMEpoEo= github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f h1:2dk3eOnYllh+wUOuDhOoC2vUVoJF/5z478ryJ+wzEII= github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e/go.mod h1:Bdzq+51GR4/0DIhaICZEOm+OHvXGwwB2trKZ8B4Y6eQ= -github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82/go.mod h1:GbuBk21JqF+driLX3XtJYNZjGa45YDoa9IqCTzNSfEc= -github.com/Yawning/aez v0.0.0-20180114000226-4dad034d9db2/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk= -github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= -github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.21.0-beta.0.20201208033208-6bd4c64a54fa/go.mod h1:Sv4JPQ3/M+teHz9Bo5jBpkNcP0x6r7rdihlNL/7tTAs= -github.com/btcsuite/btcd v0.21.0-beta.0.20210426180113-7eba688b65e5/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/btcsuite/btcd v0.21.0-beta.0.20210429225535-ce697fe7e82b h1:+BMyRYlNCozjv6zGhnyHExB6JquAIYZRwsc5bxPEXrI= -github.com/btcsuite/btcd v0.21.0-beta.0.20210429225535-ce697fe7e82b/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.22.0-beta.0.20220207191057-4dc4ff7963b4/go.mod h1:7alexyj/lHlOtr2PJK7L/+HDJZpcGDn/pAU98r7DY08= +github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= +github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.2 h1:XLMbX8JQEiwMcYft2EGi8zPUkoa0abKIU6/BJSRsjzQ= +github.com/btcsuite/btcd/btcutil v1.1.2/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= -github.com/btcsuite/btcutil/psbt v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= -github.com/btcsuite/btcwallet v0.12.0/go.mod h1:f1HuBGov5+OTp40Gh1vA+tvF6d7bbuLFTceJMRB7fXw= -github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= -github.com/btcsuite/btcwallet/wallet/txauthor v1.0.1-0.20210329233242-e0607006dce6/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= -github.com/btcsuite/btcwallet/wallet/txrules v1.0.0/go.mod h1:UwQE78yCerZ313EXZwEiu3jNAtfXj2n2+c8RWiE/WNA= -github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= -github.com/btcsuite/btcwallet/wallet/txsizes v1.0.1-0.20210329233242-e0607006dce6/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= -github.com/btcsuite/btcwallet/walletdb v1.3.4/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= -github.com/btcsuite/btcwallet/walletdb v1.3.5-0.20210513043850-3a2f12e3a954/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= -github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= -github.com/btcsuite/btcwallet/wtxmgr v1.3.0/go.mod h1:awQsh1n/0ZrEQ+JZgWvHeo153ubzEisf/FyNtwI0dDk= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/glendc/go-external-ip v0.0.0-20200601212049-c872357d968e h1:gLpAlmoGqnW3a3GCkOe+Ic8hZoSCfi0PdA0B8j7d6uw= -github.com/glendc/go-external-ip v0.0.0-20200601212049-c872357d968e/go.mod h1:o9OoDQyE1WHvYVUH1FdFapy1/rCZHHq3O5wS4VA83ig= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/glendc/go-external-ip v0.1.0 h1:iX3xQ2Q26atAmLTbd++nUce2P5ht5P4uD4V7caSY/xg= +github.com/glendc/go-external-ip v0.1.0/go.mod h1:CNx312s2FLAJoWNdJWZ2Fpf5O4oLsMFwuYviHjS4uJE= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= -github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= -github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= -github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= -github.com/juju/retry v0.0.0-20180821225755-9058e192b216/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= -github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= -github.com/juju/utils v0.0.0-20180820210520-bf9cc5bdd62d/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= -github.com/juju/version v0.0.0-20180108022336-b64dbd566305/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lightninglabs/gozmq v0.0.0-20191113021534-d20a764486bf/go.mod h1:vxmQPeIQxPf6Jf9rM8R+B4rKBqLA2AjttNxkFBL2Plk= -github.com/lightninglabs/neutrino v0.12.1/go.mod h1:GlKninWpRBbL7b8G0oQ36/8downfnFwKsr0hbRA6E/E= -github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display/go.mod h1:2oKOBU042GKFHrdbgGiKax4xVrFiZu51lhacUZQ9MnE= -github.com/lightningnetwork/lightning-onion v1.0.2-0.20200501022730-3c8c8d0b89ea/go.mod h1:rigfi6Af/KqsF7Za0hOgcyq2PNH4AN70AaMRxcJkff4= -github.com/lightningnetwork/lnd v0.13.0-beta.rc3 h1:vPFNRHISP7NtMafprsBZ0bi2HPoA/yo/jvcwUjiX7Wk= -github.com/lightningnetwork/lnd v0.13.0-beta.rc3/go.mod h1:uPP8n+uTsMC7WDpO6tosvVwI2B51wgHptMzWDXcwq2M= -github.com/lightningnetwork/lnd/cert v1.0.3/go.mod h1:3MWXVLLPI0Mg0XETm9fT4N9Vyy/8qQLmaM5589bEggM= -github.com/lightningnetwork/lnd/clock v1.0.1/go.mod h1:KnQudQ6w0IAMZi1SgvecLZQZ43ra2vpDNj7H/aasemg= -github.com/lightningnetwork/lnd/healthcheck v1.0.0/go.mod h1:u92p1JGFJNMSkMvztKEwmt1P3TRnLeJBXZ3M85xkU1E= -github.com/lightningnetwork/lnd/kvdb v1.0.0/go.mod h1:NMZdCUmFmS6dezJo1uSUM7GRjKTVksQrIfinoyKIGAI= -github.com/lightningnetwork/lnd/queue v1.0.1/go.mod h1:vaQwexir73flPW43Mrm7JOgJHmcEFBWWSl9HlyASoms= -github.com/lightningnetwork/lnd/queue v1.0.4/go.mod h1:YTkTVZCxz8tAYreH27EO3s8572ODumWrNdYW2E/YKxg= -github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0= -github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796/go.mod h1:3p7ZTf9V1sNPI5H8P3NkTFF4LuwMdPl2DodF60qAKqY= -github.com/ltcsuite/ltcutil v0.0.0-20181217130922-17f3b04680b6/go.mod h1:8Vg/LTOO0KYa/vlHWJ6XZAevPQThGH5sufO0Hrou/lA= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8 h1:PRMAcldsl4mXKJeRNB/KVNz6TlbS6hk2Rs42PqgU3Ws= -github.com/miekg/dns v0.0.0-20171125082028-79bfde677fa8/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/lightningnetwork/lnd/tor v1.1.0 h1:iXO7fSzjxTI+p88KmtpbuyuRJeNfgtpl9QeaAliILXE= +github.com/lightningnetwork/lnd/tor v1.1.0/go.mod h1:RDtaAdwfAm+ONuPYwUhNIH1RAvKPv+75lHPOegUcz64= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tv42/zbase32 v0.0.0-20160707012821-501572607d02/go.mod h1:tHlrkM198S068ZqfrO6S8HsoJq2bF3ETfTL+kt4tInY= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.5.0-alpha.5.0.20201125193152-8a03d2e9614b/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg= -golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426080607-c94f62235c83 h1:kHSDPqCtsHZOg0nVylfTo20DDhE9gG4Y0jn7hKQ0QAM= -golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v1 v1.0.1/go.mod h1:3NjfXwocQRYAPTq4/fzX+CwUhPRcR/azYRhj8G+LqMo= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/macaroon-bakery.v2 v2.0.1/go.mod h1:B4/T17l+ZWGwxFSZQmlBwp25x+og7OkhETfr3S9MbIA= -gopkg.in/macaroon.v2 v2.0.0/go.mod h1:+I6LnTMkm/uV5ew/0nsulNjL16SK4+C8yDmRUzHR17I= -gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= From f61ae6913437bb670c03061e9745cf42d80d16c3 Mon Sep 17 00:00:00 2001 From: roshii Date: Tue, 20 Sep 2022 13:47:34 +0200 Subject: [PATCH 03/24] Use low QR error correction and green background Low error correction slightly reduces QR size. Green background helps at reducing LCD blooming --- lndconnect.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lndconnect.go b/lndconnect.go index 25d9933..9573ac3 100644 --- a/lndconnect.go +++ b/lndconnect.go @@ -4,14 +4,15 @@ import ( b64 "encoding/base64" "encoding/pem" "fmt" + "image/color" "io/ioutil" "net" "net/url" "os" "strings" - "github.com/Baozisoftware/qrcode-terminal-go" - "github.com/glendc/go-external-ip" + qrcodeTerminal "github.com/Baozisoftware/qrcode-terminal-go" + externalip "github.com/glendc/go-external-ip" "github.com/skip2/go-qrcode" ) @@ -126,10 +127,11 @@ func displayLink(loadedConfig *config) { if loadedConfig.LndConnect.Url { fmt.Println(u.String()) } else if loadedConfig.LndConnect.Image { - qrcode.WriteFile(u.String(), qrcode.Medium, 512, "lndconnect-qr.png") + BrightGreen := color.RGBA{95, 191, 95, 255} + qrcode.WriteColorFile(u.String(), qrcode.Low, 512, BrightGreen, color.Black, "lndconnect-qr.png") fmt.Println("Wrote QR Code to file \"lndconnect-qr.png\"") } else { - obj := qrcodeTerminal.New() + obj := qrcodeTerminal.New2(qrcodeTerminal.ConsoleColors.BrightBlack, qrcodeTerminal.ConsoleColors.BrightGreen, qrcodeTerminal.QRCodeRecoveryLevels.Low) obj.Get(u.String()).Print() fmt.Println("\n⚠️ Press \"cmd + -\" a few times to see the full QR Code!\nIf that doesn't work run \"lndconnect -j\" to get a code you can copy paste into the app.") } From baa273d72381981a51c02e3f9096f0e24a829257 Mon Sep 17 00:00:00 2001 From: roshii Date: Wed, 21 Sep 2022 17:52:49 +0200 Subject: [PATCH 04/24] move URI related code --- lndconnect_test.go | 76 ------------------------------ uri.go | 112 +++++++++++++++++++++++++++++++++++++++++++++ uri_test.go | 93 +++++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+), 76 deletions(-) delete mode 100644 lndconnect_test.go create mode 100644 uri.go create mode 100644 uri_test.go diff --git a/lndconnect_test.go b/lndconnect_test.go deleted file mode 100644 index 246696c..0000000 --- a/lndconnect_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package main - -func ExampleLocalhost() { - c := &config{ - TLSCertPath: "testdata/tls.cert", - AdminMacPath: "testdata/admin.macaroon", - LndConnect: &lndConnectConfig{ - Localhost: true, - Url: true, - }, - } - displayLink(c) - - // Output: lndconnect://127.0.0.1:0?cert=MIICiDCCAi-gAwIBAgIQdo5v0QBXHnji4hRaeeMjNDAKBggqhkjOPQQDAjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwHhcNMTgwODIzMDU1ODEwWhcNMTkxMDE4MDU1ODEwWjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASFhRm-w_T10PoKtg4lm9hBNJjJD473fkzHwPUFwy91vTrQSf7543j2JrgFo8mbTV0VtpgqkfK1IMVKMLrF21xio4H8MIH5MA4GA1UdDwEB_wQEAwICpDAPBgNVHRMBAf8EBTADAQH_MIHVBgNVHREEgc0wgcqCG0p1c3R1c3MtTWFjQm9vay1Qcm8tMy5sb2NhbIIJbG9jYWxob3N0ggR1bml4ggp1bml4cGFja2V0hwR_AAABhxAAAAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAwlc9Zck7bDhwTAqAEEhxD-gAAAAAAAABiNp__-GxXGhxD-gAAAAAAAAKWJ5tliDORjhwQKDwAChxD-gAAAAAAAAG6Wz__-3atFhxD92tDQyv4TAQAAAAAAABAAMAoGCCqGSM49BAMCA0cAMEQCIA9O9xtazmdxCKj0MfbFHVBq5I7JMnOFPpwRPJXQfrYaAiBd5NyJQCwlSx5ECnPOH5sRpv26T8aUcXbmynx9CoDufA&macaroon=AgEDbG5kArsBAwoQ3_I9f6kgSE6aUPd85lWpOBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaFgoHbWVzc2FnZRIEcmVhZBIFd3JpdGUaFwoIb2ZmY2hhaW4SBHJlYWQSBXdyaXRlGhYKB29uY2hhaW4SBHJlYWQSBXdyaXRlGhQKBXBlZXJzEgRyZWFkEgV3cml0ZQAABiAiUTBv3Eh6iDbdjmXCfNxp4HBEcOYNzXhrm-ncLHf5jA -} - -func ExampleQuery() { - c := &config{ - TLSCertPath: "testdata/tls.cert", - AdminMacPath: "testdata/admin.macaroon", - LndConnect: &lndConnectConfig{ - Localhost: true, - Url: true, - Query: arrayFlags{"test=abc"}, - }, - } - displayLink(c) - - // Output: lndconnect://127.0.0.1:0?cert=MIICiDCCAi-gAwIBAgIQdo5v0QBXHnji4hRaeeMjNDAKBggqhkjOPQQDAjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwHhcNMTgwODIzMDU1ODEwWhcNMTkxMDE4MDU1ODEwWjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASFhRm-w_T10PoKtg4lm9hBNJjJD473fkzHwPUFwy91vTrQSf7543j2JrgFo8mbTV0VtpgqkfK1IMVKMLrF21xio4H8MIH5MA4GA1UdDwEB_wQEAwICpDAPBgNVHRMBAf8EBTADAQH_MIHVBgNVHREEgc0wgcqCG0p1c3R1c3MtTWFjQm9vay1Qcm8tMy5sb2NhbIIJbG9jYWxob3N0ggR1bml4ggp1bml4cGFja2V0hwR_AAABhxAAAAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAwlc9Zck7bDhwTAqAEEhxD-gAAAAAAAABiNp__-GxXGhxD-gAAAAAAAAKWJ5tliDORjhwQKDwAChxD-gAAAAAAAAG6Wz__-3atFhxD92tDQyv4TAQAAAAAAABAAMAoGCCqGSM49BAMCA0cAMEQCIA9O9xtazmdxCKj0MfbFHVBq5I7JMnOFPpwRPJXQfrYaAiBd5NyJQCwlSx5ECnPOH5sRpv26T8aUcXbmynx9CoDufA&macaroon=AgEDbG5kArsBAwoQ3_I9f6kgSE6aUPd85lWpOBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaFgoHbWVzc2FnZRIEcmVhZBIFd3JpdGUaFwoIb2ZmY2hhaW4SBHJlYWQSBXdyaXRlGhYKB29uY2hhaW4SBHJlYWQSBXdyaXRlGhQKBXBlZXJzEgRyZWFkEgV3cml0ZQAABiAiUTBv3Eh6iDbdjmXCfNxp4HBEcOYNzXhrm-ncLHf5jA&test=abc -} - -func ExamplePort() { - c := &config{ - TLSCertPath: "testdata/tls.cert", - AdminMacPath: "testdata/admin.macaroon", - LndConnect: &lndConnectConfig{ - Localhost: true, - Url: true, - Port: 123, - }, - } - displayLink(c) - - // Output: lndconnect://127.0.0.1:123?cert=MIICiDCCAi-gAwIBAgIQdo5v0QBXHnji4hRaeeMjNDAKBggqhkjOPQQDAjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwHhcNMTgwODIzMDU1ODEwWhcNMTkxMDE4MDU1ODEwWjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASFhRm-w_T10PoKtg4lm9hBNJjJD473fkzHwPUFwy91vTrQSf7543j2JrgFo8mbTV0VtpgqkfK1IMVKMLrF21xio4H8MIH5MA4GA1UdDwEB_wQEAwICpDAPBgNVHRMBAf8EBTADAQH_MIHVBgNVHREEgc0wgcqCG0p1c3R1c3MtTWFjQm9vay1Qcm8tMy5sb2NhbIIJbG9jYWxob3N0ggR1bml4ggp1bml4cGFja2V0hwR_AAABhxAAAAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAwlc9Zck7bDhwTAqAEEhxD-gAAAAAAAABiNp__-GxXGhxD-gAAAAAAAAKWJ5tliDORjhwQKDwAChxD-gAAAAAAAAG6Wz__-3atFhxD92tDQyv4TAQAAAAAAABAAMAoGCCqGSM49BAMCA0cAMEQCIA9O9xtazmdxCKj0MfbFHVBq5I7JMnOFPpwRPJXQfrYaAiBd5NyJQCwlSx5ECnPOH5sRpv26T8aUcXbmynx9CoDufA&macaroon=AgEDbG5kArsBAwoQ3_I9f6kgSE6aUPd85lWpOBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaFgoHbWVzc2FnZRIEcmVhZBIFd3JpdGUaFwoIb2ZmY2hhaW4SBHJlYWQSBXdyaXRlGhYKB29uY2hhaW4SBHJlYWQSBXdyaXRlGhQKBXBlZXJzEgRyZWFkEgV3cml0ZQAABiAiUTBv3Eh6iDbdjmXCfNxp4HBEcOYNzXhrm-ncLHf5jA -} - -func ExampleHost() { - c := &config{ - TLSCertPath: "testdata/tls.cert", - AdminMacPath: "testdata/admin.macaroon", - LndConnect: &lndConnectConfig{ - Localhost: true, - Url: true, - Host: "1.2.3.4", - }, - } - displayLink(c) - - // Output: lndconnect://1.2.3.4:0?cert=MIICiDCCAi-gAwIBAgIQdo5v0QBXHnji4hRaeeMjNDAKBggqhkjOPQQDAjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwHhcNMTgwODIzMDU1ODEwWhcNMTkxMDE4MDU1ODEwWjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASFhRm-w_T10PoKtg4lm9hBNJjJD473fkzHwPUFwy91vTrQSf7543j2JrgFo8mbTV0VtpgqkfK1IMVKMLrF21xio4H8MIH5MA4GA1UdDwEB_wQEAwICpDAPBgNVHRMBAf8EBTADAQH_MIHVBgNVHREEgc0wgcqCG0p1c3R1c3MtTWFjQm9vay1Qcm8tMy5sb2NhbIIJbG9jYWxob3N0ggR1bml4ggp1bml4cGFja2V0hwR_AAABhxAAAAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAwlc9Zck7bDhwTAqAEEhxD-gAAAAAAAABiNp__-GxXGhxD-gAAAAAAAAKWJ5tliDORjhwQKDwAChxD-gAAAAAAAAG6Wz__-3atFhxD92tDQyv4TAQAAAAAAABAAMAoGCCqGSM49BAMCA0cAMEQCIA9O9xtazmdxCKj0MfbFHVBq5I7JMnOFPpwRPJXQfrYaAiBd5NyJQCwlSx5ECnPOH5sRpv26T8aUcXbmynx9CoDufA&macaroon=AgEDbG5kArsBAwoQ3_I9f6kgSE6aUPd85lWpOBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaFgoHbWVzc2FnZRIEcmVhZBIFd3JpdGUaFwoIb2ZmY2hhaW4SBHJlYWQSBXdyaXRlGhYKB29uY2hhaW4SBHJlYWQSBXdyaXRlGhQKBXBlZXJzEgRyZWFkEgV3cml0ZQAABiAiUTBv3Eh6iDbdjmXCfNxp4HBEcOYNzXhrm-ncLHf5jA -} - -func ExampleNoCert() { - c := &config{ - TLSCertPath: "testdata/tls.cert", - AdminMacPath: "testdata/admin.macaroon", - LndConnect: &lndConnectConfig{ - Localhost: true, - Url: true, - Host: "1.2.3.4", - NoCert: true, - }, - } - displayLink(c) - - // Output: lndconnect://1.2.3.4:0?macaroon=AgEDbG5kArsBAwoQ3_I9f6kgSE6aUPd85lWpOBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaFgoHbWVzc2FnZRIEcmVhZBIFd3JpdGUaFwoIb2ZmY2hhaW4SBHJlYWQSBXdyaXRlGhYKB29uY2hhaW4SBHJlYWQSBXdyaXRlGhQKBXBlZXJzEgRyZWFkEgV3cml0ZQAABiAiUTBv3Eh6iDbdjmXCfNxp4HBEcOYNzXhrm-ncLHf5jA -} diff --git a/uri.go b/uri.go new file mode 100644 index 0000000..2df5ac1 --- /dev/null +++ b/uri.go @@ -0,0 +1,112 @@ +package main + +import ( + b64 "encoding/base64" + "encoding/pem" + "fmt" + "io/ioutil" + "net" + "net/url" + "os" + "strings" + + externalip "github.com/glendc/go-external-ip" +) + +func getLocalIP() string { + addrs, err := net.InterfaceAddrs() + if err != nil { + return "" + } + for _, address := range addrs { + if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + return ipnet.IP.String() + } + } + } + return "" +} + +func getPublicIP() string { + consensus := externalip.DefaultConsensus(nil, nil) + ip, err := consensus.ExternalIP() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + return ip.String() +} + +func getURI(loadedConfig *config) (string, error) { + var err error + + // host + ipString := "" + if loadedConfig.LndConnect.Host != "" { + ipString = loadedConfig.LndConnect.Host + } else if loadedConfig.LndConnect.LocalIp { + ipString = getLocalIP() + } else if loadedConfig.LndConnect.Localhost { + ipString = "127.0.0.1" + } else { + ipString = getPublicIP() + } + + ipString = net.JoinHostPort(ipString, fmt.Sprint(loadedConfig.LndConnect.Port)) + + u := url.URL{Scheme: "lndconnect", Host: ipString} + q := u.Query() + + // cert + if !loadedConfig.LndConnect.NoCert { + certBytes, err := ioutil.ReadFile(loadedConfig.TLSCertPath) + if err != nil { + return "", err + } + + block, _ := pem.Decode(certBytes) + if block == nil || block.Type != "CERTIFICATE" { + fmt.Println("failed to decode PEM block containing certificate") + } + + certificate := b64.RawURLEncoding.EncodeToString([]byte(block.Bytes)) + + q.Add("cert", certificate) + } + + // macaroon + var macBytes []byte + if loadedConfig.LndConnect.Invoice { + macBytes, err = ioutil.ReadFile(loadedConfig.InvoiceMacPath) + } else if loadedConfig.LndConnect.Readonly { + macBytes, err = ioutil.ReadFile(loadedConfig.ReadMacPath) + } else { + macBytes, err = ioutil.ReadFile(loadedConfig.AdminMacPath) + } + + if err != nil { + return "", err + } + + macaroonB64 := b64.RawURLEncoding.EncodeToString([]byte(macBytes)) + + q.Add("macaroon", macaroonB64) + + // custom query + for _, s := range loadedConfig.LndConnect.Query { + queryParts := strings.Split(s, "=") + + if len(queryParts) != 2 { + return "", fmt.Errorf("Invalid Query Argument: %s", s) + } + + q.Add(queryParts[0], queryParts[1]) + } + + u.RawQuery = q.Encode() + + fmt.Println("\nURI generated successfully.") + return u.String(), nil +} diff --git a/uri_test.go b/uri_test.go new file mode 100644 index 0000000..dedc8ae --- /dev/null +++ b/uri_test.go @@ -0,0 +1,93 @@ +package main + +import "testing" + +func ExampleLocalhost(t *testing.T) { + c := &config{ + TLSCertPath: "testdata/tls.cert", + AdminMacPath: "testdata/admin.macaroon", + LndConnect: &lndConnectConfig{ + Localhost: true, + Url: true, + }, + } + + want := "lndconnect://127.0.0.1:0?cert=MIICiDCCAi-gAwIBAgIQdo5v0QBXHnji4hRaeeMjNDAKBggqhkjOPQQDAjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwHhcNMTgwODIzMDU1ODEwWhcNMTkxMDE4MDU1ODEwWjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASFhRm-w_T10PoKtg4lm9hBNJjJD473fkzHwPUFwy91vTrQSf7543j2JrgFo8mbTV0VtpgqkfK1IMVKMLrF21xio4H8MIH5MA4GA1UdDwEB_wQEAwICpDAPBgNVHRMBAf8EBTADAQH_MIHVBgNVHREEgc0wgcqCG0p1c3R1c3MtTWFjQm9vay1Qcm8tMy5sb2NhbIIJbG9jYWxob3N0ggR1bml4ggp1bml4cGFja2V0hwR_AAABhxAAAAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAwlc9Zck7bDhwTAqAEEhxD-gAAAAAAAABiNp__-GxXGhxD-gAAAAAAAAKWJ5tliDORjhwQKDwAChxD-gAAAAAAAAG6Wz__-3atFhxD92tDQyv4TAQAAAAAAABAAMAoGCCqGSM49BAMCA0cAMEQCIA9O9xtazmdxCKj0MfbFHVBq5I7JMnOFPpwRPJXQfrYaAiBd5NyJQCwlSx5ECnPOH5sRpv26T8aUcXbmynx9CoDufA&macaroon=AgEDbG5kArsBAwoQ3_I9f6kgSE6aUPd85lWpOBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaFgoHbWVzc2FnZRIEcmVhZBIFd3JpdGUaFwoIb2ZmY2hhaW4SBHJlYWQSBXdyaXRlGhYKB29uY2hhaW4SBHJlYWQSBXdyaXRlGhQKBXBlZXJzEgRyZWFkEgV3cml0ZQAABiAiUTBv3Eh6iDbdjmXCfNxp4HBEcOYNzXhrm-ncLHf5jA" + uri, err := getURI(c) + if want != uri || err != nil { + t.FailNow() + } +} + +func ExampleQuery(t *testing.T) { + c := &config{ + TLSCertPath: "testdata/tls.cert", + AdminMacPath: "testdata/admin.macaroon", + LndConnect: &lndConnectConfig{ + Localhost: true, + Url: true, + Query: arrayFlags{"test=abc"}, + }, + } + + want := "lndconnect://127.0.0.1:0?cert=MIICiDCCAi-gAwIBAgIQdo5v0QBXHnji4hRaeeMjNDAKBggqhkjOPQQDAjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwHhcNMTgwODIzMDU1ODEwWhcNMTkxMDE4MDU1ODEwWjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASFhRm-w_T10PoKtg4lm9hBNJjJD473fkzHwPUFwy91vTrQSf7543j2JrgFo8mbTV0VtpgqkfK1IMVKMLrF21xio4H8MIH5MA4GA1UdDwEB_wQEAwICpDAPBgNVHRMBAf8EBTADAQH_MIHVBgNVHREEgc0wgcqCG0p1c3R1c3MtTWFjQm9vay1Qcm8tMy5sb2NhbIIJbG9jYWxob3N0ggR1bml4ggp1bml4cGFja2V0hwR_AAABhxAAAAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAwlc9Zck7bDhwTAqAEEhxD-gAAAAAAAABiNp__-GxXGhxD-gAAAAAAAAKWJ5tliDORjhwQKDwAChxD-gAAAAAAAAG6Wz__-3atFhxD92tDQyv4TAQAAAAAAABAAMAoGCCqGSM49BAMCA0cAMEQCIA9O9xtazmdxCKj0MfbFHVBq5I7JMnOFPpwRPJXQfrYaAiBd5NyJQCwlSx5ECnPOH5sRpv26T8aUcXbmynx9CoDufA&macaroon=AgEDbG5kArsBAwoQ3_I9f6kgSE6aUPd85lWpOBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaFgoHbWVzc2FnZRIEcmVhZBIFd3JpdGUaFwoIb2ZmY2hhaW4SBHJlYWQSBXdyaXRlGhYKB29uY2hhaW4SBHJlYWQSBXdyaXRlGhQKBXBlZXJzEgRyZWFkEgV3cml0ZQAABiAiUTBv3Eh6iDbdjmXCfNxp4HBEcOYNzXhrm-ncLHf5jA&test=abc" + uri, err := getURI(c) + if want != uri || err != nil { + t.FailNow() + } +} + +func ExamplePort(t *testing.T) { + c := &config{ + TLSCertPath: "testdata/tls.cert", + AdminMacPath: "testdata/admin.macaroon", + LndConnect: &lndConnectConfig{ + Localhost: true, + Url: true, + Port: 123, + }, + } + + want := "lndconnect://127.0.0.1:123?cert=MIICiDCCAi-gAwIBAgIQdo5v0QBXHnji4hRaeeMjNDAKBggqhkjOPQQDAjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwHhcNMTgwODIzMDU1ODEwWhcNMTkxMDE4MDU1ODEwWjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASFhRm-w_T10PoKtg4lm9hBNJjJD473fkzHwPUFwy91vTrQSf7543j2JrgFo8mbTV0VtpgqkfK1IMVKMLrF21xio4H8MIH5MA4GA1UdDwEB_wQEAwICpDAPBgNVHRMBAf8EBTADAQH_MIHVBgNVHREEgc0wgcqCG0p1c3R1c3MtTWFjQm9vay1Qcm8tMy5sb2NhbIIJbG9jYWxob3N0ggR1bml4ggp1bml4cGFja2V0hwR_AAABhxAAAAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAwlc9Zck7bDhwTAqAEEhxD-gAAAAAAAABiNp__-GxXGhxD-gAAAAAAAAKWJ5tliDORjhwQKDwAChxD-gAAAAAAAAG6Wz__-3atFhxD92tDQyv4TAQAAAAAAABAAMAoGCCqGSM49BAMCA0cAMEQCIA9O9xtazmdxCKj0MfbFHVBq5I7JMnOFPpwRPJXQfrYaAiBd5NyJQCwlSx5ECnPOH5sRpv26T8aUcXbmynx9CoDufA&macaroon=AgEDbG5kArsBAwoQ3_I9f6kgSE6aUPd85lWpOBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaFgoHbWVzc2FnZRIEcmVhZBIFd3JpdGUaFwoIb2ZmY2hhaW4SBHJlYWQSBXdyaXRlGhYKB29uY2hhaW4SBHJlYWQSBXdyaXRlGhQKBXBlZXJzEgRyZWFkEgV3cml0ZQAABiAiUTBv3Eh6iDbdjmXCfNxp4HBEcOYNzXhrm-ncLHf5jA" + uri, err := getURI(c) + if want != uri || err != nil { + t.FailNow() + } +} + +func ExampleHost(t *testing.T) { + c := &config{ + TLSCertPath: "testdata/tls.cert", + AdminMacPath: "testdata/admin.macaroon", + LndConnect: &lndConnectConfig{ + Localhost: true, + Url: true, + Host: "1.2.3.4", + }, + } + + want := "lndconnect://1.2.3.4:0?cert=MIICiDCCAi-gAwIBAgIQdo5v0QBXHnji4hRaeeMjNDAKBggqhkjOPQQDAjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwHhcNMTgwODIzMDU1ODEwWhcNMTkxMDE4MDU1ODEwWjBHMR8wHQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MSQwIgYDVQQDExtKdXN0dXNzLU1hY0Jvb2stUHJvLTMubG9jYWwwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASFhRm-w_T10PoKtg4lm9hBNJjJD473fkzHwPUFwy91vTrQSf7543j2JrgFo8mbTV0VtpgqkfK1IMVKMLrF21xio4H8MIH5MA4GA1UdDwEB_wQEAwICpDAPBgNVHRMBAf8EBTADAQH_MIHVBgNVHREEgc0wgcqCG0p1c3R1c3MtTWFjQm9vay1Qcm8tMy5sb2NhbIIJbG9jYWxob3N0ggR1bml4ggp1bml4cGFja2V0hwR_AAABhxAAAAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAAAAAAAAAABhxD-gAAAAAAAAAwlc9Zck7bDhwTAqAEEhxD-gAAAAAAAABiNp__-GxXGhxD-gAAAAAAAAKWJ5tliDORjhwQKDwAChxD-gAAAAAAAAG6Wz__-3atFhxD92tDQyv4TAQAAAAAAABAAMAoGCCqGSM49BAMCA0cAMEQCIA9O9xtazmdxCKj0MfbFHVBq5I7JMnOFPpwRPJXQfrYaAiBd5NyJQCwlSx5ECnPOH5sRpv26T8aUcXbmynx9CoDufA&macaroon=AgEDbG5kArsBAwoQ3_I9f6kgSE6aUPd85lWpOBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaFgoHbWVzc2FnZRIEcmVhZBIFd3JpdGUaFwoIb2ZmY2hhaW4SBHJlYWQSBXdyaXRlGhYKB29uY2hhaW4SBHJlYWQSBXdyaXRlGhQKBXBlZXJzEgRyZWFkEgV3cml0ZQAABiAiUTBv3Eh6iDbdjmXCfNxp4HBEcOYNzXhrm-ncLHf5jA" + uri, err := getURI(c) + if want != uri || err != nil { + t.FailNow() + } +} + +func ExampleNoCert(t *testing.T) { + c := &config{ + TLSCertPath: "testdata/tls.cert", + AdminMacPath: "testdata/admin.macaroon", + LndConnect: &lndConnectConfig{ + Localhost: true, + Url: true, + Host: "1.2.3.4", + NoCert: true, + }, + } + + want := "lndconnect://1.2.3.4:0?macaroon=AgEDbG5kArsBAwoQ3_I9f6kgSE6aUPd85lWpOBIBMBoWCgdhZGRyZXNzEgRyZWFkEgV3cml0ZRoTCgRpbmZvEgRyZWFkEgV3cml0ZRoXCghpbnZvaWNlcxIEcmVhZBIFd3JpdGUaFgoHbWVzc2FnZRIEcmVhZBIFd3JpdGUaFwoIb2ZmY2hhaW4SBHJlYWQSBXdyaXRlGhYKB29uY2hhaW4SBHJlYWQSBXdyaXRlGhQKBXBlZXJzEgRyZWFkEgV3cml0ZQAABiAiUTBv3Eh6iDbdjmXCfNxp4HBEcOYNzXhrm-ncLHf5jA" + uri, err := getURI(c) + if want != uri || err != nil { + t.FailNow() + } +} From 46f807514ef2850b9354f1a3d0b64d73604ce7d2 Mon Sep 17 00:00:00 2001 From: roshii Date: Wed, 21 Sep 2022 17:53:39 +0200 Subject: [PATCH 05/24] define MockEncrypter refer to https://github.com/lightningnetwork/lnd/pull/6526 for more information --- crypto.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 crypto.go diff --git a/crypto.go b/crypto.go new file mode 100644 index 0000000..1974ddd --- /dev/null +++ b/crypto.go @@ -0,0 +1,13 @@ +package main + +import "io" + +type MockEncrypter struct{} + +func (m MockEncrypter) EncryptPayloadToWriter(_ []byte, _ io.Writer) error { + return nil +} + +func (m MockEncrypter) DecryptPayloadFromReader(_ io.Reader) ([]byte, error) { + return []byte("hello world!"), nil +} From 59e3848a114c46e0e0ad8604e9f6ccc142e05032 Mon Sep 17 00:00:00 2001 From: roshii Date: Wed, 21 Sep 2022 17:56:19 +0200 Subject: [PATCH 06/24] add tor onion service support allows to automatically create onion service for LND REST interface --- config.go | 57 ++++++++++++++-------- lndconnect.go | 128 +++++++++----------------------------------------- tor.go | 80 +++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 124 deletions(-) create mode 100644 tor.go diff --git a/config.go b/config.go index da18374..bab132c 100644 --- a/config.go +++ b/config.go @@ -25,6 +25,8 @@ const ( defaultReadMacFilename = "readonly.macaroon" defaultInvoiceMacFilename = "invoice.macaroon" defaultRPCPort = 10009 + defaultRESTPort = 8080 + defaultRESTKeyFileName = "rest_onion_private_key" ) var ( @@ -32,6 +34,7 @@ var ( defaultConfigFile = filepath.Join(defaultLndDir, defaultConfigFilename) defaultDataDir = filepath.Join(defaultLndDir, defaultDataDirname) defaultTLSCertPath = filepath.Join(defaultLndDir, defaultTLSCertFilename) + defaultRESTKeyPath = filepath.Join(defaultLndDir, defaultRESTKeyFileName) ) type chainConfig struct { @@ -42,19 +45,29 @@ type chainConfig struct { RegTest bool `long:"regtest" description:"Use the regression test network"` } +type torConfig struct { + Active bool `long:"active" description:"Allow outbound and inbound connections to be routed through Tor"` + V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"` + Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"` + TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"` + Password string `long:"password" description:"If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."` + RESTKeyPath string `short:"r" long:"restkeypath" description:"The path to the private key of the onion service being created if provided."` +} + type arrayFlags []string type lndConnectConfig struct { - LocalIp bool `short:"i" long:"localip" description:"Include local ip in QRCode"` - Localhost bool `short:"l" long:"localhost" description:"Use 127.0.0.1 for ip"` - Host string `long:"host" description:"Use specific host name"` - NoCert bool `long:"nocert" description:"Don't include the certificate"` - Port uint16 `short:"p" long:"port" description:"Use this port"` - Url bool `short:"j" long:"url" description:"Display url instead of a QRCode"` - Image bool `short:"o" long:"image" description:"Output QRCode to file"` - Invoice bool `long:"invoice" description:"Use invoice macaroon"` - Readonly bool `long:"readonly" description:"Use readonly macaroon"` - Query arrayFlags `short:"q" long:"query" description:"Add additional url query parameters"` + LocalIp bool `short:"i" long:"localip" description:"Include local ip in QRCode"` + Localhost bool `short:"l" long:"localhost" description:"Use 127.0.0.1 for ip"` + Host string `long:"host" description:"Use specific host name"` + NoCert bool `long:"nocert" description:"Don't include the certificate"` + Port uint16 `short:"p" long:"port" description:"Use this port"` + Url bool `short:"j" long:"url" description:"Display url instead of a QRCode"` + Image bool `short:"o" long:"image" description:"Output QRCode to file"` + Invoice bool `long:"invoice" description:"Use invoice macaroon"` + Readonly bool `long:"readonly" description:"Use readonly macaroon"` + Query arrayFlags `short:"q" long:"query" description:"Add additional url query parameters"` + CreateOnion bool `short:"c" long:"createonion" description:"Create onion v3 hidden service to access REST interface."` } // config defines the configuration options for lndconnect. @@ -64,17 +77,20 @@ type lndConnectConfig struct { type config struct { LndConnect *lndConnectConfig `group:"LndConnect"` - LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."` - ConfigFile string `long:"C" long:"configfile" description:"Path to configuration file"` - DataDir string `short:"b" long:"datadir" description:"The directory to find lnd's data within"` - TLSCertPath string `long:"tlscertpath" description:"Path to read the TLS certificate from"` - AdminMacPath string `long:"adminmacaroonpath" description:"Path to read the admin macaroon from"` - ReadMacPath string `long:"readonlymacaroonpath" description:"Path to read the read-only macaroon from"` - InvoiceMacPath string `long:"invoicemacaroonpath" description:"Path to read the invoice-only macaroon from"` + LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."` + ConfigFile string `long:"C" long:"configfile" description:"Path to configuration file"` + DataDir string `short:"b" long:"datadir" description:"The directory to find lnd's data within"` + TLSCertPath string `long:"tlscertpath" description:"Path to read the TLS certificate from"` + AdminMacPath string `long:"adminmacaroonpath" description:"Path to read the admin macaroon from"` + ReadMacPath string `long:"readonlymacaroonpath" description:"Path to read the read-only macaroon from"` + InvoiceMacPath string `long:"invoicemacaroonpath" description:"Path to read the invoice-only macaroon from"` + RawRESTListeners []string `long:"restlisten" description:"Interface/Port/Socket listening for REST connections"` Bitcoin *chainConfig `group:"Bitcoin" namespace:"bitcoin"` Litecoin *chainConfig `group:"Litecoin" namespace:"litecoin"` + Tor *torConfig `group:"Tor" namespace:"tor"` + // The following lines we only need to be able to parse the // configuration INI file without errors. The content will be ignored. BtcdMode *chainConfig `hidden:"true" group:"btcd" namespace:"btcd"` @@ -83,7 +99,6 @@ type config struct { LtcdMode *chainConfig `hidden:"true" group:"ltcd" namespace:"ltcd"` LitecoindMode *chainConfig `hidden:"true" group:"litecoind" namespace:"litecoind"` Autopilot *chainConfig `hidden:"true" group:"Autopilot" namespace:"autopilot"` - Tor *chainConfig `hidden:"true" group:"Tor" namespace:"tor"` Hodl *chainConfig `hidden:"true" group:"hodl" namespace:"hodl"` net tor.Net @@ -106,7 +121,10 @@ func loadConfig() (*config, error) { ConfigFile: defaultConfigFile, DataDir: defaultDataDir, TLSCertPath: defaultTLSCertPath, - net: &tor.ClearNet{}, + Tor: &torConfig{ + RESTKeyPath: defaultRESTKeyPath, + }, + net: &tor.ClearNet{}, } // Pre-parse the command line options to pick up an alternative config @@ -130,6 +148,7 @@ func loadConfig() (*config, error) { } preCfg.DataDir = filepath.Join(lndDir, defaultDataDirname) preCfg.TLSCertPath = filepath.Join(lndDir, defaultTLSCertFilename) + preCfg.Tor.RESTKeyPath = filepath.Join(lndDir, defaultRESTKeyFileName) } // Next, load any additional configuration options from the file. diff --git a/lndconnect.go b/lndconnect.go index 9573ac3..0a90ed4 100644 --- a/lndconnect.go +++ b/lndconnect.go @@ -1,138 +1,56 @@ package main import ( - b64 "encoding/base64" - "encoding/pem" "fmt" "image/color" - "io/ioutil" - "net" - "net/url" - "os" + "log" + "strconv" "strings" qrcodeTerminal "github.com/Baozisoftware/qrcode-terminal-go" - externalip "github.com/glendc/go-external-ip" "github.com/skip2/go-qrcode" ) -func getLocalIP() string { - addrs, err := net.InterfaceAddrs() - if err != nil { - return "" - } - for _, address := range addrs { - if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { - if ipnet.IP.To4() != nil { - return ipnet.IP.String() - } - } - } - return "" -} - -func getPublicIP() string { - consensus := externalip.DefaultConsensus(nil, nil) - ip, err := consensus.ExternalIP() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - return ip.String() -} - func main() { loadedConfig, err := loadConfig() if err != nil { - fmt.Println(err) - return + log.Fatal(err) } - displayLink(loadedConfig) -} - -func displayLink(loadedConfig *config) { - var err error - - // host - ipString := "" - if loadedConfig.LndConnect.Host != "" { - ipString = loadedConfig.LndConnect.Host - } else if loadedConfig.LndConnect.LocalIp { - ipString = getLocalIP() - } else if loadedConfig.LndConnect.Localhost { - ipString = "127.0.0.1" - } else { - ipString = getPublicIP() - } - - ipString = net.JoinHostPort(ipString, fmt.Sprint(loadedConfig.LndConnect.Port)) - - u := url.URL{Scheme: "lndconnect", Host: ipString} - q := u.Query() - - // cert - if !loadedConfig.LndConnect.NoCert { - certBytes, err := ioutil.ReadFile(loadedConfig.TLSCertPath) + if loadedConfig.LndConnect.CreateOnion { + addr, err := createNewHiddenService(loadedConfig) if err != nil { - fmt.Println(err) - return + log.Fatal(err) } - - block, _ := pem.Decode(certBytes) - if block == nil || block.Type != "CERTIFICATE" { - fmt.Println("failed to decode PEM block containing certificate") + parsedAddr := strings.Split(addr, ":") + loadedConfig.LndConnect.Host = parsedAddr[0] + parsedPort, err := strconv.ParseUint(parsedAddr[1], 10, 16) + if err != nil { + log.Fatal(err) } - - certificate := b64.RawURLEncoding.EncodeToString([]byte(block.Bytes)) - - q.Add("cert", certificate) - } - - // macaroon - var macBytes []byte - if loadedConfig.LndConnect.Invoice { - macBytes, err = ioutil.ReadFile(loadedConfig.InvoiceMacPath) - } else if loadedConfig.LndConnect.Readonly { - macBytes, err = ioutil.ReadFile(loadedConfig.ReadMacPath) - } else { - macBytes, err = ioutil.ReadFile(loadedConfig.AdminMacPath) + loadedConfig.LndConnect.Port = uint16(parsedPort) + loadedConfig.LndConnect.NoCert = true } + // Generate URI + uri, err := getURI(loadedConfig) if err != nil { - fmt.Println(err) - return - } - - macaroonB64 := b64.RawURLEncoding.EncodeToString([]byte(macBytes)) - - q.Add("macaroon", macaroonB64) - - // custom query - for _, s := range loadedConfig.LndConnect.Query { - queryParts := strings.Split(s, "=") - - if len(queryParts) != 2 { - fmt.Println("Invalid Query Argument:", s) - return - } - - q.Add(queryParts[0], queryParts[1]) + log.Fatal(err) } - u.RawQuery = q.Encode() - - // generate link / QR Code + // Print URI or QR Code to selected output if loadedConfig.LndConnect.Url { - fmt.Println(u.String()) + fmt.Println(uri) + } else if loadedConfig.LndConnect.Image { BrightGreen := color.RGBA{95, 191, 95, 255} - qrcode.WriteColorFile(u.String(), qrcode.Low, 512, BrightGreen, color.Black, "lndconnect-qr.png") + qrcode.WriteColorFile(uri, qrcode.Low, 512, BrightGreen, color.Black, "lndconnect-qr.png") fmt.Println("Wrote QR Code to file \"lndconnect-qr.png\"") + } else { obj := qrcodeTerminal.New2(qrcodeTerminal.ConsoleColors.BrightBlack, qrcodeTerminal.ConsoleColors.BrightGreen, qrcodeTerminal.QRCodeRecoveryLevels.Low) - obj.Get(u.String()).Print() + obj.Get(uri).Print() fmt.Println("\n⚠️ Press \"cmd + -\" a few times to see the full QR Code!\nIf that doesn't work run \"lndconnect -j\" to get a code you can copy paste into the app.") } + } diff --git a/tor.go b/tor.go new file mode 100644 index 0000000..f14f700 --- /dev/null +++ b/tor.go @@ -0,0 +1,80 @@ +package main + +import ( + "fmt" + "strconv" + "strings" + + "github.com/lightningnetwork/lnd/tor" +) + +// createNewHiddenService automatically sets up a v3 onion service in +// order to listen for inbound connections over Tor. +func createNewHiddenService(loadedConfig *config) (string, error) { + + // If tor is active make a tor controller for creating onion REST service interface + var torController *tor.Controller + if loadedConfig.Tor.Active && loadedConfig.Tor.V3 { + torController = tor.NewController( + loadedConfig.Tor.Control, loadedConfig.Tor.TargetIPAddress, + loadedConfig.Tor.Password, + ) + + // Start the tor controller before giving it to any other + // subsystems. + if err := torController.Start(); err != nil { + return "", err + } + defer func() { + if err := torController.Stop(); err != nil { + fmt.Printf("error stopping tor "+ + "controller: %v", err) + } + }() + } else { + return "", fmt.Errorf("Either tor is inactive or v3 onion service are disabled, check configuration.") + } + + // Determine the different ports the server is listening on. The onion + // service's virtual port will map to these ports and one will be picked + // at random when the onion service is being accessed. + restListenPorts := make([]int, 0, len(loadedConfig.RawRESTListeners)) + for _, RawRESTListener := range loadedConfig.RawRESTListeners { + + // Addresses can either be in network://address:port format, + // network:address:port, address:port, or just port. We want to support + // all possible types. + var parsedPort string + if strings.Contains(RawRESTListener, ":") { + parts := strings.Split(RawRESTListener, ":") + parsedPort = parts[len(parts)-1] + } else { + parsedPort = RawRESTListener + } + port, err := strconv.Atoi(parsedPort) + if err != nil { + return "", err + } + restListenPorts = append(restListenPorts, port) + } + + // Once the port mapping has been set, we can go ahead and automatically + // create our onion service. The service's private key will be saved to + // disk in order to regain access to this service when restarting `lnd`. + + onionCfg := tor.AddOnionConfig{ + VirtualPort: defaultRESTPort, + TargetPorts: restListenPorts, + Store: tor.NewOnionFile(loadedConfig.Tor.RESTKeyPath, 0600, false, MockEncrypter{}), + Type: tor.V3, + } + + addr, err := torController.AddOnion(onionCfg) + if err != nil { + return "", err + } + fmt.Println("\nOnion service created for LND REST interface, address reads:") + fmt.Println(addr) + + return addr.String(), nil +} From 81d8f0b9e02de069f886b48c490db805cb7238b4 Mon Sep 17 00:00:00 2001 From: roshii Date: Wed, 21 Sep 2022 17:57:18 +0200 Subject: [PATCH 07/24] dev config --- .gitignore | 5 +++++ Makefile | 19 +++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 02aaabc..75ab010 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,8 @@ *.out build + +# Development files and folders +.data +lndconnect +*.png \ No newline at end of file diff --git a/Makefile b/Makefile index 64f1c28..193df84 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,17 @@ -default: install +BINARY_NAME=lndconnect +GOARCH=amd64 +GOOS=linux -dep: - go get ./... +default: run + +build: + go build -o ${BINARY_NAME} -install: dep - go install -v ./... +run: build + ./${BINARY_NAME} --lnddir .data -j -c + +dep: + go mod download -test: +test: dep go test -v \ No newline at end of file From 56ade796602e14219fb2c80c6bb8a4b30077d8e6 Mon Sep 17 00:00:00 2001 From: roshii Date: Wed, 21 Sep 2022 18:02:08 +0200 Subject: [PATCH 08/24] add REST onion usage instruction --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index f7115f7..899cd94 100644 --- a/README.md +++ b/README.md @@ -40,4 +40,7 @@ lndconnect --adminmacaroonpath= Path to read the admin macaroon from --readonlymacaroonpath= Path to read the read-only macaroon from --invoicemacaroonpath= Path to read the invoice-only macaroon from + +-c, --createonion Create onion hidden service to access REST interface +-r, --tor.restkeypath= The path to the private key of the onion service being created ``` From 6ded8dd4236c80d3c42ce04b4f2b3524a11e0800 Mon Sep 17 00:00:00 2001 From: roshii Date: Wed, 21 Sep 2022 18:02:25 +0200 Subject: [PATCH 09/24] fix option description --- config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.go b/config.go index bab132c..041ec61 100644 --- a/config.go +++ b/config.go @@ -50,8 +50,8 @@ type torConfig struct { V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"` Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"` TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"` - Password string `long:"password" description:"If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."` - RESTKeyPath string `short:"r" long:"restkeypath" description:"The path to the private key of the onion service being created if provided."` + Password string `long:"password" description:"If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one"` + RESTKeyPath string `short:"r" long:"restkeypath" description:"The path to the private key of the onion service being created"` } type arrayFlags []string From e990834dc78e94561dc969f9077c5b2cf73f3699 Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 09:15:48 +0200 Subject: [PATCH 10/24] set module path to github.com/roshii/lndconnect --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 1335ea6..b41c91c 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/LN-Zap/lndconnect +module github.com/roshii/lndconnect go 1.16 From d7def2d85af021752b7f6d185d8573a7b4ad4ea4 Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 11:22:37 +0200 Subject: [PATCH 11/24] add defaultQRFilePath write QR file to LndDir --- config.go | 2 ++ lndconnect.go | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/config.go b/config.go index bab132c..1b8e2c5 100644 --- a/config.go +++ b/config.go @@ -27,6 +27,7 @@ const ( defaultRPCPort = 10009 defaultRESTPort = 8080 defaultRESTKeyFileName = "rest_onion_private_key" + defaultQRFileName = "lndconnect-qr.png" ) var ( @@ -35,6 +36,7 @@ var ( defaultDataDir = filepath.Join(defaultLndDir, defaultDataDirname) defaultTLSCertPath = filepath.Join(defaultLndDir, defaultTLSCertFilename) defaultRESTKeyPath = filepath.Join(defaultLndDir, defaultRESTKeyFileName) + defaultQRFilePath = filepath.Join(defaultLndDir, defaultQRFileName) ) type chainConfig struct { diff --git a/lndconnect.go b/lndconnect.go index 0a90ed4..4ff3e29 100644 --- a/lndconnect.go +++ b/lndconnect.go @@ -44,8 +44,8 @@ func main() { } else if loadedConfig.LndConnect.Image { BrightGreen := color.RGBA{95, 191, 95, 255} - qrcode.WriteColorFile(uri, qrcode.Low, 512, BrightGreen, color.Black, "lndconnect-qr.png") - fmt.Println("Wrote QR Code to file \"lndconnect-qr.png\"") + qrcode.WriteColorFile(uri, qrcode.Low, 512, BrightGreen, color.Black, defaultQRFilePath) + fmt.Printf("\nWrote QR Code to file \"%s\"", defaultQRFilePath) } else { obj := qrcodeTerminal.New2(qrcodeTerminal.ConsoleColors.BrightBlack, qrcodeTerminal.ConsoleColors.BrightGreen, qrcodeTerminal.QRCodeRecoveryLevels.Low) From 3afb135991e06a2cd06f1c4d98c85ae1925e3321 Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 13:15:37 +0200 Subject: [PATCH 12/24] move qr code logic to uri --- lndconnect.go | 14 +------------- uri.go | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/lndconnect.go b/lndconnect.go index 4ff3e29..ec214e8 100644 --- a/lndconnect.go +++ b/lndconnect.go @@ -2,13 +2,9 @@ package main import ( "fmt" - "image/color" "log" "strconv" "strings" - - qrcodeTerminal "github.com/Baozisoftware/qrcode-terminal-go" - "github.com/skip2/go-qrcode" ) func main() { @@ -42,15 +38,7 @@ func main() { if loadedConfig.LndConnect.Url { fmt.Println(uri) - } else if loadedConfig.LndConnect.Image { - BrightGreen := color.RGBA{95, 191, 95, 255} - qrcode.WriteColorFile(uri, qrcode.Low, 512, BrightGreen, color.Black, defaultQRFilePath) - fmt.Printf("\nWrote QR Code to file \"%s\"", defaultQRFilePath) - } else { - obj := qrcodeTerminal.New2(qrcodeTerminal.ConsoleColors.BrightBlack, qrcodeTerminal.ConsoleColors.BrightGreen, qrcodeTerminal.QRCodeRecoveryLevels.Low) - obj.Get(uri).Print() - fmt.Println("\n⚠️ Press \"cmd + -\" a few times to see the full QR Code!\nIf that doesn't work run \"lndconnect -j\" to get a code you can copy paste into the app.") + getQR(uri, loadedConfig.LndConnect.Image) } - } diff --git a/uri.go b/uri.go index 2df5ac1..d44e078 100644 --- a/uri.go +++ b/uri.go @@ -4,13 +4,16 @@ import ( b64 "encoding/base64" "encoding/pem" "fmt" + "image/color" "io/ioutil" "net" "net/url" "os" "strings" + qrcodeTerminal "github.com/Baozisoftware/qrcode-terminal-go" externalip "github.com/glendc/go-external-ip" + "github.com/skip2/go-qrcode" ) func getLocalIP() string { @@ -110,3 +113,18 @@ func getURI(loadedConfig *config) (string, error) { fmt.Println("\nURI generated successfully.") return u.String(), nil } + +func getQR(uri string, printToFile bool) error { + // Generate URI + if printToFile { + BrightGreen := color.RGBA{95, 191, 95, 255} + qrcode.WriteColorFile(uri, qrcode.Low, 512, BrightGreen, color.Black, defaultQRFilePath) + fmt.Printf("\nWrote QR Code to file \"%s\"", defaultQRFilePath) + + } else { + obj := qrcodeTerminal.New2(qrcodeTerminal.ConsoleColors.BrightBlack, qrcodeTerminal.ConsoleColors.BrightGreen, qrcodeTerminal.QRCodeRecoveryLevels.Low) + obj.Get(uri).Print() + fmt.Println("\n⚠️ Press \"cmd + -\" a few times to see the full QR Code!\nIf that doesn't work run \"lndconnect -j\" to get a code you can copy paste into the app.") + } + return nil +} From e9a5be0095ccbf07fee38b84c02b236b5312c734 Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 14:22:58 +0200 Subject: [PATCH 13/24] fix tag identifier --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index 1b8e2c5..abe9a81 100644 --- a/config.go +++ b/config.go @@ -80,7 +80,7 @@ type config struct { LndConnect *lndConnectConfig `group:"LndConnect"` LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."` - ConfigFile string `long:"C" long:"configfile" description:"Path to configuration file"` + ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` DataDir string `short:"b" long:"datadir" description:"The directory to find lnd's data within"` TLSCertPath string `long:"tlscertpath" description:"Path to read the TLS certificate from"` AdminMacPath string `long:"adminmacaroonpath" description:"Path to read the admin macaroon from"` From d603a2f17cdec688bf35560e178cea9e2beb82dd Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 14:24:33 +0200 Subject: [PATCH 14/24] fix errors' strings format --- config.go | 2 +- uri.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.go b/config.go index abe9a81..05518c3 100644 --- a/config.go +++ b/config.go @@ -197,7 +197,7 @@ func loadConfig() (*config, error) { networkName = "simnet" } if numNets > 1 { - str := "The mainnet, testnet, regtest, and " + + str := "the mainnet, testnet, regtest, and " + "simnet params can't be used together -- " + "choose one of the four" err := fmt.Errorf(str) diff --git a/uri.go b/uri.go index d44e078..8284136 100644 --- a/uri.go +++ b/uri.go @@ -102,7 +102,7 @@ func getURI(loadedConfig *config) (string, error) { queryParts := strings.Split(s, "=") if len(queryParts) != 2 { - return "", fmt.Errorf("Invalid Query Argument: %s", s) + return "", fmt.Errorf("invalid Query Argument: %s", s) } q.Add(queryParts[0], queryParts[1]) From 01f8d81bf7dac737288589b81b8e67ce33540c36 Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 14:25:24 +0200 Subject: [PATCH 15/24] switch from deprecated io/ioutil package --- uri.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/uri.go b/uri.go index 8284136..a4f4a21 100644 --- a/uri.go +++ b/uri.go @@ -5,7 +5,6 @@ import ( "encoding/pem" "fmt" "image/color" - "io/ioutil" "net" "net/url" "os" @@ -64,7 +63,7 @@ func getURI(loadedConfig *config) (string, error) { // cert if !loadedConfig.LndConnect.NoCert { - certBytes, err := ioutil.ReadFile(loadedConfig.TLSCertPath) + certBytes, err := os.ReadFile(loadedConfig.TLSCertPath) if err != nil { return "", err } @@ -82,11 +81,11 @@ func getURI(loadedConfig *config) (string, error) { // macaroon var macBytes []byte if loadedConfig.LndConnect.Invoice { - macBytes, err = ioutil.ReadFile(loadedConfig.InvoiceMacPath) + macBytes, err = os.ReadFile(loadedConfig.InvoiceMacPath) } else if loadedConfig.LndConnect.Readonly { - macBytes, err = ioutil.ReadFile(loadedConfig.ReadMacPath) + macBytes, err = os.ReadFile(loadedConfig.ReadMacPath) } else { - macBytes, err = ioutil.ReadFile(loadedConfig.AdminMacPath) + macBytes, err = os.ReadFile(loadedConfig.AdminMacPath) } if err != nil { From a8ce1c7515693bb78d1806688508886e8b43ae8c Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 14:35:16 +0200 Subject: [PATCH 16/24] fix attribute name format --- config.go | 4 ++-- uri.go | 2 +- uri_test.go | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/config.go b/config.go index 05518c3..d827755 100644 --- a/config.go +++ b/config.go @@ -59,12 +59,12 @@ type torConfig struct { type arrayFlags []string type lndConnectConfig struct { - LocalIp bool `short:"i" long:"localip" description:"Include local ip in QRCode"` + LocalIP bool `short:"i" long:"localip" description:"Include local ip in QRCode"` Localhost bool `short:"l" long:"localhost" description:"Use 127.0.0.1 for ip"` Host string `long:"host" description:"Use specific host name"` NoCert bool `long:"nocert" description:"Don't include the certificate"` Port uint16 `short:"p" long:"port" description:"Use this port"` - Url bool `short:"j" long:"url" description:"Display url instead of a QRCode"` + URL bool `short:"j" long:"url" description:"Display url instead of a QRCode"` Image bool `short:"o" long:"image" description:"Output QRCode to file"` Invoice bool `long:"invoice" description:"Use invoice macaroon"` Readonly bool `long:"readonly" description:"Use readonly macaroon"` diff --git a/uri.go b/uri.go index a4f4a21..c6ed43f 100644 --- a/uri.go +++ b/uri.go @@ -48,7 +48,7 @@ func getURI(loadedConfig *config) (string, error) { ipString := "" if loadedConfig.LndConnect.Host != "" { ipString = loadedConfig.LndConnect.Host - } else if loadedConfig.LndConnect.LocalIp { + } else if loadedConfig.LndConnect.LocalIP { ipString = getLocalIP() } else if loadedConfig.LndConnect.Localhost { ipString = "127.0.0.1" diff --git a/uri_test.go b/uri_test.go index dedc8ae..389cef4 100644 --- a/uri_test.go +++ b/uri_test.go @@ -8,7 +8,7 @@ func ExampleLocalhost(t *testing.T) { AdminMacPath: "testdata/admin.macaroon", LndConnect: &lndConnectConfig{ Localhost: true, - Url: true, + URL: true, }, } @@ -25,7 +25,7 @@ func ExampleQuery(t *testing.T) { AdminMacPath: "testdata/admin.macaroon", LndConnect: &lndConnectConfig{ Localhost: true, - Url: true, + URL: true, Query: arrayFlags{"test=abc"}, }, } @@ -43,7 +43,7 @@ func ExamplePort(t *testing.T) { AdminMacPath: "testdata/admin.macaroon", LndConnect: &lndConnectConfig{ Localhost: true, - Url: true, + URL: true, Port: 123, }, } @@ -61,7 +61,7 @@ func ExampleHost(t *testing.T) { AdminMacPath: "testdata/admin.macaroon", LndConnect: &lndConnectConfig{ Localhost: true, - Url: true, + URL: true, Host: "1.2.3.4", }, } @@ -79,7 +79,7 @@ func ExampleNoCert(t *testing.T) { AdminMacPath: "testdata/admin.macaroon", LndConnect: &lndConnectConfig{ Localhost: true, - Url: true, + URL: true, Host: "1.2.3.4", NoCert: true, }, From 21dc8e44d3119ae38e60c06ae53d7eb17f8fbcce Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 14:40:30 +0200 Subject: [PATCH 17/24] add comments --- crypto.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crypto.go b/crypto.go index 1974ddd..236146f 100644 --- a/crypto.go +++ b/crypto.go @@ -2,12 +2,15 @@ package main import "io" +// MockEncrypter is a mocked up structure implementing tor.NewOnionFile required encrypter methods type MockEncrypter struct{} +// EncryptPayloadToWriter is implementing expected signature func (m MockEncrypter) EncryptPayloadToWriter(_ []byte, _ io.Writer) error { return nil } +// DecryptPayloadFromReader is implementing expected signature func (m MockEncrypter) DecryptPayloadFromReader(_ io.Reader) ([]byte, error) { return []byte("hello world!"), nil } From 634691fc24605916a46a38e8fa0a4cf7b85e1bd3 Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 15:10:07 +0200 Subject: [PATCH 18/24] autoformatting --- config.go | 60 +++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/config.go b/config.go index d827755..0c4ed18 100644 --- a/config.go +++ b/config.go @@ -40,35 +40,35 @@ var ( ) type chainConfig struct { - Active bool `long:"active" description:"If the chain should be active or not"` + Active bool `long:"active" description:"If the chain should be active or not"` MainNet bool `long:"mainnet" description:"Use the main network"` TestNet3 bool `long:"testnet" description:"Use the test network"` - SimNet bool `long:"simnet" description:"Use the simulation test network"` + SimNet bool `long:"simnet" description:"Use the simulation test network"` RegTest bool `long:"regtest" description:"Use the regression test network"` } type torConfig struct { - Active bool `long:"active" description:"Allow outbound and inbound connections to be routed through Tor"` - V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"` - Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"` + Active bool `long:"active" description:"Allow outbound and inbound connections to be routed through Tor"` + V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"` + Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"` TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"` - Password string `long:"password" description:"If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."` - RESTKeyPath string `short:"r" long:"restkeypath" description:"The path to the private key of the onion service being created if provided."` + Password string `long:"password" description:"If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."` + RESTKeyPath string `long:"restkeypath" description:"The path to the private key of the onion service being created if provided." short:"r"` } type arrayFlags []string type lndConnectConfig struct { - LocalIP bool `short:"i" long:"localip" description:"Include local ip in QRCode"` - Localhost bool `short:"l" long:"localhost" description:"Use 127.0.0.1 for ip"` - Host string `long:"host" description:"Use specific host name"` - NoCert bool `long:"nocert" description:"Don't include the certificate"` - Port uint16 `short:"p" long:"port" description:"Use this port"` - URL bool `short:"j" long:"url" description:"Display url instead of a QRCode"` - Image bool `short:"o" long:"image" description:"Output QRCode to file"` - Invoice bool `long:"invoice" description:"Use invoice macaroon"` - Readonly bool `long:"readonly" description:"Use readonly macaroon"` - Query arrayFlags `short:"q" long:"query" description:"Add additional url query parameters"` + LocalIP bool `short:"i" long:"localip" description:"Include local ip in QRCode"` + Localhost bool `short:"l" long:"localhost" description:"Use 127.0.0.1 for ip"` + Host string ` long:"host" description:"Use specific host name"` + NoCert bool ` long:"nocert" description:"Don't include the certificate"` + Port uint16 `short:"p" long:"port" description:"Use this port"` + URL bool `short:"j" long:"url" description:"Display url instead of a QRCode"` + Image bool `short:"o" long:"image" description:"Output QRCode to file"` + Invoice bool ` long:"invoice" description:"Use invoice macaroon"` + Readonly bool ` long:"readonly" description:"Use readonly macaroon"` + Query arrayFlags `short:"q" long:"query" description:"Add additional url query parameters"` CreateOnion bool `short:"c" long:"createonion" description:"Create onion v3 hidden service to access REST interface."` } @@ -79,29 +79,29 @@ type lndConnectConfig struct { type config struct { LndConnect *lndConnectConfig `group:"LndConnect"` - LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."` - ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` - DataDir string `short:"b" long:"datadir" description:"The directory to find lnd's data within"` - TLSCertPath string `long:"tlscertpath" description:"Path to read the TLS certificate from"` - AdminMacPath string `long:"adminmacaroonpath" description:"Path to read the admin macaroon from"` + LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."` + ConfigFile string `long:"configfile" description:"Path to configuration file" short:"C"` + DataDir string `long:"datadir" description:"The directory to find lnd's data within" short:"b"` + TLSCertPath string `long:"tlscertpath" description:"Path to read the TLS certificate from"` + AdminMacPath string `long:"adminmacaroonpath" description:"Path to read the admin macaroon from"` ReadMacPath string `long:"readonlymacaroonpath" description:"Path to read the read-only macaroon from"` - InvoiceMacPath string `long:"invoicemacaroonpath" description:"Path to read the invoice-only macaroon from"` - RawRESTListeners []string `long:"restlisten" description:"Interface/Port/Socket listening for REST connections"` + InvoiceMacPath string `long:"invoicemacaroonpath" description:"Path to read the invoice-only macaroon from"` + RawRESTListeners []string `long:"restlisten" description:"Interface/Port/Socket listening for REST connections"` - Bitcoin *chainConfig `group:"Bitcoin" namespace:"bitcoin"` + Bitcoin *chainConfig `group:"Bitcoin" namespace:"bitcoin"` Litecoin *chainConfig `group:"Litecoin" namespace:"litecoin"` Tor *torConfig `group:"Tor" namespace:"tor"` // The following lines we only need to be able to parse the // configuration INI file without errors. The content will be ignored. - BtcdMode *chainConfig `hidden:"true" group:"btcd" namespace:"btcd"` - BitcoindMode *chainConfig `hidden:"true" group:"bitcoind" namespace:"bitcoind"` - NeutrinoMode *chainConfig `hidden:"true" group:"neutrino" namespace:"neutrino"` - LtcdMode *chainConfig `hidden:"true" group:"ltcd" namespace:"ltcd"` + BtcdMode *chainConfig `hidden:"true" group:"btcd" namespace:"btcd"` + BitcoindMode *chainConfig `hidden:"true" group:"bitcoind" namespace:"bitcoind"` + NeutrinoMode *chainConfig `hidden:"true" group:"neutrino" namespace:"neutrino"` + LtcdMode *chainConfig `hidden:"true" group:"ltcd" namespace:"ltcd"` LitecoindMode *chainConfig `hidden:"true" group:"litecoind" namespace:"litecoind"` Autopilot *chainConfig `hidden:"true" group:"Autopilot" namespace:"autopilot"` - Hodl *chainConfig `hidden:"true" group:"hodl" namespace:"hodl"` + Hodl *chainConfig `hidden:"true" group:"hodl" namespace:"hodl"` net tor.Net } From 581fb706d0bedcb0463097a277591eca1e4c90f7 Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 15:14:08 +0200 Subject: [PATCH 19/24] capture and WriteColorFile return error --- uri.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/uri.go b/uri.go index c6ed43f..401e3a4 100644 --- a/uri.go +++ b/uri.go @@ -114,10 +114,18 @@ func getURI(loadedConfig *config) (string, error) { } func getQR(uri string, printToFile bool) error { + var err error // Generate URI if printToFile { BrightGreen := color.RGBA{95, 191, 95, 255} - qrcode.WriteColorFile(uri, qrcode.Low, 512, BrightGreen, color.Black, defaultQRFilePath) + err = qrcode.WriteColorFile( + uri, + qrcode.Low, + 512, + BrightGreen, + color.Black, + defaultQRFilePath, + ) fmt.Printf("\nWrote QR Code to file \"%s\"", defaultQRFilePath) } else { @@ -125,5 +133,5 @@ func getQR(uri string, printToFile bool) error { obj.Get(uri).Print() fmt.Println("\n⚠️ Press \"cmd + -\" a few times to see the full QR Code!\nIf that doesn't work run \"lndconnect -j\" to get a code you can copy paste into the app.") } - return nil + return err } From 9a71eb810d2dd041b7a81c59d1bf3474e9de8159 Mon Sep 17 00:00:00 2001 From: roshii Date: Thu, 22 Sep 2022 18:09:31 +0200 Subject: [PATCH 20/24] implement torController goroutine --- config.go | 15 +++++++++++ lndconnect.go | 71 +++++++++++++++++++++++++++++++++++++++------------ tor.go | 37 +++++++-------------------- 3 files changed, 78 insertions(+), 45 deletions(-) diff --git a/config.go b/config.go index 0c4ed18..b6bd346 100644 --- a/config.go +++ b/config.go @@ -6,9 +6,11 @@ package main import ( "fmt" + "log" "os" "os/user" "path/filepath" + "strconv" "strings" "github.com/btcsuite/btcd/btcutil" @@ -277,3 +279,16 @@ func cleanAndExpandPath(path string) string { // but the variables can still be expanded via POSIX-style $VARIABLE. return filepath.Clean(os.ExpandEnv(path)) } + +// updates config with onion host and port +func updateHostAddrConfig(addr string, loadedConfig *config) error { + parsedAddr := strings.Split(addr, ":") + loadedConfig.LndConnect.Host = parsedAddr[0] + parsedPort, err := strconv.ParseUint(parsedAddr[1], 10, 16) + if err != nil { + log.Fatal(err) + } + loadedConfig.LndConnect.Port = uint16(parsedPort) + loadedConfig.LndConnect.NoCert = true + return nil +} diff --git a/lndconnect.go b/lndconnect.go index ec214e8..5d460bb 100644 --- a/lndconnect.go +++ b/lndconnect.go @@ -1,31 +1,48 @@ package main import ( - "fmt" "log" - "strconv" - "strings" + "os" + "os/signal" + "syscall" + + "github.com/lightningnetwork/lnd/tor" ) +// var wg sync.WaitGroup + func main() { loadedConfig, err := loadConfig() if err != nil { log.Fatal(err) } - if loadedConfig.LndConnect.CreateOnion { - addr, err := createNewHiddenService(loadedConfig) - if err != nil { - log.Fatal(err) + // If createonion option is selected, tor is active and v3 onion services have been + // specified, make a tor controller and pass it into the REST controller server + var torController *tor.Controller + if loadedConfig.LndConnect.CreateOnion && loadedConfig.Tor.Active && loadedConfig.Tor.V3 { + torController = tor.NewController( + loadedConfig.Tor.Control, + loadedConfig.Tor.TargetIPAddress, + loadedConfig.Tor.Password, + ) + + // Start the tor controller before giving it to any other + // subsystems. + if err := torController.Start(); err != nil { + log.Fatalf("error starting tor controller: %v", err) } - parsedAddr := strings.Split(addr, ":") - loadedConfig.LndConnect.Host = parsedAddr[0] - parsedPort, err := strconv.ParseUint(parsedAddr[1], 10, 16) - if err != nil { + // defer func() { + // if err := torController.Stop(); err != nil { + // log.Printf("error stopping tor controller: %v", err) + // } + // }() + } + + if torController != nil { + if err := createNewHiddenService(loadedConfig, torController); err != nil { log.Fatal(err) } - loadedConfig.LndConnect.Port = uint16(parsedPort) - loadedConfig.LndConnect.NoCert = true } // Generate URI @@ -35,10 +52,30 @@ func main() { } // Print URI or QR Code to selected output - if loadedConfig.LndConnect.Url { - fmt.Println(uri) - + if loadedConfig.LndConnect.URL { + log.Println(uri) } else { - getQR(uri, loadedConfig.LndConnect.Image) + err = getQR(uri, loadedConfig.LndConnect.Image) + if err != nil { + log.Println(err) + } + } + if torController != nil { + cancelChan := make(chan os.Signal, 1) + // catch SIGINT, SIGQUIT or SIGETRM + signal.Notify(cancelChan, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM) + + done := make(chan bool, 1) + go func() { + sig := <-cancelChan + log.Printf("Caught SIGTERM %v", sig) + done <- true + }() + <-done + log.Println("exiting...") + if err := torController.Stop(); err != nil { + log.Printf("error stopping tor controller: %v", err) + } + } } diff --git a/tor.go b/tor.go index f14f700..d4cae7b 100644 --- a/tor.go +++ b/tor.go @@ -10,30 +10,8 @@ import ( // createNewHiddenService automatically sets up a v3 onion service in // order to listen for inbound connections over Tor. -func createNewHiddenService(loadedConfig *config) (string, error) { - +func createNewHiddenService(loadedConfig *config, torController *tor.Controller) error { // If tor is active make a tor controller for creating onion REST service interface - var torController *tor.Controller - if loadedConfig.Tor.Active && loadedConfig.Tor.V3 { - torController = tor.NewController( - loadedConfig.Tor.Control, loadedConfig.Tor.TargetIPAddress, - loadedConfig.Tor.Password, - ) - - // Start the tor controller before giving it to any other - // subsystems. - if err := torController.Start(); err != nil { - return "", err - } - defer func() { - if err := torController.Stop(); err != nil { - fmt.Printf("error stopping tor "+ - "controller: %v", err) - } - }() - } else { - return "", fmt.Errorf("Either tor is inactive or v3 onion service are disabled, check configuration.") - } // Determine the different ports the server is listening on. The onion // service's virtual port will map to these ports and one will be picked @@ -53,7 +31,7 @@ func createNewHiddenService(loadedConfig *config) (string, error) { } port, err := strconv.Atoi(parsedPort) if err != nil { - return "", err + return err } restListenPorts = append(restListenPorts, port) } @@ -65,16 +43,19 @@ func createNewHiddenService(loadedConfig *config) (string, error) { onionCfg := tor.AddOnionConfig{ VirtualPort: defaultRESTPort, TargetPorts: restListenPorts, - Store: tor.NewOnionFile(loadedConfig.Tor.RESTKeyPath, 0600, false, MockEncrypter{}), + Store: tor.NewOnionFile(loadedConfig.Tor.RESTKeyPath, 0o600, false, MockEncrypter{}), Type: tor.V3, } - addr, err := torController.AddOnion(onionCfg) + onionAddr, err := torController.AddOnion(onionCfg) if err != nil { - return "", err + return err } + addr := onionAddr.String() fmt.Println("\nOnion service created for LND REST interface, address reads:") fmt.Println(addr) - return addr.String(), nil + err = updateHostAddrConfig(addr, loadedConfig) + + return err } From 1ca2ec5329d9ae266cb72b73ef4930e39ea665bd Mon Sep 17 00:00:00 2001 From: roshii Date: Fri, 23 Sep 2022 16:10:58 +0200 Subject: [PATCH 21/24] leverage log pkg --- tor.go | 6 +++--- uri.go | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tor.go b/tor.go index d4cae7b..8ec0392 100644 --- a/tor.go +++ b/tor.go @@ -1,7 +1,7 @@ package main import ( - "fmt" + "log" "strconv" "strings" @@ -52,8 +52,8 @@ func createNewHiddenService(loadedConfig *config, torController *tor.Controller) return err } addr := onionAddr.String() - fmt.Println("\nOnion service created for LND REST interface, address reads:") - fmt.Println(addr) + log.Println("Onion service created for LND REST interface") + log.Printf("serviceID: %v", addr) err = updateHostAddrConfig(addr, loadedConfig) diff --git a/uri.go b/uri.go index 401e3a4..c0a38af 100644 --- a/uri.go +++ b/uri.go @@ -5,6 +5,7 @@ import ( "encoding/pem" "fmt" "image/color" + "log" "net" "net/url" "os" @@ -34,8 +35,7 @@ func getPublicIP() string { consensus := externalip.DefaultConsensus(nil, nil) ip, err := consensus.ExternalIP() if err != nil { - fmt.Println(err) - os.Exit(1) + log.Fatalln(err) } return ip.String() @@ -70,7 +70,7 @@ func getURI(loadedConfig *config) (string, error) { block, _ := pem.Decode(certBytes) if block == nil || block.Type != "CERTIFICATE" { - fmt.Println("failed to decode PEM block containing certificate") + log.Println("failed to decode PEM block containing certificate") } certificate := b64.RawURLEncoding.EncodeToString([]byte(block.Bytes)) @@ -109,7 +109,7 @@ func getURI(loadedConfig *config) (string, error) { u.RawQuery = q.Encode() - fmt.Println("\nURI generated successfully.") + log.Println("lndconnect URI generated successfully") return u.String(), nil } @@ -126,7 +126,7 @@ func getQR(uri string, printToFile bool) error { color.Black, defaultQRFilePath, ) - fmt.Printf("\nWrote QR Code to file \"%s\"", defaultQRFilePath) + log.Printf("Wrote QR Code to file \"%s\"", defaultQRFilePath) } else { obj := qrcodeTerminal.New2(qrcodeTerminal.ConsoleColors.BrightBlack, qrcodeTerminal.ConsoleColors.BrightGreen, qrcodeTerminal.QRCodeRecoveryLevels.Low) From 305afcfb09cf3d94fb6f140794c74b145ddcf90b Mon Sep 17 00:00:00 2001 From: roshii Date: Fri, 23 Sep 2022 16:11:45 +0200 Subject: [PATCH 22/24] lookup tor.targetipaddress --- lndconnect.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lndconnect.go b/lndconnect.go index 5d460bb..272761b 100644 --- a/lndconnect.go +++ b/lndconnect.go @@ -2,6 +2,7 @@ package main import ( "log" + "net" "os" "os/signal" "syscall" @@ -21,9 +22,24 @@ func main() { // specified, make a tor controller and pass it into the REST controller server var torController *tor.Controller if loadedConfig.LndConnect.CreateOnion && loadedConfig.Tor.Active && loadedConfig.Tor.V3 { + var targetIPAddress string + if net.ParseIP(loadedConfig.Tor.TargetIPAddress) == nil { + addrs, err := loadedConfig.net.LookupHost(loadedConfig.Tor.TargetIPAddress) + if err != nil { + log.Fatalln(err) + } + targetIPAddress = addrs[0] + log.Printf( + "`tor.targetipaddress` doesn't define an IP address, hostname %s was resolved to %s", + loadedConfig.Tor.TargetIPAddress, + targetIPAddress, + ) + } else { + targetIPAddress = loadedConfig.Tor.TargetIPAddress + } torController = tor.NewController( loadedConfig.Tor.Control, - loadedConfig.Tor.TargetIPAddress, + targetIPAddress, loadedConfig.Tor.Password, ) From 8684c688583d5ec0bb88d62a8eadb6b5b32c1835 Mon Sep 17 00:00:00 2001 From: roshii Date: Fri, 23 Sep 2022 16:12:11 +0200 Subject: [PATCH 23/24] code cleanup --- lndconnect.go | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/lndconnect.go b/lndconnect.go index 272761b..b57773f 100644 --- a/lndconnect.go +++ b/lndconnect.go @@ -10,8 +10,6 @@ import ( "github.com/lightningnetwork/lnd/tor" ) -// var wg sync.WaitGroup - func main() { loadedConfig, err := loadConfig() if err != nil { @@ -48,14 +46,12 @@ func main() { if err := torController.Start(); err != nil { log.Fatalf("error starting tor controller: %v", err) } - // defer func() { - // if err := torController.Stop(); err != nil { - // log.Printf("error stopping tor controller: %v", err) - // } - // }() - } + defer func() { + if err := torController.Stop(); err != nil { + log.Printf("error stopping tor controller: %v", err) + } + }() - if torController != nil { if err := createNewHiddenService(loadedConfig, torController); err != nil { log.Fatal(err) } @@ -78,20 +74,17 @@ func main() { } if torController != nil { cancelChan := make(chan os.Signal, 1) + done := make(chan bool, 1) + // catch SIGINT, SIGQUIT or SIGETRM signal.Notify(cancelChan, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM) - done := make(chan bool, 1) go func() { sig := <-cancelChan - log.Printf("Caught SIGTERM %v", sig) + log.Printf("Caught %v signal", sig) done <- true }() <-done - log.Println("exiting...") - if err := torController.Stop(); err != nil { - log.Printf("error stopping tor controller: %v", err) - } - + log.Println("lndconnect is shutting down now...") } } From 74a707d05e369201998b8a8698ceee2714089765 Mon Sep 17 00:00:00 2001 From: roshii Date: Fri, 23 Sep 2022 16:13:23 +0200 Subject: [PATCH 24/24] Revert "dev config" This reverts commit 81d8f0b9e02de069f886b48c490db805cb7238b4. --- .gitignore | 5 ----- Makefile | 19 ++++++------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 75ab010..02aaabc 100644 --- a/.gitignore +++ b/.gitignore @@ -12,8 +12,3 @@ *.out build - -# Development files and folders -.data -lndconnect -*.png \ No newline at end of file diff --git a/Makefile b/Makefile index 193df84..64f1c28 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,10 @@ -BINARY_NAME=lndconnect -GOARCH=amd64 -GOOS=linux - -default: run - -build: - go build -o ${BINARY_NAME} - -run: build - ./${BINARY_NAME} --lnddir .data -j -c +default: install dep: - go mod download + go get ./... + +install: dep + go install -v ./... -test: dep +test: go test -v \ No newline at end of file