Browse Source

Merge branch 'dev' of https://git.hush.is/hush/silentdragon into dev

pull/69/head
Duke Leto 3 years ago
parent
commit
80f82fd965
  1. 13
      .gitignore
  2. 5
      AUTHORS
  3. 75
      README.md
  4. 5
      application.qrc
  5. BIN
      asmap.dat
  6. 8
      build.sh
  7. 6
      docs/index.html
  8. 21
      hush-cli
  9. BIN
      images/sd-hushd-tab.png
  10. BIN
      images/sd-main-window.png
  11. BIN
      images/sd-market-tab.png
  12. BIN
      images/sd-peers-tab.png
  13. BIN
      images/sd-receive-tab.png
  14. BIN
      images/sd-send-tab.png
  15. BIN
      images/sd-transactions-tab.png
  16. 2
      res/Info.plist
  17. 13
      res/SIGNATURES_README
  18. 2
      res/css/midnight.css
  19. 2
      res/libsodium/buildlibsodium.sh
  20. 2973
      res/silentdragon_be.ts
  21. 730
      res/silentdragon_bg.ts
  22. BIN
      res/silentdragon_de.qm
  23. 756
      res/silentdragon_de.ts
  24. BIN
      res/silentdragon_es.qm
  25. 770
      res/silentdragon_es.ts
  26. BIN
      res/silentdragon_fi.qm
  27. 742
      res/silentdragon_fi.ts
  28. BIN
      res/silentdragon_fil.qm
  29. 754
      res/silentdragon_fil.ts
  30. BIN
      res/silentdragon_fr.qm
  31. 750
      res/silentdragon_fr.ts
  32. BIN
      res/silentdragon_hr.qm
  33. 754
      res/silentdragon_hr.ts
  34. BIN
      res/silentdragon_id.qm
  35. 752
      res/silentdragon_id.ts
  36. BIN
      res/silentdragon_it.qm
  37. 734
      res/silentdragon_it.ts
  38. BIN
      res/silentdragon_nl.qm
  39. 746
      res/silentdragon_nl.ts
  40. 2377
      res/silentdragon_pl.ts
  41. BIN
      res/silentdragon_pt.qm
  42. 736
      res/silentdragon_pt.ts
  43. BIN
      res/silentdragon_ro.qm
  44. 754
      res/silentdragon_ro.ts
  45. BIN
      res/silentdragon_ru.qm
  46. 1041
      res/silentdragon_ru.ts
  47. BIN
      res/silentdragon_sr.qm
  48. 754
      res/silentdragon_sr.ts
  49. 10
      res/silentdragon_template.ts
  50. BIN
      res/silentdragon_tr.qm
  51. 742
      res/silentdragon_tr.ts
  52. BIN
      res/silentdragon_uk.qm
  53. 754
      res/silentdragon_uk.ts
  54. BIN
      res/silentdragon_zh.qm
  55. 746
      res/silentdragon_zh.ts
  56. BIN
      res/tropical-hush-square.png
  57. BIN
      res/tropical-hush.png
  58. BIN
      res/zcashdlogo.gif
  59. 2
      run-after-build.sh
  60. BIN
      sapling-output.params
  61. BIN
      sapling-spend.params
  62. BIN
      silentdragon.png
  63. 14
      silentdragon.pro
  64. 3
      src/3rdparty/sodium.h
  65. 10
      src/about.ui
  66. 2
      src/addressbook.cpp
  67. 4
      src/addressbook.h
  68. 4
      src/addresscombo.cpp
  69. 2
      src/addresscombo.h
  70. 2
      src/balancestablemodel.cpp
  71. 4
      src/balancestablemodel.h
  72. 128
      src/bannedpeerstablemodel.cpp
  73. 36
      src/bannedpeerstablemodel.h
  74. 193
      src/connection.cpp
  75. 26
      src/connection.h
  76. 8
      src/createzcashconfdialog.ui
  77. 4
      src/fillediconlabel.cpp
  78. 4
      src/fillediconlabel.h
  79. 4
      src/logger.cpp
  80. 4
      src/logger.h
  81. 10
      src/main.cpp
  82. 293
      src/mainwindow.cpp
  83. 12
      src/mainwindow.h
  84. 92
      src/mainwindow.ui
  85. 4
      src/memoedit.cpp
  86. 4
      src/memoedit.h
  87. 2
      src/mobileappconnector.cpp
  88. 2
      src/mobileappconnector.h
  89. 178
      src/peerstablemodel.cpp
  90. 44
      src/peerstablemodel.h
  91. 2
      src/precompiled.h
  92. 4
      src/qrcodelabel.cpp
  93. 2
      src/qrcodelabel.h
  94. 4
      src/recurring.cpp
  95. 4
      src/recurring.h
  96. 6
      src/requestdialog.cpp
  97. 2
      src/requestdialog.h
  98. 192
      src/rpc.cpp
  99. 53
      src/rpc.h
  100. 2
      src/scripts/dotranslations.sh
  101. 11
      src/scripts/make-binary-tarball.sh
  102. 20
      src/scripts/make-deb.sh
  103. 2
      src/scripts/make-only-deb.sh
  104. 2
      src/scripts/mkmacdmg.sh
  105. 2
      src/scripts/mkrelease.sh
  106. 2
      src/scripts/signbinaries.sh
  107. 19
      src/sendtab.cpp
  108. 2
      src/senttxstore.cpp
  109. 2
      src/senttxstore.h
  110. 20
      src/settings.cpp
  111. 17
      src/settings.h
  112. 12
      src/settings.ui
  113. 2
      src/txtablemodel.cpp
  114. 2
      src/txtablemodel.h
  115. 2
      src/validateaddress.cpp
  116. 2
      src/validateaddress.h
  117. 2
      src/version.h
  118. 2
      src/viewalladdresses.cpp
  119. 4
      src/viewalladdresses.h
  120. 16
      src/websockets.cpp
  121. 6
      src/websockets.h
  122. 9
      util/silentdragon.desktop
  123. 2
      win-build.sh

13
.gitignore

@ -8,6 +8,8 @@ hushd
IDEWorkspaceChecks.plist IDEWorkspaceChecks.plist
komodo-cli komodo-cli
komodod komodod
hush-cli
hushd
*.mak *.mak
Makefile Makefile
Makefile.* Makefile.*
@ -29,12 +31,7 @@ src/ui_*.h
workspace.code-workspace workspace.code-workspace
x64/ x64/
*.xcsettings *.xcsettings
zec-qt-wallet-mingw*
zec-qt-wallet_plugin_import.cpp
zec-qt-wallet_resource*
zec-qt-wallet.sln
zec-qt-wallet.vcxproj*
zecwallet_plugin_import.cpp
zecwallet_resource*
zecwallet.vcxproj*
*.zip *.zip
# compiled translation files can be ignored
*.qm

5
AUTHORS

@ -0,0 +1,5 @@
# The Hush Developers
Duke Leto https://git.hush.is/duke https://github.com/leto
Jane Mercer https://git.hush.is/radix42 https://github.com/radix42

75
README.md

@ -1,7 +1,4 @@
# SilentDragon # SilentDragon
[![GitHub license](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)](https://github.com/MyHush/SilentDragon/blob/master/LICENSE)
[![GitHub version](https://badge.fury.io/gh/MyHush%2FSilentDragon.svg)](https://badge.fury.io/gh/MyHush%2FSilentDragon)
[![Github All Releases](https://img.shields.io/github/downloads/MyHush/SilentDragon/total.svg)](https://img.shields.io/github/downloads/MyHush/SilentDragon/total.svg)
<p align="left"> <p align="left">
<a href="https://twitter.com/MyHushTeam"> <a href="https://twitter.com/MyHushTeam">
@ -21,7 +18,15 @@
SilentDragon desktop wallet for HUSH runs on Linux, Windows and macOS. SilentDragon desktop wallet for HUSH runs on Linux, Windows and macOS.
This is experimental software under active development! This is experimental software under active development!
![Screenshots](silentdragon.png?raw=true) ![Screenshots](images/sd-receive-tab.png?raw=true)
The following are screenshots for each SilentDragon tab:
* [Main Window](images/sd-main-window.png)
* [Send Tab](images/sd-send-tab.png)
* [Transactions Tab](images/sd-transactions-tab.png)
* [Peers Tab](images/sd-peers-tab.png)
* [Market Tab](images/sd-market-tab.png)
* [Hushd Tab](images/sd-hushd-tab.png)
## PRIVACY NOTICE ## PRIVACY NOTICE
@ -29,20 +34,21 @@ SilentDragon contacts a few different external websites to get various
bits of data. bits of data.
* coingecko.com for price data API * coingecko.com for price data API
* explorer.myhush.org for explorer links * explorer.hush.is for explorer links
* dexstats.info for address utilities * dexstats.info for address utilities
* wormhole.myhush.org for Wormhole services * wormhole.hush.is for Wormhole services
This means your IP address is known to these servers. Enable Tor setting This means your IP address is known to these servers. Enable Tor setting
in SilentDragon to prevent this, or better yet, use TAILS: https://tails.boum.org/ in SilentDragon to prevent this, or better yet, use TAILS: https://tails.boum.org/
# Installation # Installation
Go to the releases page and grab the latest installers or binary. https://github.com/MyHush/SilentDragon/releases Go to the [releases page](https://git.hush.is/hush/SilentDragon/releases) and grab the latest installers or binary.
For Arch Linux users, this is available from the AUR.
## hushd ## hushd
SilentDragon needs a Hush full node running [hushd](https://github.com/MyHush/hush3/). If you already have a hushd node running, SilentDragon will connect to it. SilentDragon needs a Hush full node running [hushd](https://git.hush.is/hush/hush3/). If you already have a hushd node running, SilentDragon will connect to it.
If you don't have one, SilentDragon will start its embedded hushd node. If you don't have one, SilentDragon will start its embedded hushd node.
@ -53,41 +59,45 @@ Pass `--no-embedded` to disable the embedded hushd and force SilentDragon to con
## Compiling from source ## Compiling from source
SilentDragon is written in C++ 14, and can be compiled with g++/clang++/visual SilentDragon is written in C++ 14, and can be compiled with g++/clang++/visual
c++. It also depends on Qt5, which you can get from c++. It also depends on Qt5, which you can get from [here](https://www.qt.io/download)
[here](https://www.qt.io/download). Note that if you are compiling from source, or within your operating system package manager. Note that if you are compiling
you won't get the embedded hushd by default. You can either run an external from source, you won't get the embedded hushd by default. You can either run an external
hushd, or compile hushd as well. hushd, or compile hushd as well.
### Building on Linux ### Building on Linux
#### Ubuntu 18.04 and 20.04: #### Ubuntu 18.04 and 20.04
``` You can install the pre-reqs and build on Ubuntu 18.04 & 20.04 with:
```shell script
sudo apt-get -y install qt5-default qt5-qmake libqt5websockets5-dev qtcreator sudo apt-get -y install qt5-default qt5-qmake libqt5websockets5-dev qtcreator
git clone https://github.com/MyHush/SilentDragon.git git clone https://git.hush.is/hush/SilentDragon
cd SilentDragon cd SilentDragon
./build.sh linguist # compile translations ./build.sh linguist
./build.sh ./build.sh
./silentdragon ./silentdragon
``` ```
#### Arch Linux: #### Arch Linux
``` You can install the pre-reqs and build on Arch Linux with:
```shell script
sudo pacman -S qt5-base qt5-tools qtcreator qt5-websockets rust sudo pacman -S qt5-base qt5-tools qtcreator qt5-websockets rust
git clone https://github.com/MyHush/SilentDragon.git git clone https://git.hush.is/hush/SilentDragon
cd SilentDragon cd SilentDragon
./build.sh linguist # compile translations ./build.sh linguist
./build.sh release ./build.sh release
./silentdragon ./silentdragon
``` ```
### Building on Windows ### Building on Windows
You need Visual Studio 2017 (The free C++ Community Edition works just fine). You need Visual Studio 2017 (The free C++ Community Edition works just fine).
From the VS Tools command prompt From the VS Tools command prompt
``` ```shell script
git clone https://github.com/MyHush/SilentDragon.git git clone https://git.hush.is/hush/SilentDragon
cd SilentDragon cd SilentDragon
c:\Qt5\bin\qmake.exe silentdragon.pro -spec win32-msvc CONFIG+=debug c:\Qt5\bin\qmake.exe silentdragon.pro -spec win32-msvc CONFIG+=debug
nmake nmake
@ -96,7 +106,7 @@ debug\SilentDragon.exe
``` ```
To create the Visual Studio project files so you can compile and run from Visual Studio: To create the Visual Studio project files so you can compile and run from Visual Studio:
``` ```shell script
c:\Qt5\bin\qmake.exe silentdragon.pro -tp vc CONFIG+=debug c:\Qt5\bin\qmake.exe silentdragon.pro -tp vc CONFIG+=debug
``` ```
@ -104,10 +114,14 @@ c:\Qt5\bin\qmake.exe silentdragon.pro -tp vc CONFIG+=debug
You need to install the Xcode app or the Xcode command line tools first, and then install Qt. You need to install the Xcode app or the Xcode command line tools first, and then install Qt.
``` TODO: Suggestions on installing qt5 deps on a Mac
git clone https://github.com/MyHush/SilentDragon.git
```shell script
git clone https://git.hush.is/hush/SilentDragon
cd SilentDragon cd SilentDragon
qmake silentdragon.pro CONFIG+=debug # These commands require qmake to be installed
./build.sh linguist
./build.sh
make make
./SilentDragon.app/Contents/MacOS/SilentDragon ./SilentDragon.app/Contents/MacOS/SilentDragon
@ -119,15 +133,14 @@ In binary releases, SilentDragon will use node binaries in the current directory
It does not attempt to download them, it bundles them. To simulate this from a developer setup, you can symlink It does not attempt to download them, it bundles them. To simulate this from a developer setup, you can symlink
these four files in your Git repo: these four files in your Git repo:
``` ```shell script
ln -s ../hush3/src/hushd ln -s ../hush3/src/hushd
ln -s ../hush3/src/komodod ln -s ../hush3/src/hush-cli
ln -s ../hush3/src/komodo-cli
``` ```
The above assumes silentdragon and hush3 git repos are in the same directory. File names on Windows will need to be tweaked. The above assumes silentdragon and hush3 git repos are in the same directory. File names on Windows will need to be tweaked.
### Support ### Support
For support or other questions, join us on [Discord](https://myhush.org/discord), or tweet at [@MyHushTeam](https://twitter.com/MyHushTeam), or toot at our [Mastodon](https://fosstodon.org/@myhushteam) or join [Telegram](http://myhush.org/telegram) or [file an issue](https://github.com/MyHush/SilentDragon/issues). For support or other questions, join us on [Telegram](https://hush.is/telegram), or tweet at [@MyHushTeam](https://twitter.com/MyHushTeam), or toot at our [Mastodon](https://fosstodon.org/@myhushteam) or join [Telegram Support](https://hush.is/telegram_support) or [file an issue](https://git.hush.is/hush/SilentDragon/issues).

5
application.qrc

@ -9,7 +9,8 @@
<file>res/icon.ico</file> <file>res/icon.ico</file>
</qresource> </qresource>
<qresource prefix="/img"> <qresource prefix="/img">
<file>res/zcashdlogo.gif</file> <file>res/tropical-hush.png</file>
<file>res/tropical-hush-square.png</file>
<file>res/logobig.gif</file> <file>res/logobig.gif</file>
<file>res/silentdragon-animated.gif</file> <file>res/silentdragon-animated.gif</file>
<file>res/silentdragon-animated-dark.gif</file> <file>res/silentdragon-animated-dark.gif</file>
@ -17,6 +18,7 @@
<file>res/silentdragon-animated-startup-dark.gif</file> <file>res/silentdragon-animated-startup-dark.gif</file>
</qresource> </qresource>
<qresource prefix="/translations"> <qresource prefix="/translations">
<file>res/silentdragon_be.qm</file>
<file>res/silentdragon_bg.qm</file> <file>res/silentdragon_bg.qm</file>
<file>res/silentdragon_de.qm</file> <file>res/silentdragon_de.qm</file>
<file>res/silentdragon_es.qm</file> <file>res/silentdragon_es.qm</file>
@ -27,6 +29,7 @@
<file>res/silentdragon_it.qm</file> <file>res/silentdragon_it.qm</file>
<file>res/silentdragon_id.qm</file> <file>res/silentdragon_id.qm</file>
<file>res/silentdragon_nl.qm</file> <file>res/silentdragon_nl.qm</file>
<file>res/silentdragon_pl.qm</file>
<file>res/silentdragon_pt.qm</file> <file>res/silentdragon_pt.qm</file>
<file>res/silentdragon_ro.qm</file> <file>res/silentdragon_ro.qm</file>
<file>res/silentdragon_ru.qm</file> <file>res/silentdragon_ru.qm</file>

BIN
asmap.dat

Binary file not shown.

8
build.sh

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright 2019-2020 The Hush Developers # Copyright 2018-2021 The Hush Developers
# Released under the GPLv3 # Released under the GPLv3
set -e set -e
@ -15,6 +15,12 @@ else
JOBS=1 JOBS=1
fi fi
# Check if qmake is installed on system and exits if it is not
if ! [ -x "$(command -v qmake)" ]; then
echo 'Error: qmake is not installed. Install qmake and try again.' >&2
exit 1
fi
VERSION=$(cat src/version.h |cut -d\" -f2) VERSION=$(cat src/version.h |cut -d\" -f2)
echo "Compiling SilentDragon $VERSION with $JOBS threads..." echo "Compiling SilentDragon $VERSION with $JOBS threads..."
CONF=silentdragon.pro CONF=silentdragon.pro

6
docs/index.html

@ -1,6 +0,0 @@
<html>
<head></head>
<body>
Hello World
</body>
</html>

21
hush-cli

@ -1,21 +0,0 @@
#!/bin/bash
# Copyright (c) 2019 Hush developers
# set working directory to the location of this script
# readlink -f does not always exist
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $DIR
DIR="$( cd "$( dirname "$( readlink "${BASH_SOURCE[0]}" )" )" && pwd )"
cd $DIR
NAME=HUSH3
CLI=${KOMODOCLI:-./komodo-cli}
if [ -f $CLI ]; then
$CLI -ac_name=$NAME "$@"
else
# We prefix our binary when installed
# system wide on Debain system, to prevent clashes
CLI=hush-komodo-cli
$CLI -ac_name=$NAME "$@"
fi

BIN
images/sd-hushd-tab.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 KiB

BIN
images/sd-main-window.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
images/sd-market-tab.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
images/sd-peers-tab.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

BIN
images/sd-receive-tab.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 KiB

BIN
images/sd-send-tab.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
images/sd-transactions-tab.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

2
res/Info.plist

@ -9,7 +9,7 @@
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>logo.icns</string> <string>logo.icns</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.myhush.silentdragon</string> <string>com.hush.silentdragon</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>

13
res/SIGNATURES_README

@ -1,13 +0,0 @@
This directory contains the hashes and signatures for SilentDargon
Verify the hashes by running:
sha256sum -c sha256sum-vX.Y.Z.txt
Verify signatures:
1. First, import the public key (Available on GitHub
at https://github.com/ZcashFoundation/zecwallet/blob/master/public_key.asc)
gpg --import public_key.asc
2. Verify signature
gpg --verify <filename.sig> <downloaded-filename-to-verify>

2
res/css/midnight.css

@ -9,7 +9,7 @@ Website: https://www.csharpe.me
License: https://opensource.org/licenses/MIT License: https://opensource.org/licenses/MIT
*/ */
QWidget, QMainWindow, QMenuBar, QMenu, QDialog, QTabWidget, QTableView, QTableView::item, QScrollArea, QGroupBox, QPlainTextEdit, QLineEdit, QLabel, MainWindow QWidget, QMainWindow, QMenuBar, QMenu, QDialog, QTabWidget, QTableView, QTableView::item, QScrollArea, QGroupBox, QPlainTextEdit, QLineEdit, QLabel, MainWindow, QPixmap, QHBoxLayout, QVBoxLayout, QGridLayout, QAbstractItemView, QFrame
{ {
background-color: #111; background-color: #111;
color: #fff; color: #fff;

2
res/libsodium/buildlibsodium.sh

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright (c) 2019-2020 The Hush developers # Copyright (c) 2019-2021 The Hush developers
# Released under the GPLv3 # Released under the GPLv3
VERSION=1.0.18 VERSION=1.0.18

2973
res/silentdragon_be.ts

File diff suppressed because it is too large

730
res/silentdragon_bg.ts

File diff suppressed because it is too large

BIN
res/silentdragon_de.qm

Binary file not shown.

756
res/silentdragon_de.ts

File diff suppressed because it is too large

BIN
res/silentdragon_es.qm

Binary file not shown.

770
res/silentdragon_es.ts

File diff suppressed because it is too large

BIN
res/silentdragon_fi.qm

Binary file not shown.

742
res/silentdragon_fi.ts

File diff suppressed because it is too large

BIN
res/silentdragon_fil.qm

Binary file not shown.

754
res/silentdragon_fil.ts

File diff suppressed because it is too large

BIN
res/silentdragon_fr.qm

Binary file not shown.

750
res/silentdragon_fr.ts

File diff suppressed because it is too large

BIN
res/silentdragon_hr.qm

Binary file not shown.

754
res/silentdragon_hr.ts

File diff suppressed because it is too large

BIN
res/silentdragon_id.qm

Binary file not shown.

752
res/silentdragon_id.ts

File diff suppressed because it is too large

BIN
res/silentdragon_it.qm

Binary file not shown.

734
res/silentdragon_it.ts

File diff suppressed because it is too large

BIN
res/silentdragon_nl.qm

Binary file not shown.

746
res/silentdragon_nl.ts

File diff suppressed because it is too large

2377
res/silentdragon_pl.ts

File diff suppressed because it is too large

BIN
res/silentdragon_pt.qm

Binary file not shown.

736
res/silentdragon_pt.ts

File diff suppressed because it is too large

BIN
res/silentdragon_ro.qm

Binary file not shown.

754
res/silentdragon_ro.ts

File diff suppressed because it is too large

BIN
res/silentdragon_ru.qm

Binary file not shown.

1041
res/silentdragon_ru.ts

File diff suppressed because it is too large

BIN
res/silentdragon_sr.qm

Binary file not shown.

754
res/silentdragon_sr.ts

File diff suppressed because it is too large

10
res/silentdragon_template.ts

@ -424,7 +424,7 @@
</message> </message>
<message> <message>
<location filename="../src/mainwindow.ui" line="1453"/> <location filename="../src/mainwindow.ui" line="1453"/>
<source>&amp;Hush Discord</source> <source>&amp;Hush Telegram</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
@ -434,7 +434,7 @@
</message> </message>
<message> <message>
<location filename="../src/mainwindow.ui" line="1463"/> <location filename="../src/mainwindow.ui" line="1463"/>
<source>Check github.com for &amp;updates</source> <source>Check git for &amp;updates</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
@ -1519,7 +1519,7 @@ Would you like to visit the releases page?</source>
</message> </message>
<message> <message>
<location filename="../src/settings.ui" line="230"/> <location filename="../src/settings.ui" line="230"/>
<source>Check github for updates at startup</source> <source>Check git for updates at startup</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
@ -1564,7 +1564,7 @@ Would you like to visit the releases page?</source>
</message> </message>
<message> <message>
<location filename="../src/settings.ui" line="312"/> <location filename="../src/settings.ui" line="312"/>
<source>Connect to github on startup to check for updates</source> <source>Connect to git on startup to check for updates</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
@ -1760,7 +1760,7 @@ Would you like to visit the releases page?</source>
</message> </message>
</context> </context>
<context> <context>
<name>createZcashConf</name> <name>createHushConf</name>
<message> <message>
<location filename="../src/createzcashconfdialog.ui" line="14"/> <location filename="../src/createzcashconfdialog.ui" line="14"/>
<source>Configure HUSH3.conf</source> <source>Configure HUSH3.conf</source>

BIN
res/silentdragon_tr.qm

Binary file not shown.

742
res/silentdragon_tr.ts

File diff suppressed because it is too large

BIN
res/silentdragon_uk.qm

Binary file not shown.

754
res/silentdragon_uk.ts

File diff suppressed because it is too large

BIN
res/silentdragon_zh.qm

Binary file not shown.

746
res/silentdragon_zh.ts

File diff suppressed because it is too large

BIN
res/tropical-hush-square.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

BIN
res/tropical-hush.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
res/zcashdlogo.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 74 KiB

2
run-after-build.sh

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/bash
# Copyright 2019-2020 The Hush Developers # Copyright 2019-2021 The Hush Developers
./build.sh && ./silentdragon ./build.sh && ./silentdragon

BIN
sapling-output.params

Binary file not shown.

BIN
sapling-spend.params

Binary file not shown.

BIN
silentdragon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

14
silentdragon.pro

@ -1,8 +1,6 @@
#------------------------------------------------- # Copyright 2018-2021 The Hush Developers
# # Released under the GPLv3
# Project created by QtCreator 2018-10-05T09:54:45 # Project created by QtCreator 2018-10-05T09:54:45
#
#-------------------------------------------------
QT += core gui network QT += core gui network
@ -51,6 +49,8 @@ SOURCES += \
src/sendtab.cpp \ src/sendtab.cpp \
src/senttxstore.cpp \ src/senttxstore.cpp \
src/txtablemodel.cpp \ src/txtablemodel.cpp \
src/peerstablemodel.cpp \
src/bannedpeerstablemodel.cpp \
src/qrcodelabel.cpp \ src/qrcodelabel.cpp \
src/connection.cpp \ src/connection.cpp \
src/fillediconlabel.cpp \ src/fillediconlabel.cpp \
@ -75,6 +75,8 @@ HEADERS += \
src/3rdparty/qrcode/QrSegment.hpp \ src/3rdparty/qrcode/QrSegment.hpp \
src/settings.h \ src/settings.h \
src/txtablemodel.h \ src/txtablemodel.h \
src/peerstablemodel.h \
src/bannedpeerstablemodel.h \
src/senttxstore.h \ src/senttxstore.h \
src/qrcodelabel.h \ src/qrcodelabel.h \
src/connection.h \ src/connection.h \
@ -111,7 +113,8 @@ FORMS += \
src/requestdialog.ui src/requestdialog.ui
TRANSLATIONS = res/silentdragon_bg.ts \ TRANSLATIONS = res/silentdragon_be.ts \
res/silentdragon_bg.ts \
res/silentdragon_de.ts \ res/silentdragon_de.ts \
res/silentdragon_es.ts \ res/silentdragon_es.ts \
res/silentdragon_fi.ts \ res/silentdragon_fi.ts \
@ -121,6 +124,7 @@ TRANSLATIONS = res/silentdragon_bg.ts \
res/silentdragon_id.ts \ res/silentdragon_id.ts \
res/silentdragon_it.ts \ res/silentdragon_it.ts \
res/silentdragon_nl.ts \ res/silentdragon_nl.ts \
res/silentdragon_pl.ts \
res/silentdragon_pt.ts \ res/silentdragon_pt.ts \
res/silentdragon_ro.ts \ res/silentdragon_ro.ts \
res/silentdragon_ru.ts \ res/silentdragon_ru.ts \

3
src/3rdparty/sodium.h

@ -1,9 +1,10 @@
// Copyright (c) 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef sodium_H #ifndef sodium_H
#define sodium_H #define sodium_H
#include "sodium/version.h" #include "sodium/version.h"
#include "sodium/core.h" #include "sodium/core.h"
#include "sodium/crypto_aead_aes256gcm.h" #include "sodium/crypto_aead_aes256gcm.h"
#include "sodium/crypto_aead_chacha20poly1305.h" #include "sodium/crypto_aead_chacha20poly1305.h"

10
src/about.ui

@ -53,13 +53,13 @@
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:12pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:12pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8.1pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8.1pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;Copyright(c) 2019-2020 The Hush developers (GPLv3)&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;Copyright(c) 2019-2021 The Hush developers (GPLv3)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;Copyright (c) 2019 Duke Leto, David Mercer and Aditya Kulkarni. (MIT License)&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;Copyright (c) 2019 Duke Leto, Jane Mercer and Aditya Kulkarni. (MIT License)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;Special thanks to:&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;Special thanks to:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;JSON for Modern C++ : &lt;/span&gt;&lt;a href=&quot;https://nlohmann.github.io/json/&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;https://nlohmann.github.io/json/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;JSON for Modern C++ : &lt;/span&gt;&lt;a href=&quot;https://nlohmann.github.io/json/&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2';text-decoration: underline; color:#0000ff;&quot;&gt;https://nlohmann.github.io/json/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;QR Code generator library Nayuki : &lt;/span&gt;&lt;a href=&quot;https://www.nayuki.io/page/qr-code-generator-library&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;https://www.nayuki.io/page/qr-code-ge…&lt;/span&gt;&lt;/a&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;QR Code generator library Nayuki : &lt;/span&gt;&lt;a href=&quot;https://www.nayuki.io/page/qr-code-generator-library&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;&quot;&gt;https://www.nayuki.io/page/qr-code-ge…&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;Made with QT : &lt;/span&gt;&lt;a href=&quot;https://www.qt.io/&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;https://www.qt.io/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;Made with QT : &lt;/span&gt;&lt;a href=&quot;https://www.qt.io/&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; text-decoration: underline; color:#0000ff;&quot;&gt;https://www.qt.io/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;LICENSE:&lt;/span&gt;&lt;/p&gt; &lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:11pt;&quot;&gt;LICENSE:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.en.html &lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.en.html

2
src/addressbook.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "addressbook.h" #include "addressbook.h"
#include "ui_addressbook.h" #include "ui_addressbook.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"

4
src/addressbook.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef ADDRESSBOOK_H #ifndef ADDRESSBOOK_H
#define ADDRESSBOOK_H #define ADDRESSBOOK_H
@ -66,4 +68,4 @@ private:
static AddressBook* instance; static AddressBook* instance;
}; };
#endif // ADDRESSBOOK_H #endif // ADDRESSBOOK_H

4
src/addresscombo.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "addresscombo.h" #include "addresscombo.h"
#include "addressbook.h" #include "addressbook.h"
#include "settings.h" #include "settings.h"
@ -36,4 +38,4 @@ void AddressCombo::insertItem(int index, const QString& text, double bal) {
QString txt = AddressBook::addLabelToAddress(text) % QString txt = AddressBook::addLabelToAddress(text) %
"(" % Settings::getDisplayFormat(bal) % ")"; "(" % Settings::getDisplayFormat(bal) % ")";
QComboBox::insertItem(index, txt); QComboBox::insertItem(index, txt);
} }

2
src/addresscombo.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef ADDRESSCOMBO_H #ifndef ADDRESSCOMBO_H
#define ADDRESSCOMBO_H #define ADDRESSCOMBO_H

2
src/balancestablemodel.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "balancestablemodel.h" #include "balancestablemodel.h"
#include "addressbook.h" #include "addressbook.h"
#include "settings.h" #include "settings.h"

4
src/balancestablemodel.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef BALANCESTABLEMODEL_H #ifndef BALANCESTABLEMODEL_H
#define BALANCESTABLEMODEL_H #define BALANCESTABLEMODEL_H
@ -31,4 +33,4 @@ private:
bool loading = true; bool loading = true;
}; };
#endif // BALANCESTABLEMODEL_H #endif // BALANCESTABLEMODEL_H

128
src/bannedpeerstablemodel.cpp

@ -0,0 +1,128 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "settings.h"
#include "rpc.h"
BannedPeersTableModel::BannedPeersTableModel(QObject *parent)
: QAbstractTableModel(parent) {
headers << QObject::tr("Address") << QObject::tr("Subnet") << QObject::tr("Banned Until");
}
BannedPeersTableModel::~BannedPeersTableModel() {
delete modeldata;
}
void BannedPeersTableModel::addData(const QList<BannedPeerItem>& data) {
bannedPeers = new QList<BannedPeerItem>();
std::copy(data.begin(), data.end(), std::back_inserter(*bannedPeers));
updateAllData();
}
void BannedPeersTableModel::updateAllData() {
auto newmodeldata = new QList<BannedPeerItem>();
// Copy peer data so GUI can use it
if (bannedPeers != nullptr) std::copy( bannedPeers->begin(), bannedPeers->end(), std::back_inserter(*newmodeldata));
// Sort by banned_until
std::sort(newmodeldata->begin(), newmodeldata->end(), [=] (auto a, auto b) {
return a.banned_until > b.banned_until; // reverse sort
});
// And then swap out the modeldata with the new one.
delete modeldata;
modeldata = newmodeldata;
// do magic
dataChanged(index(0, 0), index(modeldata->size()-1, columnCount(index(0,0))-1));
layoutChanged();
}
int BannedPeersTableModel::rowCount(const QModelIndex&) const
{
if (modeldata == nullptr) return 0;
return modeldata->size();
}
int BannedPeersTableModel::columnCount(const QModelIndex&) const
{
return headers.size();
}
QVariant BannedPeersTableModel::data(const QModelIndex &index, int role) const
{
auto dat = modeldata->at(index.row());
if (role == Qt::DisplayRole) {
switch (index.column()) {
case 0: return dat.address;
case 1: return dat.subnet;
case 2: return QDateTime::fromSecsSinceEpoch(dat.banned_until).toLocalTime().toString();
}
}
// we show mask because it's possible to ban ranges of addresses
if (role == Qt::ToolTipRole) {
switch (index.column()) {
case 0: return "Network Address";
case 1: return "Subnet Mask";
case 2: return "Banned Until " + QDateTime::fromSecsSinceEpoch(dat.banned_until).toUTC().toString();
}
}
//TODO: show different icons for IP vs Tor vs other kinds of connections
/*
if (role == Qt::DecorationRole && index.column() == 0) {
if (!dat.memo.isEmpty()) {
// If the memo is a Payment URI, then show a payment request icon
if (dat.memo.startsWith("hush:")) {
QIcon icon(":/icons/res/paymentreq.gif");
return QVariant(icon.pixmap(16, 16));
} else {
// Return the info pixmap to indicate memo
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
return QVariant(icon.pixmap(16, 16));
}
} else {
// Empty pixmap to make it align
QPixmap p(16, 16);
p.fill(Qt::white);
return QVariant(p);
}
}
*/
return QVariant();
}
QVariant BannedPeersTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
//if (role == Qt::TextAlignmentRole && section == 3) return QVariant(Qt::AlignRight | Qt::AlignVCenter);
if (role == Qt::TextAlignmentRole) return QVariant(Qt::AlignCenter | Qt::AlignVCenter);
if (role == Qt::FontRole) {
QFont f;
f.setBold(true);
return f;
}
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
return headers.at(section);
}
return QVariant();
}
QString BannedPeersTableModel::getAddress(int row) const {
return modeldata->at(row).address.trimmed();
}
QString BannedPeersTableModel::getSubnet(int row) const {
return modeldata->at(row).subnet;
}
qint64 BannedPeersTableModel::getBannedUntil(int row) const {
return modeldata->at(row).banned_until;
}

36
src/bannedpeerstablemodel.h

@ -0,0 +1,36 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef BANNEDPEERSTABLEMODEL_H
#define BANNEDPEERSTABLEMODEL_H
#include "precompiled.h"
struct BannedPeerItem;
class BannedPeersTableModel: public QAbstractTableModel
{
public:
BannedPeersTableModel(QObject* parent);
~BannedPeersTableModel();
QString getSubnet(int row) const;
QString getAddress(int row) const;
qint64 getBannedUntil(int row) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
void addData (const QList<BannedPeerItem>& data);
private:
void updateAllData();
QList<BannedPeerItem>* bannedPeers = nullptr;
QList<BannedPeerItem>* modeldata = nullptr;
QList<QString> headers;
};
#endif // BANNEDPEERSTABLEMODEL_H

193
src/connection.cpp

@ -1,15 +1,13 @@
// Copyright 2019-2020 The Hush developers // Copyright 2019-2021 The Hush developers
// GPLv3 // Released under the GPLv3
#include "connection.h" #include "connection.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "settings.h" #include "settings.h"
#include "ui_connection.h" #include "ui_connection.h"
#include "ui_createzcashconfdialog.h" #include "ui_createzcashconfdialog.h"
#include "rpc.h" #include "rpc.h"
#include "precompiled.h" #include "precompiled.h"
ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) { ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) {
this->main = main; this->main = main;
this->rpc = rpc; this->rpc = rpc;
@ -52,28 +50,28 @@ void ConnectionLoader::loadConnection() {
void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) { void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
// Priority 1: Ensure all params are present. // Priority 1: Ensure all params are present.
if (!verifyParams()) { if (!verifyParams()) {
downloadParams([=]() { this->doAutoConnect(); }); qDebug() << "Cannot find sapling params!";
return; return;
} }
// Priority 2: Try to connect to detect HUSH3.conf and connect to it. // Priority 2: Try to connect to detect HUSH3.conf and connect to it.
auto config = autoDetectZcashConf(); auto config = autoDetectHushConf();
main->logger->write(QObject::tr("Attempting autoconnect")); main->logger->write(QObject::tr("Attempting autoconnect"));
if (config.get() != nullptr) { if (config.get() != nullptr) {
auto connection = makeConnection(config); auto connection = makeConnection(config);
refreshZcashdState(connection, [=] () { refreshHushdState(connection, [=] () {
// Refused connection. So try and start embedded zcashd // Refused connection. So try and start embedded hushd
if (Settings::getInstance()->useEmbedded()) { if (Settings::getInstance()->useEmbedded()) {
if (tryEzcashdStart) { if (tryEzcashdStart) {
this->showInformation(QObject::tr("Starting embedded hushd")); this->showInformation(QObject::tr("Starting embedded hushd"));
if (this->startEmbeddedZcashd()) { if (this->startEmbeddedHushd()) {
// Embedded hushd started up. Wait a second and then refresh the connection // Embedded hushd started up. Wait a second and then refresh the connection
main->logger->write("Embedded hushd started up, trying autoconnect in 1 sec"); main->logger->write("Embedded hushd started up, trying autoconnect in 1 sec");
QTimer::singleShot(1000, [=]() { doAutoConnect(); } ); QTimer::singleShot(1000, [=]() { doAutoConnect(); } );
} else { } else {
if (config->zcashDaemon) { if (config->hushDaemon) {
// hushd is configured to run as a daemon, so we must wait for a few seconds // hushd is configured to run as a daemon, so we must wait for a few seconds
// to let it start up. // to let it start up.
main->logger->write("hushd is daemon=1. Waiting for it to start up"); main->logger->write("hushd is daemon=1. Waiting for it to start up");
@ -84,14 +82,14 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
// We're going to attempt to connect to the one in the background one last time // We're going to attempt to connect to the one in the background one last time
// and see if that works, else throw an error // and see if that works, else throw an error
main->logger->write("Unknown problem while trying to start hushd!"); main->logger->write("Unknown problem while trying to start hushd!");
QTimer::singleShot(2000, [=]() { doAutoConnect(/* don't attempt to start ezcashd */ false); }); QTimer::singleShot(2000, [=]() { doAutoConnect(/* don't attempt to start ehushd */ false); });
} }
} }
} else { } else {
// We tried to start ezcashd previously, and it didn't work. So, show the error. // We tried to start ehushd previously, and it didn't work. So, show the error.
main->logger->write("Couldn't start embedded hushd for unknown reason"); main->logger->write("Couldn't start embedded hushd for unknown reason");
QString explanation; QString explanation;
if (config->zcashDaemon) { if (config->hushDaemon) {
explanation = QString() % QObject::tr("You have hushd set to start as a daemon, which can cause problems " explanation = QString() % QObject::tr("You have hushd set to start as a daemon, which can cause problems "
"with SilentDragon\n\n." "with SilentDragon\n\n."
"Please remove the following line from your HUSH3.conf and restart SilentDragon\n" "Please remove the following line from your HUSH3.conf and restart SilentDragon\n"
@ -100,7 +98,7 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
explanation = QString() % QObject::tr("Couldn't start the embedded hushd.\n\n" explanation = QString() % QObject::tr("Couldn't start the embedded hushd.\n\n"
"Please try restarting.\n\nIf you previously started hushd with custom arguments, you might need to reset HUSH3.conf.\n\n" "Please try restarting.\n\nIf you previously started hushd with custom arguments, you might need to reset HUSH3.conf.\n\n"
"If all else fails, please run hushd manually.") % "If all else fails, please run hushd manually.") %
(ezcashd ? QObject::tr("The process returned") + ":\n\n" % ezcashd->errorString() : QString("")); (ehushd ? QObject::tr("The process returned") + ":\n\n" % ehushd->errorString() : QString(""));
} }
this->showError(explanation); this->showError(explanation);
@ -116,7 +114,7 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
} else { } else {
if (Settings::getInstance()->useEmbedded()) { if (Settings::getInstance()->useEmbedded()) {
// HUSH3.conf was not found, so create one // HUSH3.conf was not found, so create one
createZcashConf(); createHushConf();
} else { } else {
// Fall back to manual connect // Fall back to manual connect
doManualConnect(); doManualConnect();
@ -144,17 +142,17 @@ QString randomPassword() {
/** /**
* This will create a new HUSH3.conf and download params if they cannot be found * This will create a new HUSH3.conf and download params if they cannot be found
*/ */
void ConnectionLoader::createZcashConf() { void ConnectionLoader::createHushConf() {
main->logger->write("createZcashConf"); main->logger->write(__func__);
auto confLocation = zcashConfWritableLocation(); auto confLocation = hushConfWritableLocation();
QFileInfo fi(confLocation); QFileInfo fi(confLocation);
QDialog d(main); QDialog d(main);
Ui_createZcashConf ui; Ui_createHushConf ui;
ui.setupUi(&d); ui.setupUi(&d);
QPixmap logo(":/img/res/zcashdlogo.gif"); QPixmap logo(":/img/res/tropical-hush-square.png");
ui.lblTopIcon->setBasePixmap(logo.scaled(512,512, Qt::KeepAspectRatio, Qt::SmoothTransformation)); ui.lblTopIcon->setBasePixmap(logo.scaled(512,512, Qt::KeepAspectRatio, Qt::SmoothTransformation));
ui.btnPickDir->setEnabled(false); ui.btnPickDir->setEnabled(false);
@ -202,7 +200,7 @@ void ConnectionLoader::createZcashConf() {
QTextStream out(&file); QTextStream out(&file);
out << "# Autogenerated by Hush SilentDragon https://myhush.org\n"; out << "# Autogenerated by Hush SilentDragon https://hush.is\n";
out << "server=1\n"; out << "server=1\n";
out << "rpcuser=hush\n"; out << "rpcuser=hush\n";
out << "rpcpassword=" % randomPassword() << "\n"; out << "rpcpassword=" % randomPassword() << "\n";
@ -217,6 +215,10 @@ void ConnectionLoader::createZcashConf() {
// Consolidation is now defaulted to ON for new wallets // Consolidation is now defaulted to ON for new wallets
out << "consolidation=1\n"; out << "consolidation=1\n";
// This is default behavior for hushd 3.6.1 and newer,
// this helps if older hushd's are being used
out << "tls=only\n";
if (!datadir.isEmpty()) { if (!datadir.isEmpty()) {
out << "datadir=" % datadir % "\n"; out << "datadir=" % datadir % "\n";
} }
@ -231,19 +233,6 @@ void ConnectionLoader::createZcashConf() {
} }
void ConnectionLoader::downloadParams(std::function<void(void)> cb) {
main->logger->write("Adding params to download queue");
// Add all the files to the download queue
downloadQueue = new QQueue<QUrl>();
client = new QNetworkAccessManager(main);
//Currently we fallback to this in rare edgecases, it's not normally executed
downloadQueue->enqueue(QUrl("https://z.cash/downloads/sapling-output.params"));
downloadQueue->enqueue(QUrl("https://z.cash/downloads/sapling-spend.params"));
doNextDownload(cb);
}
void ConnectionLoader::doNextDownload(std::function<void(void)> cb) { void ConnectionLoader::doNextDownload(std::function<void(void)> cb) {
auto fnSaveFileName = [&] (QUrl url) { auto fnSaveFileName = [&] (QUrl url) {
QString path = url.path(); QString path = url.path();
@ -334,7 +323,7 @@ void ConnectionLoader::doNextDownload(std::function<void(void)> cb) {
}); });
} }
bool ConnectionLoader::startEmbeddedZcashd() { bool ConnectionLoader::startEmbeddedHushd() {
if (!Settings::getInstance()->useEmbedded()) if (!Settings::getInstance()->useEmbedded())
return false; return false;
@ -343,8 +332,8 @@ bool ConnectionLoader::startEmbeddedZcashd() {
// Static because it needs to survive even after this method returns. // Static because it needs to survive even after this method returns.
static QString processStdErrOutput; static QString processStdErrOutput;
if (ezcashd != nullptr) { if (ehushd != nullptr) {
if (ezcashd->state() == QProcess::NotRunning) { if (ehushd->state() == QProcess::NotRunning) {
if (!processStdErrOutput.isEmpty()) { if (!processStdErrOutput.isEmpty()) {
QMessageBox::critical(main, QObject::tr("hushd error"), "hushd said: " + processStdErrOutput, QMessageBox::critical(main, QObject::tr("hushd error"), "hushd said: " + processStdErrOutput,
QMessageBox::Ok); QMessageBox::Ok);
@ -358,9 +347,9 @@ bool ConnectionLoader::startEmbeddedZcashd() {
QDir appPath(QCoreApplication::applicationDirPath()); QDir appPath(QCoreApplication::applicationDirPath());
#ifdef Q_OS_WIN64 #ifdef Q_OS_WIN64
auto hushdProgram = appPath.absoluteFilePath("komodod.exe"); auto hushdProgram = appPath.absoluteFilePath("hushd.exe");
#else #else
auto hushdProgram = appPath.absoluteFilePath("komodod"); auto hushdProgram = appPath.absoluteFilePath("hushd");
#endif #endif
//if (!QFile(hushdProgram).exists()) { //if (!QFile(hushdProgram).exists()) {
@ -372,48 +361,59 @@ bool ConnectionLoader::startEmbeddedZcashd() {
main->logger->write("Found hushd at " + hushdProgram); main->logger->write("Found hushd at " + hushdProgram);
} }
ezcashd = std::shared_ptr<QProcess>(new QProcess(main)); ehushd = std::shared_ptr<QProcess>(new QProcess(main));
QObject::connect(ezcashd.get(), &QProcess::started, [=] () { QObject::connect(ehushd.get(), &QProcess::started, [=] () {
qDebug() << "Embedded hushd started via " << hushdProgram; qDebug() << "Embedded hushd started via " << hushdProgram;
}); });
QObject::connect(ezcashd.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), QObject::connect(ehushd.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[=](int exitCode, QProcess::ExitStatus exitStatus) { [=](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug() << "hushd finished with code " << exitCode << "," << exitStatus; qDebug() << "hushd finished with code " << exitCode << "," << exitStatus;
}); });
QObject::connect(ezcashd.get(), &QProcess::errorOccurred, [&] (QProcess::ProcessError error) { QObject::connect(ehushd.get(), &QProcess::errorOccurred, [&] (QProcess::ProcessError error) {
qDebug() << "Couldn't start hushd at " << hushdProgram << ":" << error; qDebug() << "Couldn't start hushd at " << hushdProgram << ":" << error;
}); });
std::weak_ptr<QProcess> weak_obj(ezcashd); std::weak_ptr<QProcess> weak_obj(ehushd);
auto ptr_main(main); auto ptr_main(main);
QObject::connect(ezcashd.get(), &QProcess::readyReadStandardError, [weak_obj, ptr_main]() { QObject::connect(ehushd.get(), &QProcess::readyReadStandardError, [weak_obj, ptr_main]() {
auto output = weak_obj.lock()->readAllStandardError(); auto output = weak_obj.lock()->readAllStandardError();
ptr_main->logger->write("hushd stderr:" + output); ptr_main->logger->write("hushd stderr:" + output);
processStdErrOutput.append(output); processStdErrOutput.append(output);
}); });
// This string should be the exact arg list seperated by single spaces // This string should be the exact arg list seperated by single spaces
QString params = "-ac_name=HUSH3 -ac_sapling=1 -ac_reward=0,1125000000,562500000 -ac_halving=129,340000,840000 -ac_end=128,340000,5422111 -ac_eras=3 -ac_blocktime=150 -ac_cc=2 -ac_ccenable=228,234,235,236,241 -ac_founders=1 -ac_supply=6178674 -ac_perc=11111111 -clientname=GoldenSandtrout -addnode=188.165.212.101 -addnode=64.120.113.130 -addnode=209.58.144.205 -addnode=94.130.35.94 -ac_cclib=hush3 -ac_script=76a9145eb10cf64f2bab1b457f1f25e658526155928fac88ac"; // Could be modified to start different Hush Smart Chains
QString params = ""; // "-ac_name=TUSH";
/* This is now enabled by default in hushd
// Binaries come with this file
if(QFile( QDir(".").filePath("asmap.dat") ).exists()) {
auto asmap = appPath.absoluteFilePath("asmap.dat");
params += " -asmap=" + asmap;
} else {
qDebug() << "No ASN map file found";
}
*/
QStringList arguments = params.split(" "); QStringList arguments = params.split(" ");
// Finally, actually start the full node
// Finally, actually start the full node
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
qDebug() << "Starting on Linux: " + hushdProgram + " " + params; qDebug() << "Starting on Linux: " + hushdProgram + " " + params;
ezcashd->start(hushdProgram, arguments); ehushd->start(hushdProgram, arguments);
#elif defined(Q_OS_DARWIN) #elif defined(Q_OS_DARWIN)
qDebug() << "Starting on Darwin: " + hushdProgram + " " + params; qDebug() << "Starting on Darwin: " + hushdProgram + " " + params;
ezcashd->start(hushdProgram, arguments); ehushd->start(hushdProgram, arguments);
#elif defined(Q_OS_WIN64) #elif defined(Q_OS_WIN64)
qDebug() << "Starting on Win64: " + hushdProgram + " " + params; qDebug() << "Starting on Win64: " + hushdProgram + " " + params;
ezcashd->setWorkingDirectory(appPath.absolutePath()); ehushd->setWorkingDirectory(appPath.absolutePath());
ezcashd->start(hushdProgram, arguments); ehushd->start(hushdProgram, arguments);
#else #else
qDebug() << "Starting on Unknown OS(!): " + hushdProgram + " " + params; qDebug() << "Starting on Unknown OS(!): " + hushdProgram + " " + params;
ezcashd->setWorkingDirectory(appPath.absolutePath()); ehushd->setWorkingDirectory(appPath.absolutePath());
ezcashd->start(hushdProgram, arguments); ehushd->start(hushdProgram, arguments);
#endif // Q_OS_LINUX #endif // Q_OS_LINUX
main->logger->write("Started via " + hushdProgram + " " + params); main->logger->write("Started via " + hushdProgram + " " + params);
@ -436,7 +436,7 @@ void ConnectionLoader::doManualConnect() {
} }
auto connection = makeConnection(config); auto connection = makeConnection(config);
refreshZcashdState(connection, [=] () { refreshHushdState(connection, [=] () {
QString explanation = QString() QString explanation = QString()
% QObject::tr("Could not connect to hushd configured in settings.\n\n" % QObject::tr("Could not connect to hushd configured in settings.\n\n"
"Please set the host/port and user/password in the Edit->Settings menu."); "Please set the host/port and user/password in the Edit->Settings menu.");
@ -449,7 +449,7 @@ void ConnectionLoader::doManualConnect() {
} }
void ConnectionLoader::doRPCSetConnection(Connection* conn) { void ConnectionLoader::doRPCSetConnection(Connection* conn) {
rpc->setEZcashd(ezcashd); rpc->setEHushd(ehushd);
rpc->setConnection(conn); rpc->setConnection(conn);
d->accept(); d->accept();
@ -476,7 +476,7 @@ Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> c
return new Connection(main, client, request, config); return new Connection(main, client, request, config);
} }
void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<void(void)> refused) { void ConnectionLoader::refreshHushdState(Connection* connection, std::function<void(void)> refused) {
main->logger->write("refreshing state"); main->logger->write("refreshing state");
QJsonObject payload = { QJsonObject payload = {
@ -519,7 +519,7 @@ void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<
this->showInformation(QObject::tr("Your hushd is starting up. Please wait."), status); this->showInformation(QObject::tr("Your hushd is starting up. Please wait."), status);
main->logger->write("Waiting for hushd to come online."); main->logger->write("Waiting for hushd to come online.");
// Refresh after one second // Refresh after one second
QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection, refused); }); QTimer::singleShot(1000, [=]() { this->refreshHushdState(connection, refused); });
} }
} }
); );
@ -547,36 +547,49 @@ void ConnectionLoader::showInformation(QString info, QString detail) {
* Show error will close the loading dialog and show an error. * Show error will close the loading dialog and show an error.
*/ */
void ConnectionLoader::showError(QString explanation) { void ConnectionLoader::showError(QString explanation) {
rpc->setEZcashd(nullptr); rpc->setEHushd(nullptr);
rpc->noConnection(); rpc->noConnection();
QMessageBox::critical(main, QObject::tr("Connection Error"), explanation, QMessageBox::Ok); QMessageBox::critical(main, QObject::tr("Connection Error"), explanation, QMessageBox::Ok);
d->close(); d->close();
} }
QString ConnectionLoader::locateZcashConfFile() { QString ConnectionLoader::locateHushConfFile() {
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, ".komodo/HUSH3/HUSH3.conf"); auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, ".hush/HUSH3/HUSH3.conf");
if(!QFile(confLocation).exists()) {
// legacy location
confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, ".komodo/HUSH3/HUSH3.conf");
}
#elif defined(Q_OS_DARWIN) #elif defined(Q_OS_DARWIN)
auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, "Library/Application Support/Komodo/HUSH3/HUSH3.conf"); auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, "Library/Application Support/Hush/HUSH3/HUSH3.conf");
if(!QFile(confLocation).exists()) {
// legacy location
confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, "Library/Application Support/Komodo/HUSH3/HUSH3.conf");
}
#else #else
auto confLocation = QStandardPaths::locate(QStandardPaths::AppDataLocation, "../../Komodo/HUSH3/HUSH3.conf"); auto confLocation = QStandardPaths::locate(QStandardPaths::AppDataLocation, "../../Hush/HUSH3/HUSH3.conf");
if(!QFile(confLocation).exists()) {
// legacy location
confLocation = QStandardPaths::locate(QStandardPaths::AppDataLocation, "../../Komodo/HUSH3/HUSH3.conf");
}
#endif #endif
main->logger->write("Found HUSH3.conf at " + QDir::cleanPath(confLocation)); main->logger->write("Found HUSH3.conf at " + QDir::cleanPath(confLocation));
return QDir::cleanPath(confLocation); return QDir::cleanPath(confLocation);
} }
QString ConnectionLoader::zcashConfWritableLocation() { // this function is only used for new config files and does not need to know about legacy locations
QString ConnectionLoader::hushConfWritableLocation() {
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".komodo/HUSH3/HUSH3.conf"); auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".hush/HUSH3/HUSH3.conf");
#elif defined(Q_OS_DARWIN) #elif defined(Q_OS_DARWIN)
auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath("Library/Application Support/Komodo/HUSH3/HUSH3.conf"); auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath("Library/Application Support/Hush/HUSH3/HUSH3.conf");
#else #else
auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("../../Komodo/HUSH3/HUSH3.conf"); auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("../../Hush/HUSH3/HUSH3.conf");
#endif #endif
main->logger->write("Found HUSH3.conf at " + QDir::cleanPath(confLocation)); main->logger->write("HUSH3.conf writeable location at " + QDir::cleanPath(confLocation));
return QDir::cleanPath(confLocation); return QDir::cleanPath(confLocation);
} }
@ -650,11 +663,11 @@ bool ConnectionLoader::verifyParams() {
/** /**
* Try to automatically detect a HUSH3/HUSH3.conf file in the correct location and load parameters * Try to automatically detect a HUSH3/HUSH3.conf file in the correct location and load parameters
*/ */
std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectZcashConf() { std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectHushConf() {
auto confLocation = locateZcashConfFile(); auto confLocation = locateHushConfFile();
if (confLocation.isNull()) { if (confLocation.isNull()) {
// No Zcash file, just return with nothing // No file, just return with nothing
return nullptr; return nullptr;
} }
@ -666,14 +679,14 @@ std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectZcashConf() {
QTextStream in(&file); QTextStream in(&file);
auto zcashconf = new ConnectionConfig(); auto hushconf = new ConnectionConfig();
zcashconf->host = "127.0.0.1"; hushconf->host = "127.0.0.1";
zcashconf->connType = ConnectionType::DetectedConfExternalZcashD; hushconf->connType = ConnectionType::DetectedConfExternalHushD;
zcashconf->usingZcashConf = true; hushconf->usingHushConf = true;
zcashconf->zcashDir = QFileInfo(confLocation).absoluteDir().absolutePath(); hushconf->hushDir = QFileInfo(confLocation).absoluteDir().absolutePath();
zcashconf->zcashDaemon = false; hushconf->hushDaemon = false;
Settings::getInstance()->setUsingZcashConf(confLocation); Settings::getInstance()->setUsingHushConf(confLocation);
while (!in.atEnd()) { while (!in.atEnd()) {
QString line = in.readLine(); QString line = in.readLine();
@ -682,43 +695,43 @@ std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectZcashConf() {
QString value = line.right(line.length() - s - 1).trimmed(); QString value = line.right(line.length() - s - 1).trimmed();
if (name == "rpcuser") { if (name == "rpcuser") {
zcashconf->rpcuser = value; hushconf->rpcuser = value;
} }
if (name == "rpcpassword") { if (name == "rpcpassword") {
zcashconf->rpcpassword = value; hushconf->rpcpassword = value;
} }
if (name == "rpcport") { if (name == "rpcport") {
zcashconf->port = value; hushconf->port = value;
} }
if (name == "daemon" && value == "1") { if (name == "daemon" && value == "1") {
zcashconf->zcashDaemon = true; hushconf->hushDaemon = true;
} }
if (name == "proxy") { if (name == "proxy") {
zcashconf->proxy = value; hushconf->proxy = value;
} }
if (name == "consolidation") { if (name == "consolidation") {
zcashconf->consolidation = value; hushconf->consolidation = value;
} }
if (name == "deletetx") { if (name == "deletetx") {
zcashconf->deletetx = value; hushconf->deletetx = value;
} }
if (name == "zindex") { if (name == "zindex") {
zcashconf->zindex = value; hushconf->zindex = value;
} }
if (name == "testnet" && if (name == "testnet" &&
value == "1" && value == "1" &&
zcashconf->port.isEmpty()) { hushconf->port.isEmpty()) {
zcashconf->port = "18232"; hushconf->port = "18232";
} }
} }
// If rpcport is not in the file, and it was not set by the testnet=1 flag, then go to default // If rpcport is not in the file, and it was not set by the testnet=1 flag, then go to default
if (zcashconf->port.isEmpty()) zcashconf->port = "18031"; if (hushconf->port.isEmpty()) hushconf->port = "18031";
file.close(); file.close();
// In addition to the HUSH3/HUSH3.conf file, also double check the params. // In addition to the HUSH3/HUSH3.conf file, also double check the params.
return std::shared_ptr<ConnectionConfig>(zcashconf); return std::shared_ptr<ConnectionConfig>(hushconf);
} }
/** /**

26
src/connection.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef CONNECTION_H #ifndef CONNECTION_H
#define CONNECTION_H #define CONNECTION_H
@ -8,9 +10,9 @@
class RPC; class RPC;
enum ConnectionType { enum ConnectionType {
DetectedConfExternalZcashD = 1, DetectedConfExternalHushD = 1,
UISettingsZCashD, UISettingsZCashD,
InternalZcashD InternalHushD
}; };
struct ConnectionConfig { struct ConnectionConfig {
@ -18,9 +20,9 @@ struct ConnectionConfig {
QString port; QString port;
QString rpcuser; QString rpcuser;
QString rpcpassword; QString rpcpassword;
bool usingZcashConf; bool usingHushConf;
bool zcashDaemon; bool hushDaemon;
QString zcashDir; QString hushDir;
QString proxy; QString proxy;
QString consolidation; QString consolidation;
QString deletetx; QString deletetx;
@ -40,7 +42,7 @@ public:
void loadConnection(); void loadConnection();
private: private:
std::shared_ptr<ConnectionConfig> autoDetectZcashConf(); std::shared_ptr<ConnectionConfig> autoDetectHushConf();
std::shared_ptr<ConnectionConfig> loadFromSettings(); std::shared_ptr<ConnectionConfig> loadFromSettings();
Connection* makeConnection(std::shared_ptr<ConnectionConfig> config); Connection* makeConnection(std::shared_ptr<ConnectionConfig> config);
@ -48,24 +50,24 @@ private:
void doAutoConnect(bool tryEzcashdStart = true); void doAutoConnect(bool tryEzcashdStart = true);
void doManualConnect(); void doManualConnect();
void createZcashConf(); void createHushConf();
QString locateZcashConfFile(); QString locateHushConfFile();
QString zcashConfWritableLocation(); QString hushConfWritableLocation();
QString zcashParamsDir(); QString zcashParamsDir();
bool verifyParams(); bool verifyParams();
void downloadParams(std::function<void(void)> cb); void downloadParams(std::function<void(void)> cb);
void doNextDownload(std::function<void(void)> cb); void doNextDownload(std::function<void(void)> cb);
bool startEmbeddedZcashd(); bool startEmbeddedHushd();
void refreshZcashdState(Connection* connection, std::function<void(void)> refused); void refreshHushdState(Connection* connection, std::function<void(void)> refused);
void showError(QString explanation); void showError(QString explanation);
void showInformation(QString info, QString detail = ""); void showInformation(QString info, QString detail = "");
void doRPCSetConnection(Connection* conn); void doRPCSetConnection(Connection* conn);
std::shared_ptr<QProcess> ezcashd; std::shared_ptr<QProcess> ehushd;
QDialog* d; QDialog* d;
Ui_ConnectionDialog* connD; Ui_ConnectionDialog* connD;

8
src/createzcashconfdialog.ui

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>createZcashConf</class> <class>createHushConf</class>
<widget class="QDialog" name="createZcashConf"> <widget class="QDialog" name="createHushConf">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -179,7 +179,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>accepted()</signal> <signal>accepted()</signal>
<receiver>createZcashConf</receiver> <receiver>createHushConf</receiver>
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
@ -195,7 +195,7 @@
<connection> <connection>
<sender>buttonBox</sender> <sender>buttonBox</sender>
<signal>rejected()</signal> <signal>rejected()</signal>
<receiver>createZcashConf</receiver> <receiver>createHushConf</receiver>
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">

4
src/fillediconlabel.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "fillediconlabel.h" #include "fillediconlabel.h"
FilledIconLabel::FilledIconLabel(QWidget* parent) : FilledIconLabel::FilledIconLabel(QWidget* parent) :
@ -24,4 +26,4 @@ void FilledIconLabel::resizeEvent(QResizeEvent*) {
painter.drawPixmap((sz.width() - scaled.width()) / 2, (sz.height() - scaled.height()) / 2, scaled); painter.drawPixmap((sz.width() - scaled.width()) / 2, (sz.height() - scaled.height()) / 2, scaled);
QLabel::setPixmap(p); QLabel::setPixmap(p);
} }

4
src/fillediconlabel.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef FILLEDICONLABEL_H #ifndef FILLEDICONLABEL_H
#define FILLEDICONLABEL_H #define FILLEDICONLABEL_H
@ -18,4 +20,4 @@ private:
}; };
#endif // FILLEDICONLABEL_H #endif // FILLEDICONLABEL_H

4
src/logger.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "logger.h" #include "logger.h"
Logger::Logger(QObject *parent, QString fileName) : QObject(parent) { Logger::Logger(QObject *parent, QString fileName) : QObject(parent) {
@ -28,4 +30,4 @@ void Logger::write(const QString &value) {
Logger::~Logger() { Logger::~Logger() {
if (file != 0) if (file != 0)
file->close(); file->close();
} }

4
src/logger.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef LOGGER_H #ifndef LOGGER_H
#define LOGGER_H #define LOGGER_H
@ -20,4 +22,4 @@ public slots:
void write(const QString &value); void write(const QString &value);
}; };
#endif // LOGGER_H #endif // LOGGER_H

10
src/main.cpp

@ -1,12 +1,10 @@
// Copyright 2019-2020 The Hush developers // Copyright 2019-2021 The Hush developers
// GPLv3 // Released under the GPLv3
#include <singleapplication.h> #include <singleapplication.h>
#include "precompiled.h" #include "precompiled.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "rpc.h" #include "rpc.h"
#include "settings.h" #include "settings.h"
#include "version.h" #include "version.h"
class SignalHandler class SignalHandler
@ -224,7 +222,7 @@ public:
// If there was a payment URI on the command line, pay it // If there was a payment URI on the command line, pay it
if (parser.positionalArguments().length() > 0) { if (parser.positionalArguments().length() > 0) {
w->payZcashURI(parser.positionalArguments()[0]); w->payHushURI(parser.positionalArguments()[0]);
} }
// Listen for any secondary instances telling us about a Hush payment URI // Listen for any secondary instances telling us about a Hush payment URI
@ -232,7 +230,7 @@ public:
QString uri(msg); QString uri(msg);
// We need to execute this async, otherwise the app seems to crash for some reason. // We need to execute this async, otherwise the app seems to crash for some reason.
QTimer::singleShot(1, [=]() { w->payZcashURI(uri); }); QTimer::singleShot(1, [=]() { w->payHushURI(uri); });
}); });
// For MacOS, we have an event filter // For MacOS, we have an event filter

293
src/mainwindow.cpp

@ -1,4 +1,4 @@
// Copyright 2019-2020 The Hush Developers // Copyright 2019-2021 The Hush Developers
// Released under the GPLv3 // Released under the GPLv3
#include "mainwindow.h" #include "mainwindow.h"
#include "addressbook.h" #include "addressbook.h"
@ -22,7 +22,6 @@
#include "requestdialog.h" #include "requestdialog.h"
#include "websockets.h" #include "websockets.h"
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
ui(new Ui::MainWindow) ui(new Ui::MainWindow)
@ -48,16 +47,11 @@ MainWindow::MainWindow(QWidget *parent) :
// Settings editor // Settings editor
setupSettingsModal(); setupSettingsModal();
// Set up exit action // Set up actions
QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close);
// Set up feedback action
QObject::connect(ui->actionDonate, &QAction::triggered, this, &MainWindow::donate); QObject::connect(ui->actionDonate, &QAction::triggered, this, &MainWindow::donate);
QObject::connect(ui->actionTelegram, &QAction::triggered, this, &MainWindow::telegram);
QObject::connect(ui->actionDiscord, &QAction::triggered, this, &MainWindow::discord);
QObject::connect(ui->actionReportBug, &QAction::triggered, this, &MainWindow::reportbug); QObject::connect(ui->actionReportBug, &QAction::triggered, this, &MainWindow::reportbug);
QObject::connect(ui->actionWebsite, &QAction::triggered, this, &MainWindow::website); QObject::connect(ui->actionWebsite, &QAction::triggered, this, &MainWindow::website);
// Set up check for updates action // Set up check for updates action
@ -73,7 +67,7 @@ MainWindow::MainWindow(QWidget *parent) :
// Pay Hush URI // Pay Hush URI
QObject::connect(ui->actionPay_URI, &QAction::triggered, [=] () { QObject::connect(ui->actionPay_URI, &QAction::triggered, [=] () {
payZcashURI(); payHushURI();
}); });
// Import Private Key // Import Private Key
@ -109,7 +103,7 @@ MainWindow::MainWindow(QWidget *parent) :
about.setupUi(&aboutDialog); about.setupUi(&aboutDialog);
Settings::saveRestore(&aboutDialog); Settings::saveRestore(&aboutDialog);
QString version = QString("Version ") % QString(APP_VERSION) % " (" % QString(__DATE__) % ")"; QString version = QString("Version ") % QString(APP_VERSION) % " (" % QString(__DATE__) % ") using QT " % qVersion();
about.versionLabel->setText(version); about.versionLabel->setText(version);
aboutDialog.exec(); aboutDialog.exec();
@ -125,6 +119,7 @@ MainWindow::MainWindow(QWidget *parent) :
setupMarketTab(); setupMarketTab();
//setupChatTab(); //setupChatTab();
setupHushTab(); setupHushTab();
setupPeersTab();
rpc = new RPC(this); rpc = new RPC(this);
qDebug() << "Created RPC"; qDebug() << "Created RPC";
@ -200,7 +195,7 @@ void MainWindow::closeEvent(QCloseEvent* event) {
s.sync(); s.sync();
// Let the RPC know to shut down any running service. // Let the RPC know to shut down any running service.
rpc->shutdownZcashd(); rpc->shutdownHushd();
// Bubble up // Bubble up
if (event) if (event)
@ -339,7 +334,7 @@ void MainWindow::setupSettingsModal() {
isUsingTor = !rpc->getConnection()->config->proxy.isEmpty(); isUsingTor = !rpc->getConnection()->config->proxy.isEmpty();
} }
settings.chkTor->setChecked(isUsingTor); settings.chkTor->setChecked(isUsingTor);
if (rpc->getEZcashD() == nullptr) { if (rpc->getEHushD() == nullptr) {
settings.chkTor->setEnabled(false); settings.chkTor->setEnabled(false);
settings.lblTor->setEnabled(false); settings.lblTor->setEnabled(false);
QString tooltip = tr("Tor configuration is available only when running an embedded hushd."); QString tooltip = tr("Tor configuration is available only when running an embedded hushd.");
@ -351,8 +346,8 @@ void MainWindow::setupSettingsModal() {
bool isUsingConsolidation = false; bool isUsingConsolidation = false;
int size = 0; int size = 0;
QDir zcashdir(rpc->getConnection()->config->zcashDir); QDir hushdir(rpc->getConnection()->config->hushDir);
QFile WalletSize(zcashdir.filePath("wallet.dat")); QFile WalletSize(hushdir.filePath("wallet.dat"));
if (WalletSize.open(QIODevice::ReadOnly)){ if (WalletSize.open(QIODevice::ReadOnly)){
size = WalletSize.size() / 1000000; //when file does open. size = WalletSize.size() / 1000000; //when file does open.
//QString size1 = QString::number(size) ; //QString size1 = QString::number(size) ;
@ -363,7 +358,7 @@ void MainWindow::setupSettingsModal() {
isUsingConsolidation = !rpc->getConnection()->config->consolidation.isEmpty() == true; isUsingConsolidation = !rpc->getConnection()->config->consolidation.isEmpty() == true;
} }
settings.chkConso->setChecked(isUsingConsolidation); settings.chkConso->setChecked(isUsingConsolidation);
if (rpc->getEZcashD() == nullptr) { if (rpc->getEHushD() == nullptr) {
settings.chkConso->setEnabled(false); settings.chkConso->setEnabled(false);
} }
@ -374,7 +369,7 @@ void MainWindow::setupSettingsModal() {
isUsingDeletetx = !rpc->getConnection()->config->deletetx.isEmpty() == true; isUsingDeletetx = !rpc->getConnection()->config->deletetx.isEmpty() == true;
} }
settings.chkDeletetx->setChecked(isUsingDeletetx); settings.chkDeletetx->setChecked(isUsingDeletetx);
if (rpc->getEZcashD() == nullptr) { if (rpc->getEHushD() == nullptr) {
settings.chkDeletetx->setEnabled(false); settings.chkDeletetx->setEnabled(false);
} }
@ -385,7 +380,7 @@ void MainWindow::setupSettingsModal() {
isUsingZindex = !rpc->getConnection()->config->zindex.isEmpty() == true; isUsingZindex = !rpc->getConnection()->config->zindex.isEmpty() == true;
} }
settings.chkzindex->setChecked(isUsingZindex); settings.chkzindex->setChecked(isUsingZindex);
if (rpc->getEZcashD() == nullptr) { if (rpc->getEHushD() == nullptr) {
settings.chkzindex->setEnabled(false); settings.chkzindex->setEnabled(false);
} }
@ -394,9 +389,9 @@ void MainWindow::setupSettingsModal() {
settings.port->setValidator(&validator); settings.port->setValidator(&validator);
// If values are coming from HUSH3.conf, then disable all the fields // If values are coming from HUSH3.conf, then disable all the fields
auto zcashConfLocation = Settings::getInstance()->getZcashdConfLocation(); auto hushConfLocation = Settings::getInstance()->getHushdConfLocation();
if (!zcashConfLocation.isEmpty()) { if (!hushConfLocation.isEmpty()) {
settings.confMsg->setText("Settings are being read from \n" + zcashConfLocation); settings.confMsg->setText("Settings are being read from \n" + hushConfLocation);
settings.hostname->setEnabled(false); settings.hostname->setEnabled(false);
settings.port->setEnabled(false); settings.port->setEnabled(false);
settings.rpcuser->setEnabled(false); settings.rpcuser->setEnabled(false);
@ -455,7 +450,7 @@ void MainWindow::setupSettingsModal() {
if (!isUsingTor && settings.chkTor->isChecked()) { if (!isUsingTor && settings.chkTor->isChecked()) {
// If "use tor" was previously unchecked and now checked // If "use tor" was previously unchecked and now checked
Settings::addToZcashConf(zcashConfLocation, "proxy=127.0.0.1:9050"); Settings::addToHushConf(hushConfLocation, "proxy=127.0.0.1:9050");
rpc->getConnection()->config->proxy = "proxy=127.0.0.1:9050"; rpc->getConnection()->config->proxy = "proxy=127.0.0.1:9050";
QMessageBox::information(this, tr("Enable Tor"), QMessageBox::information(this, tr("Enable Tor"),
@ -465,7 +460,7 @@ void MainWindow::setupSettingsModal() {
if (isUsingTor && !settings.chkTor->isChecked()) { if (isUsingTor && !settings.chkTor->isChecked()) {
// If "use tor" was previously checked and now is unchecked // If "use tor" was previously checked and now is unchecked
Settings::removeFromZcashConf(zcashConfLocation, "proxy"); Settings::removeFromHushConf(hushConfLocation, "proxy");
rpc->getConnection()->config->proxy.clear(); rpc->getConnection()->config->proxy.clear();
QMessageBox::information(this, tr("Disable Tor"), QMessageBox::information(this, tr("Disable Tor"),
@ -473,7 +468,7 @@ void MainWindow::setupSettingsModal() {
QMessageBox::Ok); QMessageBox::Ok);
} }
if (zcashConfLocation.isEmpty()) { if (hushConfLocation.isEmpty()) {
// Save settings // Save settings
Settings::getInstance()->saveSettings( Settings::getInstance()->saveSettings(
settings.hostname->text(), settings.hostname->text(),
@ -496,55 +491,55 @@ void MainWindow::setupSettingsModal() {
bool showRestartInfo = false; bool showRestartInfo = false;
bool showReindexInfo = false; bool showReindexInfo = false;
if (settings.chkRescan->isChecked()) { if (settings.chkRescan->isChecked()) {
Settings::addToZcashConf(zcashConfLocation, "rescan=1"); Settings::addToHushConf(hushConfLocation, "rescan=1");
showRestartInfo = true; showRestartInfo = true;
} }
if (settings.chkReindex->isChecked()) { if (settings.chkReindex->isChecked()) {
Settings::addToZcashConf(zcashConfLocation, "reindex=1"); Settings::addToHushConf(hushConfLocation, "reindex=1");
showRestartInfo = true; showRestartInfo = true;
} }
if (!rpc->getConnection()->config->consolidation.isEmpty()==false) { if (!rpc->getConnection()->config->consolidation.isEmpty()==false) {
if (settings.chkConso->isChecked()) { if (settings.chkConso->isChecked()) {
Settings::addToZcashConf(zcashConfLocation, "consolidation=1"); Settings::addToHushConf(hushConfLocation, "consolidation=1");
showRestartInfo = true; showRestartInfo = true;
} }
} }
if (!rpc->getConnection()->config->consolidation.isEmpty()) { if (!rpc->getConnection()->config->consolidation.isEmpty()) {
if (settings.chkConso->isChecked() == false) { if (settings.chkConso->isChecked() == false) {
Settings::removeFromZcashConf(zcashConfLocation, "consolidation"); Settings::removeFromHushConf(hushConfLocation, "consolidation");
showRestartInfo = true; showRestartInfo = true;
} }
} }
if (!rpc->getConnection()->config->deletetx.isEmpty() == false) { if (!rpc->getConnection()->config->deletetx.isEmpty() == false) {
if (settings.chkDeletetx->isChecked()) { if (settings.chkDeletetx->isChecked()) {
Settings::addToZcashConf(zcashConfLocation, "deletetx=1"); Settings::addToHushConf(hushConfLocation, "deletetx=1");
showRestartInfo = true; showRestartInfo = true;
} }
} }
if (!rpc->getConnection()->config->deletetx.isEmpty()) { if (!rpc->getConnection()->config->deletetx.isEmpty()) {
if (settings.chkDeletetx->isChecked() == false) { if (settings.chkDeletetx->isChecked() == false) {
Settings::removeFromZcashConf(zcashConfLocation, "deletetx"); Settings::removeFromHushConf(hushConfLocation, "deletetx");
showRestartInfo = true; showRestartInfo = true;
} }
} }
if (!rpc->getConnection()->config->zindex.isEmpty() == false) { if (!rpc->getConnection()->config->zindex.isEmpty() == false) {
if (settings.chkzindex->isChecked()) { if (settings.chkzindex->isChecked()) {
Settings::addToZcashConf(zcashConfLocation, "zindex=1"); Settings::addToHushConf(hushConfLocation, "zindex=1");
Settings::addToZcashConf(zcashConfLocation, "reindex=1"); Settings::addToHushConf(hushConfLocation, "reindex=1");
showReindexInfo = true; showReindexInfo = true;
} }
} }
if (!rpc->getConnection()->config->zindex.isEmpty()) { if (!rpc->getConnection()->config->zindex.isEmpty()) {
if (settings.chkzindex->isChecked() == false) { if (settings.chkzindex->isChecked() == false) {
Settings::removeFromZcashConf(zcashConfLocation, "zindex"); Settings::removeFromHushConf(hushConfLocation, "zindex");
Settings::addToZcashConf(zcashConfLocation, "reindex=1"); Settings::addToHushConf(hushConfLocation, "reindex=1");
showReindexInfo = true; showReindexInfo = true;
} }
} }
@ -579,18 +574,18 @@ void MainWindow::addressBook() {
AddressBook::open(this); AddressBook::open(this);
} }
void MainWindow::discord() { void MainWindow::telegram() {
QString url = "https://myhush.org/discord/"; QString url = "https://hush.is/tg";
QDesktopServices::openUrl(QUrl(url)); QDesktopServices::openUrl(QUrl(url));
} }
void MainWindow::reportbug() { void MainWindow::reportbug() {
QString url = "https://github.com/MyHush/SilentDragon/issues/new"; QString url = "https://git.hush.is/hush/SilentDragon/issues/new";
QDesktopServices::openUrl(QUrl(url)); QDesktopServices::openUrl(QUrl(url));
} }
void MainWindow::website() { void MainWindow::website() {
QString url = "https://myhush.org"; QString url = "https://hush.is";
QDesktopServices::openUrl(QUrl(url)); QDesktopServices::openUrl(QUrl(url));
} }
@ -608,9 +603,7 @@ void MainWindow::donate() {
ui->tabWidget->setCurrentIndex(1); ui->tabWidget->setCurrentIndex(1);
} }
/** // Validate an address
* Validate an address
*/
void MainWindow::validateAddress() { void MainWindow::validateAddress() {
// Make sure everything is up and running // Make sure everything is up and running
if (!getRPC() || !getRPC()->getConnection()) if (!getRPC() || !getRPC()->getConnection())
@ -699,7 +692,7 @@ void MainWindow::balancesReady() {
// process it. // process it.
if (!pendingURIPayment.isEmpty()) { if (!pendingURIPayment.isEmpty()) {
qDebug() << "Paying hush URI"; qDebug() << "Paying hush URI";
payZcashURI(pendingURIPayment); payHushURI(pendingURIPayment);
pendingURIPayment = ""; pendingURIPayment = "";
} }
@ -710,7 +703,7 @@ bool MainWindow::eventFilter(QObject *object, QEvent *event) {
if (event->type() == QEvent::FileOpen) { if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event); QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event);
if (!fileEvent->url().isEmpty()) if (!fileEvent->url().isEmpty())
payZcashURI(fileEvent->url().toString()); payHushURI(fileEvent->url().toString());
return true; return true;
} }
@ -722,7 +715,7 @@ bool MainWindow::eventFilter(QObject *object, QEvent *event) {
// Pay the Hush URI by showing a confirmation window. If the URI parameter is empty, the UI // Pay the Hush URI by showing a confirmation window. If the URI parameter is empty, the UI
// will prompt for one. If the myAddr is empty, then the default from address is used to send // will prompt for one. If the myAddr is empty, then the default from address is used to send
// the transaction. // the transaction.
void MainWindow::payZcashURI(QString uri, QString myAddr) { void MainWindow::payHushURI(QString uri, QString myAddr) {
// If the Payments UI is not ready (i.e, all balances have not loaded), defer the payment URI // If the Payments UI is not ready (i.e, all balances have not loaded), defer the payment URI
if (!uiPaymentsReady) { if (!uiPaymentsReady) {
qDebug() << "Payment UI not ready, waiting for UI to pay URI"; qDebug() << "Payment UI not ready, waiting for UI to pay URI";
@ -844,15 +837,15 @@ void MainWindow::backupWalletDat() {
if (!rpc->getConnection()) if (!rpc->getConnection())
return; return;
QDir zcashdir(rpc->getConnection()->config->zcashDir); QDir hushdir(rpc->getConnection()->config->hushDir);
QString backupDefaultName = "hush-wallet-backup-" + QDateTime::currentDateTime().toString("yyyyMMdd") + ".dat"; QString backupDefaultName = "hush-wallet-backup-" + QDateTime::currentDateTime().toString("yyyyMMdd") + ".dat";
if (Settings::getInstance()->isTestnet()) { if (Settings::getInstance()->isTestnet()) {
zcashdir.cd("testnet3"); hushdir.cd("testnet3");
backupDefaultName = "testnet-" + backupDefaultName; backupDefaultName = "testnet-" + backupDefaultName;
} }
QFile wallet(zcashdir.filePath("wallet.dat")); QFile wallet(hushdir.filePath("wallet.dat"));
if (!wallet.exists()) { if (!wallet.exists()) {
QMessageBox::critical(this, tr("No wallet.dat"), tr("Couldn't find the wallet.dat on this computer") + "\n" + QMessageBox::critical(this, tr("No wallet.dat"), tr("Couldn't find the wallet.dat on this computer") + "\n" +
tr("You need to back it up from the machine hushd is running on"), QMessageBox::Ok); tr("You need to back it up from the machine hushd is running on"), QMessageBox::Ok);
@ -1068,6 +1061,69 @@ void MainWindow::setupBalancesTab() {
ui->statusBar->showMessage(tr("Copied to clipboard"), 3 * 1000); ui->statusBar->showMessage(tr("Copied to clipboard"), 3 * 1000);
}); });
/* Example reply from z_shieldcoinbase and z_mergetoaddress
{
"remainingUTXOs": 0,
"remainingValue": 0.00000000,
"shieldingUTXOs": 6,
"shieldingValue": 16.87530000,
"opid": "opid-0245ddfa-5f60-4e00-8ace-e782d814132b"
}
*/
if(addr.startsWith("zs1")) {
menu.addAction(tr("Shield all non-mining taddr funds to this zaddr"), [=] () {
QJsonArray params = QJsonArray { "ANY_TADDR" , addr };
qDebug() << "Calling mergeToAddress with params=" << params;
rpc->mergeToAddress(params, [=](const QJsonValue& reply) {
qDebug() << "mergeToAddress reply=" << reply;
QString shieldingValue = reply.toObject()["shieldingValue"].toString();
QString opid = reply.toObject()["opid"].toString();
auto remainingUTXOs = reply.toObject()["remainingUTXOs"].toInt();
if(remainingUTXOs > 0) {
//TODO: more utxos to shield
}
ui->statusBar->showMessage(tr("Shielded") + shieldingValue + " HUSH in transparent funds to " + addr + " in opid " + opid, 3 * 1000);
}, [=](QString errStr) {
qDebug() << "z_mergetoaddress pooped:" << errStr;
if(errStr == "Could not find any funds to merge.") {
ui->statusBar->showMessage("No funds found to shield!");
}
});
});
}
if(addr.startsWith("zs1")) {
menu.addAction(tr("Shield all mining funds to this zaddr"), [=] () {
//QJsonArray params = QJsonArray {addr, zaddresses->first() };
// We shield all coinbase funds to the selected zaddr
QJsonArray params = QJsonArray {"*", addr };
qDebug() << "Calling shieldCoinbase with params=" << params;
rpc->shieldCoinbase(params, [=](const QJsonValue& reply) {
QString shieldingValue = reply.toObject()["shieldingValue"].toString();
QString opid = reply.toObject()["opid"].toString();
auto remainingUTXOs = reply.toObject()["remainingUTXOs"].toInt();
qDebug() << "ShieldCoinbase reply=" << reply;
// By default we shield 50 blocks at a time
if(remainingUTXOs > 0) {
//TODO: more utxos to shield
}
ui->statusBar->showMessage(tr("Shielded") + shieldingValue + " HUSH in Mining funds to " + addr + " in opid " + opid, 3 * 1000);
}, [=](QString errStr) {
//error("", errStr);
qDebug() << "z_shieldcoinbase pooped:" << errStr;
if(errStr == "Could not find any coinbase funds to shield.") {
ui->statusBar->showMessage("No mining funds found to shield!");
}
});
});
}
menu.addAction(tr("Get private key"), [=] () { menu.addAction(tr("Get private key"), [=] () {
this->exportKeys(addr); this->exportKeys(addr);
}); });
@ -1122,6 +1178,7 @@ void MainWindow::setupBalancesTab() {
QDesktopServices::openUrl(QUrl(url)); QDesktopServices::openUrl(QUrl(url));
}); });
//TODO: should this be kept?
menu.addAction(tr("Convert Address"), [=] () { menu.addAction(tr("Convert Address"), [=] () {
QString url; QString url;
url = "https://dexstats.info/addressconverter.php?fromcoin=HUSH3&address=" + addr; url = "https://dexstats.info/addressconverter.php?fromcoin=HUSH3&address=" + addr;
@ -1133,8 +1190,148 @@ void MainWindow::setupBalancesTab() {
}); });
} }
QString peer2ip(QString peer) {
QString ip = "";
if(peer.contains("[")) {
// this is actually ipv6, grab it all except the port
auto parts = peer.split(":");
parts[8]=""; // remove port
peer = parts.join(":");
peer.chop(1); // remove trailing :
} else {
ip = peer.split(":")[0];
}
return ip;
}
void MainWindow::setupPeersTab() {
qDebug() << __FUNCTION__;
// Set up context menu on transactions tab
ui->peersTable->setContextMenuPolicy(Qt::CustomContextMenu);
ui->bannedPeersTable->setContextMenuPolicy(Qt::CustomContextMenu);
// Table right click
QObject::connect(ui->bannedPeersTable, &QTableView::customContextMenuRequested, [=] (QPoint pos) {
QModelIndex index = ui->peersTable->indexAt(pos);
if (index.row() < 0) return;
QMenu menu(this);
auto bannedPeerModel = dynamic_cast<BannedPeersTableModel *>(ui->bannedPeersTable->model());
QString addr = bannedPeerModel->getAddress(index.row());
QString ip = peer2ip(addr);
QString subnet = bannedPeerModel->getSubnet(index.row());
//qint64 banned_until = bannedPeerModel->getBannedUntil(index.row());
if(!ip.isEmpty()) {
menu.addAction(tr("Copy banned peer IP"), [=] () {
QGuiApplication::clipboard()->setText(ip);
ui->statusBar->showMessage(tr("Copied to clipboard"), 3 * 1000);
});
}
// shodan only supports ipv4 addresses *and* we get ipv6 addresses
// in a different format, yay
if(!ip.isEmpty() && !ip.contains(":")) {
menu.addAction(tr("View banned host IP on shodan.io (3rd party service)"), [=] () {
QString url = "https://www.shodan.io/host/" + ip;
qDebug() << "opening " << url;
QDesktopServices::openUrl(QUrl(url));
});
}
menu.exec(ui->bannedPeersTable->viewport()->mapToGlobal(pos));
});
// Table right click
QObject::connect(ui->peersTable, &QTableView::customContextMenuRequested, [=] (QPoint pos) {
QModelIndex index = ui->peersTable->indexAt(pos);
if (index.row() < 0) return;
QMenu menu(this);
auto peerModel = dynamic_cast<PeersTableModel *>(ui->peersTable->model());
QString addr = peerModel->getAddress(index.row());
QString cipher = peerModel->getTLSCipher(index.row());
qint64 asn = peerModel->getASN(index.row());
QString ip = peer2ip(addr);
QString as = QString::number(asn);
menu.addAction(tr("Copy peer address+port"), [=] () {
QGuiApplication::clipboard()->setText(addr);
ui->statusBar->showMessage(tr("Copied to clipboard"), 3 * 1000);
});
//TODO: support Tor correctly when v3 lands
menu.addAction(tr("Copy peer address"), [=] () {
QGuiApplication::clipboard()->setText(ip);
ui->statusBar->showMessage(tr("Copied to clipboard"), 3 * 1000);
});
menu.addAction(tr("Copy TLS ciphersuite"), [=] () {
QGuiApplication::clipboard()->setText(cipher);
ui->statusBar->showMessage(tr("Copied to clipboard"), 3 * 1000);
});
menu.addAction(tr("Copy ASN"), [=] () {
QGuiApplication::clipboard()->setText(as);
ui->statusBar->showMessage(tr("Copied to clipboard"), 3 * 1000);
});
// shodan only supports ipv4 addresses
if(!ip.isEmpty() && !ip.contains("[")) {
menu.addAction(tr("View host on shodan.io (3rd party service)"), [=] () {
QString url = "https://www.shodan.io/host/" + ip;
qDebug() << "opening " << url;
QDesktopServices::openUrl(QUrl(url));
});
}
if(!as.isEmpty()) {
menu.addAction(tr("View ASN on bgpview.io (3rd party service)"), [=] () {
QString url = "https://bgpview.io/asn/" + as;
qDebug() << "opening " << url;
QDesktopServices::openUrl(QUrl(url));
});
}
menu.exec(ui->peersTable->viewport()->mapToGlobal(pos));
});
/*
//grep 'BAN THRESHOLD EXCEEDED' ~/.komodo/HUSH3/debug.log
//grep Disconnected ...
QFile debuglog = "";
#ifdef Q_OS_LINUX
debuglog = "~/.komodo/HUSH3/debug.log";
#elif defined(Q_OS_DARWIN)
debuglog = "~/Library/Application Support/Komodo/HUSH3/debug.log";
#elif defined(Q_OS_WIN64)
// "C:/Users/<USER>/AppData/Roaming/<APPNAME>",
// TODO: get current username
debuglog = "C:/Users/<USER>/AppData/Roaming/Komodo/HUSH3/debug.log";
#else
// Bless Your Heart, You Like Danger!
// There are open bounties to port HUSH softtware to OpenBSD and friends:
// git.hush.is/hush/tasks
debuglog = "~/.komodo/HUSH3/debug.log";
#endif // Q_OS_LINUX
if(debuglog.exists()) {
qDebug() << __func__ << ": Found debuglog at " << debuglog;
} else {
qDebug() << __func__ << ": No debug.log found";
}
*/
//ui->recentlyBannedPeers = "Could not open " + debuglog;
}
void MainWindow::setupHushTab() { void MainWindow::setupHushTab() {
ui->hushlogo->setBasePixmap(QPixmap(":/img/res/zcashdlogo.gif")); QPixmap image(":/img/res/tropical-hush-square.png");
ui->hushlogo->setBasePixmap( image ); // image.scaled(600,600, Qt::KeepAspectRatioByExpanding, Qt::FastTransformation ) );
} }
/* /*
void MainWindow::setupChatTab() { void MainWindow::setupChatTab() {

12
src/mainwindow.h

@ -1,8 +1,11 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
#include "precompiled.h" #include "precompiled.h"
#include "logger.h" #include "logger.h"
#include <memory>
// Forward declare to break circular dependency. // Forward declare to break circular dependency.
class RPC; class RPC;
@ -52,7 +55,7 @@ public:
void stopWebsocket(); void stopWebsocket();
void balancesReady(); void balancesReady();
void payZcashURI(QString uri = "", QString myAddr = ""); void payHushURI(QString uri = "", QString myAddr = "");
void validateAddress(); void validateAddress();
@ -65,7 +68,6 @@ public:
QLabel* statusLabel; QLabel* statusLabel;
QLabel* statusIcon; QLabel* statusIcon;
QLabel* loadingLabel; QLabel* loadingLabel;
QWidget* zcashdtab;
Logger* logger; Logger* logger;
@ -75,6 +77,7 @@ private:
void closeEvent(QCloseEvent* event); void closeEvent(QCloseEvent* event);
void setupSendTab(); void setupSendTab();
void setupPeersTab();
void setupTransactionsTab(); void setupTransactionsTab();
void setupReceiveTab(); void setupReceiveTab();
void setupBalancesTab(); void setupBalancesTab();
@ -93,9 +96,6 @@ private:
Tx createTxFromSendPage(); Tx createTxFromSendPage();
bool confirmTx(Tx tx); bool confirmTx(Tx tx);
void turnstileDoMigration(QString fromAddr = "");
void turnstileProgress();
void cancelButton(); void cancelButton();
void sendButton(); void sendButton();
void inputComboTextChanged(int index); void inputComboTextChanged(int index);
@ -116,7 +116,7 @@ private:
void donate(); void donate();
void website(); void website();
void discord(); void telegram();
void reportbug(); void reportbug();
void addressBook(); void addressBook();
void postToZBoard(); void postToZBoard();

92
src/mainwindow.ui

@ -915,6 +915,7 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab_4"> <widget class="QWidget" name="tab_4">
<attribute name="title"> <attribute name="title">
<string>Transactions</string> <string>Transactions</string>
@ -932,6 +933,73 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="peer_tab">
<attribute name="title">
<string>Peers</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QLabel" name="currentPeersLabel">
<property name="text">
<string>
Current Peers
</string>
</property>
</widget>
</item>
<item>
<widget class="QTableView" name="peersTable">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="bannedPeersLabel">
<property name="text">
<string>
Banned Peers
</string>
</property>
</widget>
</item>
<item>
<widget class="QTableView" name="bannedPeersTable">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
<!--
<widget class="QLabel" name="recentlyDisconnectedPeers">
<property name="text">
<string>
Looking For Recently Disconnected Peers ...
</string>
</property>
</widget>
</item>
-->
</layout>
</widget>
<widget class="QWidget" name="tab_6"> <widget class="QWidget" name="tab_6">
<attribute name="title"> <attribute name="title">
<string>Market</string> <string>Market</string>
@ -1078,7 +1146,7 @@
<property name="title"> <property name="title">
<string/> <string/>
</property> </property>
<layout class="QGridLayout" name="gridLayout_5"> <layout class="QGridLayout" name="gridLayout_51">
<item row="5" column="0" colspan="3"> <item row="5" column="0" colspan="3">
<widget class="QLabel" name="label_14"> <widget class="QLabel" name="label_14">
<property name="text"> <property name="text">
@ -1176,6 +1244,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<!--
<item row="10" column="0"> <item row="10" column="0">
<widget class="QLabel" name="kmdversionlabel"> <widget class="QLabel" name="kmdversionlabel">
<property name="text"> <property name="text">
@ -1183,6 +1252,7 @@
</property> </property>
</widget> </widget>
</item> </item>
-->
<item row="10" column="2"> <item row="10" column="2">
<widget class="QLabel" name="kmdversion"> <widget class="QLabel" name="kmdversion">
<property name="text"> <property name="text">
@ -1540,7 +1610,7 @@
<string>&amp;Help</string> <string>&amp;Help</string>
</property> </property>
<addaction name="actionDonate"/> <addaction name="actionDonate"/>
<addaction name="actionDiscord"/> <addaction name="actionTelegram"/>
<addaction name="actionWebsite"/> <addaction name="actionWebsite"/>
<addaction name="actionCheck_for_Updates"/> <addaction name="actionCheck_for_Updates"/>
<addaction name="actionReportBug"/> <addaction name="actionReportBug"/>
@ -1563,8 +1633,8 @@
</widget> </widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
<addaction name="menu_Edit"/> <addaction name="menu_Edit"/>
<addaction name="menuHelp"/>
<addaction name="menuApps"/> <addaction name="menuApps"/>
<addaction name="menuHelp"/>
</widget> </widget>
<widget class="QStatusBar" name="statusBar"/> <widget class="QStatusBar" name="statusBar"/>
<action name="actionExit"> <action name="actionExit">
@ -1579,7 +1649,7 @@
</action> </action>
<action name="actionReportBug"> <action name="actionReportBug">
<property name="text"> <property name="text">
<string>&amp;Report a bug on Github</string> <string>&amp;Report a bug</string>
</property> </property>
</action> </action>
<action name="actionSettings"> <action name="actionSettings">
@ -1595,9 +1665,9 @@
<string>&amp;Send Duke Feedback</string> <string>&amp;Send Duke Feedback</string>
</property> </property>
</action> </action>
<action name="actionDiscord"> <action name="actionTelegram">
<property name="text"> <property name="text">
<string>&amp;Hush Discord</string> <string>&amp;Hush Telegram</string>
</property> </property>
</action> </action>
<action name="actionWebsite"> <action name="actionWebsite">
@ -1607,15 +1677,7 @@
</action> </action>
<action name="actionCheck_for_Updates"> <action name="actionCheck_for_Updates">
<property name="text"> <property name="text">
<string>Check github.com for &amp;updates</string> <string>Check git.hush.is for &amp;updates</string>
</property>
</action>
<action name="actionTurnstile_Migration">
<property name="text">
<string>Sapling &amp;turnstile</string>
</property>
<property name="shortcut">
<string>Ctrl+A, Ctrl+T</string>
</property> </property>
</action> </action>
<action name="actionImport_Private_Key"> <action name="actionImport_Private_Key">

4
src/memoedit.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "memoedit.h" #include "memoedit.h"
MemoEdit::MemoEdit(QWidget* parent) : QPlainTextEdit(parent) { MemoEdit::MemoEdit(QWidget* parent) : QPlainTextEdit(parent) {
@ -49,4 +51,4 @@ void MemoEdit::includeReplyTo(QString addr) {
return; return;
this->setPlainText(curText + "\n" + tr("Reply to") + ":\n" + addr); this->setPlainText(curText + "\n" + tr("Reply to") + ":\n" + addr);
} }

4
src/memoedit.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef MEMOEDIT_H #ifndef MEMOEDIT_H
#define MEMOEDIT_H #define MEMOEDIT_H
@ -20,4 +22,4 @@ private:
QPushButton* acceptButton = nullptr; QPushButton* acceptButton = nullptr;
}; };
#endif // MEMOEDIT_H #endif // MEMOEDIT_H

2
src/mobileappconnector.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "mobileappconnector.h" #include "mobileappconnector.h"
#include "ui_mobileappconnector.h" #include "ui_mobileappconnector.h"

2
src/mobileappconnector.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef MOBILEAPPCONNECTOR_H #ifndef MOBILEAPPCONNECTOR_H
#define MOBILEAPPCONNECTOR_H #define MOBILEAPPCONNECTOR_H

178
src/peerstablemodel.cpp

@ -0,0 +1,178 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "txtablemodel.h"
#include "settings.h"
#include "rpc.h"
PeersTableModel::PeersTableModel(QObject *parent)
: QAbstractTableModel(parent) {
headers << QObject::tr("PeerID") << QObject::tr("Address") << QObject::tr("ASN") << QObject::tr("TLS Cipher") << QObject::tr("TLS Verfied") << QObject::tr("Version") << QObject::tr("Protocol Version") << QObject::tr("Ping Time") << QObject::tr("Banscore") << QObject::tr("Bytes received") << QObject::tr("Bytes sent");
}
PeersTableModel::~PeersTableModel() {
delete modeldata;
}
void PeersTableModel::addData(const QList<PeerItem>& data) {
peers = new QList<PeerItem>();
std::copy(data.begin(), data.end(), std::back_inserter(*peers));
updateAllData();
}
void PeersTableModel::updateAllData() {
auto newmodeldata = new QList<PeerItem>();
// Copy peer data so GUI can use it
if (peers != nullptr) std::copy( peers->begin(), peers->end(), std::back_inserter(*newmodeldata));
// Sort by connection time
std::sort(newmodeldata->begin(), newmodeldata->end(), [=] (auto a, auto b) {
return a.conntime > b.conntime; // reverse sort
});
// And then swap out the modeldata with the new one.
delete modeldata;
modeldata = newmodeldata;
// do magic
dataChanged(index(0, 0), index(modeldata->size()-1, columnCount(index(0,0))-1));
layoutChanged();
}
int PeersTableModel::rowCount(const QModelIndex&) const
{
if (modeldata == nullptr) return 0;
return modeldata->size();
}
int PeersTableModel::columnCount(const QModelIndex&) const
{
return headers.size();
}
QVariant PeersTableModel::data(const QModelIndex &index, int role) const
{
// Align column 4 (amount) right
//if (role == Qt::TextAlignmentRole && index.column() == 3) return QVariant(Qt::AlignRight | Qt::AlignVCenter);
if (role == Qt::ForegroundRole) {
// peers with banscore >=50 will likely be banned soon, color them red
if (modeldata->at(index.row()).banscore >= 50) {
QBrush b;
b.setColor(Qt::red);
return b;
}
// Else, just return the default brush
QBrush b;
b.setColor(Qt::black);
return b;
}
auto dat = modeldata->at(index.row());
if (role == Qt::DisplayRole) {
switch (index.column()) {
case 0: return dat.peerid;
case 1: return dat.address;
case 2: return "AS" + QString::number(dat.asn);
case 3: return dat.tls_cipher;
case 4: return dat.tls_verified;
case 5: return dat.subver;
case 6: return dat.protocolversion;
case 7: return dat.pingtime;
case 8: return dat.banscore;
case 9: return dat.bytes_received;
case 10: return dat.bytes_sent;
}
}
if (role == Qt::ToolTipRole) {
switch (index.column()) {
case 0: return "Unique Peer ID";
case 1: return "Network Address";
case 2: return "Autonomous System Number";
case 3: return "TLS Ciphersuite";
case 4: return "TLS Certificate verified";
case 5: return "Full Node Version";
case 6: return "P2P Protocol Version";
case 7: return "Ping Time (seconds)";
case 8: return "Banscore";
case 9: return "Bytes received";
case 10: return "Bytes sent";
}
}
//TODO: show different icons for IP vs Tor vs other kinds of connections
/*
if (role == Qt::DecorationRole && index.column() == 0) {
if (!dat.memo.isEmpty()) {
// If the memo is a Payment URI, then show a payment request icon
if (dat.memo.startsWith("hush:")) {
QIcon icon(":/icons/res/paymentreq.gif");
return QVariant(icon.pixmap(16, 16));
} else {
// Return the info pixmap to indicate memo
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
return QVariant(icon.pixmap(16, 16));
}
} else {
// Empty pixmap to make it align
QPixmap p(16, 16);
p.fill(Qt::white);
return QVariant(p);
}
}
*/
return QVariant();
}
QVariant PeersTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
//if (role == Qt::TextAlignmentRole && section == 3) return QVariant(Qt::AlignRight | Qt::AlignVCenter);
if (role == Qt::TextAlignmentRole) return QVariant(Qt::AlignCenter | Qt::AlignVCenter);
if (role == Qt::FontRole) {
QFont f;
f.setBold(true);
return f;
}
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
return headers.at(section);
}
return QVariant();
}
QString PeersTableModel::getPeerId(int row) const {
return QString::number(modeldata->at(row).peerid);
}
QString PeersTableModel::getAddress(int row) const {
return modeldata->at(row).address.trimmed();
}
QString PeersTableModel::getTLSCipher(int row) const {
return modeldata->at(row).tls_cipher;
}
qint64 PeersTableModel::getASN(int row) const {
return modeldata->at(row).asn;
}
qint64 PeersTableModel::getConntime(int row) const {
return modeldata->at(row).conntime;
}
QString PeersTableModel::getType(int row) const {
return modeldata->at(row).type;
}
QString PeersTableModel::getPingtime(int row) const {
return Settings::getDecimalString(modeldata->at(row).pingtime);
}

44
src/peerstablemodel.h

@ -0,0 +1,44 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef PEERSTABLEMODEL_H
#define PEERSTABLEMODEL_H
#include "precompiled.h"
struct PeerItem;
class PeersTableModel: public QAbstractTableModel
{
public:
PeersTableModel(QObject* parent);
~PeersTableModel();
QString getPeerId(int row) const;
QString getAddress(int row) const;
QString getType(int row) const;
qint64 getConntime(int row) const;
qint64 getASN(int row) const;
QString getSubver(int row) const;
QString getTLSCipher(int row) const;
bool getTLSVerified(int row) const;
QString getPingtime(int row) const;
unsigned int getBanscore(int row) const;
unsigned int getProtocolVersion(int row) const;
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
void addData (const QList<PeerItem>& data);
private:
void updateAllData();
QList<PeerItem>* peers = nullptr;
QList<PeerItem>* modeldata = nullptr;
QList<QString> headers;
};
#endif // PEERSTABLEMODEL_H

2
src/precompiled.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#if defined __cplusplus #if defined __cplusplus
/* Add C++ includes here */ /* Add C++ includes here */

4
src/qrcodelabel.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "qrcodelabel.h" #include "qrcodelabel.h"
QRCodeLabel::QRCodeLabel(QWidget *parent) : QRCodeLabel::QRCodeLabel(QWidget *parent) :
@ -54,4 +56,4 @@ QPixmap QRCodeLabel::scaledPixmap() const {
void QRCodeLabel::setQrcodeString(QString stra) { void QRCodeLabel::setQrcodeString(QString stra) {
str = stra; str = stra;
QLabel::setPixmap(scaledPixmap()); QLabel::setPixmap(scaledPixmap());
} }

2
src/qrcodelabel.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef QRCODELABEL_H #ifndef QRCODELABEL_H
#define QRCODELABEL_H #define QRCODELABEL_H

4
src/recurring.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "recurring.h" #include "recurring.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -45,4 +47,4 @@ void Recurring::showEditDialog(QWidget* parent, MainWindow* main, Tx tx) {
ui.txtDesc->setFocus(); ui.txtDesc->setFocus();
d.exec(); d.exec();
} }

4
src/recurring.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef RECURRING_H #ifndef RECURRING_H
#define RECURRING_H #define RECURRING_H
@ -33,4 +35,4 @@ public:
static void showEditDialog(QWidget* parent, MainWindow* main, Tx tx); static void showEditDialog(QWidget* parent, MainWindow* main, Tx tx);
}; };
#endif // RECURRING_H #endif // RECURRING_H

6
src/requestdialog.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "requestdialog.h" #include "requestdialog.h"
#include "ui_requestdialog.h" #include "ui_requestdialog.h"
#include "settings.h" #include "settings.h"
@ -80,7 +82,7 @@ void RequestDialog::showPaymentConfirmation(MainWindow* main, QString paymentURI
req.lblHeader->setText(tr("You are paying a payment request. Your address will not be visible to the person requesting this payment.")); req.lblHeader->setText(tr("You are paying a payment request. Your address will not be visible to the person requesting this payment."));
if (d.exec() == QDialog::Accepted) { if (d.exec() == QDialog::Accepted) {
main->payZcashURI(paymentURI, req.cmbMyAddress->currentText()); main->payHushURI(paymentURI, req.cmbMyAddress->currentText());
} }
} }
@ -134,6 +136,6 @@ void RequestDialog::showRequestZcash(MainWindow* main) {
// If the disclosed address in the memo doesn't have a balance, it will automatically fallback to the default // If the disclosed address in the memo doesn't have a balance, it will automatically fallback to the default
// sapling address // sapling address
main->payZcashURI(sendURI, req.cmbMyAddress->currentText()); main->payHushURI(sendURI, req.cmbMyAddress->currentText());
} }
} }

2
src/requestdialog.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef REQUESTDIALOG_H #ifndef REQUESTDIALOG_H
#define REQUESTDIALOG_H #define REQUESTDIALOG_H

192
src/rpc.cpp

@ -1,14 +1,12 @@
// Copyright 2019-2020 The Hush Developers // Copyright 2019-2021 The Hush Developers
// Released under the GPLv3 // Released under the GPLv3
#include "rpc.h" #include "rpc.h"
#include "addressbook.h" #include "addressbook.h"
#include "settings.h" #include "settings.h"
#include "senttxstore.h" #include "senttxstore.h"
#include "version.h" #include "version.h"
#include "websockets.h" #include "websockets.h"
RPC::RPC(MainWindow* main) { RPC::RPC(MainWindow* main) {
auto cl = new ConnectionLoader(main, this); auto cl = new ConnectionLoader(main, this);
@ -16,7 +14,7 @@ RPC::RPC(MainWindow* main) {
QTimer::singleShot(1, [=]() { cl->loadConnection(); }); QTimer::singleShot(1, [=]() { cl->loadConnection(); });
this->main = main; this->main = main;
this->ui = main->ui; this->ui = main->ui;
// Setup balances table model // Setup balances table model
balancesTableModel = new BalancesTableModel(main->ui->balancesTable); balancesTableModel = new BalancesTableModel(main->ui->balancesTable);
@ -27,12 +25,24 @@ RPC::RPC(MainWindow* main) {
main->ui->transactionsTable->setModel(transactionsTableModel); main->ui->transactionsTable->setModel(transactionsTableModel);
main->ui->transactionsTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch); main->ui->transactionsTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);
peersTableModel = new PeersTableModel(ui->peersTable);
main->ui->peersTable->setModel(peersTableModel);
// tls ciphersuite is wide
main->ui->peersTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
bannedPeersTableModel = new BannedPeersTableModel(ui->bannedPeersTable);
main->ui->bannedPeersTable->setModel(bannedPeersTableModel);
main->ui->bannedPeersTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch);
qDebug() << __func__ << "Done settings up TableModels";
// Set up timer to refresh Price // Set up timer to refresh Price
priceTimer = new QTimer(main); priceTimer = new QTimer(main);
QObject::connect(priceTimer, &QTimer::timeout, [=]() { QObject::connect(priceTimer, &QTimer::timeout, [=]() {
refreshPrice(); refreshPrice();
}); });
priceTimer->start(Settings::priceRefreshSpeed); // Every hour priceTimer->start(Settings::priceRefreshSpeed);
qDebug() << __func__ << ": started price refresh at speed=" << Settings::priceRefreshSpeed;
// Set up a timer to refresh the UI every few seconds // Set up a timer to refresh the UI every few seconds
timer = new QTimer(main); timer = new QTimer(main);
@ -48,8 +58,9 @@ RPC::RPC(MainWindow* main) {
//qDebug() << "Watching tx status"; //qDebug() << "Watching tx status";
watchTxStatus(); watchTxStatus();
}); });
// Start at every 10s. When an operation is pending, this will change to every second
txTimer->start(Settings::updateSpeed); txTimer->start(Settings::updateSpeed);
qDebug() << __func__ << "Done settings up all timers";
usedAddresses = new QMap<QString, bool>(); usedAddresses = new QMap<QString, bool>();
} }
@ -60,6 +71,8 @@ RPC::~RPC() {
delete transactionsTableModel; delete transactionsTableModel;
delete balancesTableModel; delete balancesTableModel;
delete peersTableModel;
delete bannedPeersTableModel;
delete utxos; delete utxos;
delete allBalances; delete allBalances;
@ -70,12 +83,8 @@ RPC::~RPC() {
delete conn; delete conn;
} }
void RPC::setEZcashd(std::shared_ptr<QProcess> p) { void RPC::setEHushd(std::shared_ptr<QProcess> p) {
ezcashd = p; ehushd = p;
if (ezcashd && ui->tabWidget->widget(4) == nullptr) {
ui->tabWidget->addTab(main->zcashdtab, "zcashd");
}
} }
// Called when a connection to hushd is available. // Called when a connection to hushd is available.
@ -87,14 +96,14 @@ void RPC::setConnection(Connection* c) {
ui->statusBar->showMessage("Ready! Thank you for helping secure the Hush network by running a full node."); ui->statusBar->showMessage("Ready! Thank you for helping secure the Hush network by running a full node.");
// See if we need to remove the reindex/rescan flags from the zcash.conf file // See if we need to remove the reindex/rescan flags from the conf file
auto zcashConfLocation = Settings::getInstance()->getZcashdConfLocation(); auto hushConfLocation = Settings::getInstance()->getHushdConfLocation();
Settings::removeFromZcashConf(zcashConfLocation, "rescan"); Settings::removeFromHushConf(hushConfLocation, "rescan");
Settings::removeFromZcashConf(zcashConfLocation, "reindex"); Settings::removeFromHushConf(hushConfLocation, "reindex");
// Refresh the UI // Refresh the UI
refreshPrice(); refreshPrice();
checkForUpdate(); //checkForUpdate();
// Force update, because this might be coming from a settings update // Force update, because this might be coming from a settings update
// where we need to immediately refresh // where we need to immediately refresh
@ -241,11 +250,57 @@ void RPC::getBalance(const std::function<void(QJsonValue)>& cb) {
conn->doRPCWithDefaultErrorHandling(payload, cb); conn->doRPCWithDefaultErrorHandling(payload, cb);
} }
void RPC::getPeerInfo(const std::function<void(QJsonValue)>& cb) {
QString method = "getpeerinfo";
conn->doRPCWithDefaultErrorHandling(makePayload(method), cb);
}
void RPC::listBanned(const std::function<void(QJsonValue)>& cb) {
QString method = "listbanned";
conn->doRPCWithDefaultErrorHandling(makePayload(method), cb);
}
void RPC::getTransactions(const std::function<void(QJsonValue)>& cb) { void RPC::getTransactions(const std::function<void(QJsonValue)>& cb) {
QString method = "listtransactions"; QString method = "listtransactions";
conn->doRPCWithDefaultErrorHandling(makePayload(method), cb); conn->doRPCWithDefaultErrorHandling(makePayload(method), cb);
} }
void RPC::mergeToAddress(QJsonArray &params, const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& err) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "42"},
{"method", "z_mergetoaddress"},
{"params", params}
};
conn->doRPC(payload, cb, [=] (QNetworkReply *reply, const QJsonValue &parsed) {
if (!parsed.isUndefined() && !parsed["error"].toObject()["message"].isNull()) {
err(parsed["error"].toObject()["message"].toString());
} else {
err(reply->errorString());
}
});
}
void RPC::shieldCoinbase(QJsonArray &params, const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& err) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "42"},
{"method", "z_shieldcoinbase"},
{"params", params}
};
conn->doRPC(payload, cb, [=] (QNetworkReply *reply, const QJsonValue &parsed) {
if (!parsed.isUndefined() && !parsed["error"].toObject()["message"].isNull()) {
err(parsed["error"].toObject()["message"].toString());
} else {
err(reply->errorString());
}
});
}
void RPC::sendZTransaction(QJsonValue params, const std::function<void(QJsonValue)>& cb, void RPC::sendZTransaction(QJsonValue params, const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& err) { const std::function<void(QString)>& err) {
QJsonObject payload = { QJsonObject payload = {
@ -572,21 +627,21 @@ void RPC::getInfoThenRefresh(bool force) {
int notarized = reply["notarized"].toInt(); int notarized = reply["notarized"].toInt();
int protocolversion = reply["protocolversion"].toInt(); int protocolversion = reply["protocolversion"].toInt();
int lag = curBlock - notarized; int lag = curBlock - notarized;
int blocks_until_halving= 340000 - curBlock; // TODO: store all future halvings
int blocks_until_halving= 2020000 - curBlock;
char halving_days[8]; char halving_days[8];
sprintf(halving_days, "%.2f", (double) (blocks_until_halving * 150) / (60*60*24) ); int blocktime = 75; // seconds
sprintf(halving_days, "%.2f", (double) (blocks_until_halving * blocktime) / (60*60*24) );
QString ntzhash = reply["notarizedhash"].toString(); QString ntzhash = reply["notarizedhash"].toString();
QString ntztxid = reply["notarizedtxid"].toString(); QString ntztxid = reply["notarizedtxid"].toString();
QString kmdver = reply["KMDversion"].toString();
Settings::getInstance()->setZcashdVersion(version); Settings::getInstance()->setHushdVersion(version);
ui->longestchain->setText(QString::number(longestchain)); ui->longestchain->setText(QString::number(longestchain));
ui->notarizedhashvalue->setText( ntzhash ); ui->notarizedhashvalue->setText( ntzhash );
ui->notarizedtxidvalue->setText( ntztxid ); ui->notarizedtxidvalue->setText( ntztxid );
ui->lagvalue->setText( QString::number(lag) ); ui->lagvalue->setText( QString::number(lag) );
ui->version->setText( QString::number(version) ); ui->version->setText( QString::number(version) );
ui->kmdversion->setText( kmdver );
ui->protocolversion->setText( QString::number(protocolversion) ); ui->protocolversion->setText( QString::number(protocolversion) );
ui->p2pport->setText( QString::number(p2pport) ); ui->p2pport->setText( QString::number(p2pport) );
ui->rpcport->setText( QString::number(rpcport) ); ui->rpcport->setText( QString::number(rpcport) );
@ -597,6 +652,7 @@ void RPC::getInfoThenRefresh(bool force) {
lastBlock = curBlock; lastBlock = curBlock;
refreshBalances(); refreshBalances();
refreshPeers();
refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans() refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans()
refreshTransactions(); refreshTransactions();
} }
@ -621,7 +677,8 @@ void RPC::getInfoThenRefresh(bool force) {
conn->doRPCIgnoreError(makePayload(method), [=](const QJsonValue& reply) { conn->doRPCIgnoreError(makePayload(method), [=](const QJsonValue& reply) {
qint64 solrate = reply.toInt(); qint64 solrate = reply.toInt();
ui->solrate->setText(QString::number(solrate) % " Sol/s"); //TODO: format decimal
ui->solrate->setText(QString::number((double)solrate / 1000000) % " MegaSol/s");
}); });
// Get network info // Get network info
@ -707,7 +764,7 @@ void RPC::getInfoThenRefresh(bool force) {
else { else {
tooltip = QObject::tr("hushd has no peer connections! Network issues?"); tooltip = QObject::tr("hushd has no peer connections! Network issues?");
} }
tooltip = tooltip % "(v" % QString::number(Settings::getInstance()->getZcashdVersion()) % ")"; tooltip = tooltip % "(v" % QString::number(Settings::getInstance()->getHushdVersion()) % ")";
if (!hushPrice.isEmpty()) { if (!hushPrice.isEmpty()) {
tooltip = "1 HUSH = " % hushPrice % "\n" % tooltip; tooltip = "1 HUSH = " % hushPrice % "\n" % tooltip;
@ -849,6 +906,76 @@ void RPC::refreshBalances() {
}); });
} }
void RPC::refreshPeers() {
qDebug() << __func__;
if (conn == nullptr)
return noConnection();
/*
[
{
"address": "199.247.28.148/255.255.255.255",
"banned_until": 1612869516
},
{
"address": "2001:19f0:5001:d26:5400:3ff:fe18:f6c2/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
"banned_until": 1612870431
}
]
*/
listBanned([=] (QJsonValue reply) {
QList<BannedPeerItem> peerdata;
for (const auto& it : reply.toArray()) {
auto addr = it.toObject()["address"].toString();
auto bantime = (qint64)it.toObject()["banned_until"].toInt();
auto parts = addr.split("/");
auto ip = parts[0];
auto subnet = parts[1];
BannedPeerItem peer { ip, subnet, bantime };
qDebug() << "Adding banned peer with address=" << addr;
peerdata.push_back(peer);
}
bannedPeersTableModel->addData(peerdata);
});
getPeerInfo([=] (QJsonValue reply) {
QList<PeerItem> peerdata;
for (const auto& it : reply.toArray()) {
auto addr = it.toObject()["addr"].toString();
auto asn = (qint64)it.toObject()["mapped_as"].toInt();
auto recv = (qint64)it.toObject()["bytesrecv"].toInt();
auto sent = (qint64)it.toObject()["bytessent"].toInt();
PeerItem peer {
it.toObject()["id"].toInt(), // peerid
"", // type
(qint64)it.toObject()["conntime"].toInt(),
addr,
asn,
it.toObject()["tls_cipher"].toString(),
// don't convert the JS string "false" to a bool, which is true, lulz
it.toObject()["tls_verified"].toString() == 'true' ? true : false,
(qint64)(it.toObject()["banscore"].toInt()),
(qint64)(it.toObject()["version"].toInt()), // protocolversion
it.toObject()["subver"].toString(),
recv,
sent,
it.toObject()["pingtime"].toDouble(),
};
qDebug() << "Adding peer with address=" << addr << " and AS=" << asn
<< " bytesrecv=" << recv << " bytessent=" << sent;
peerdata.push_back(peer);
}
//qDebug() << peerdata;
// Update model data, which updates the table view
peersTableModel->addData(peerdata);
});
}
void RPC::refreshTransactions() { void RPC::refreshTransactions() {
if (conn == nullptr) if (conn == nullptr)
return noConnection(); return noConnection();
@ -1025,12 +1152,15 @@ void RPC::watchTxStatus() {
} }
void RPC::checkForUpdate(bool silent) { void RPC::checkForUpdate(bool silent) {
// Disable update checks for now
// TODO: Use Gitea API
return;
qDebug() << "checking for updates"; qDebug() << "checking for updates";
if (conn == nullptr) if (conn == nullptr)
return noConnection(); return noConnection();
QUrl cmcURL("https://api.github.com/repos/MyHush/SilentDragon/releases"); QUrl cmcURL("https://git.hush.is/hush/SilentDragon/releases");
QNetworkRequest req; QNetworkRequest req;
req.setUrl(cmcURL); req.setUrl(cmcURL);
@ -1074,7 +1204,7 @@ void RPC::checkForUpdate(bool silent) {
.arg(currentVersion.toString()), .arg(currentVersion.toString()),
QMessageBox::Yes, QMessageBox::Cancel); QMessageBox::Yes, QMessageBox::Cancel);
if (ans == QMessageBox::Yes) { if (ans == QMessageBox::Yes) {
QDesktopServices::openUrl(QUrl("https://github.com/MyHush/SilentDragon/releases")); QDesktopServices::openUrl(QUrl("https://git.hush.is/hush/SilentDragon/releases"));
} else { } else {
// If the user selects cancel, don't bother them again for this version // If the user selects cancel, don't bother them again for this version
s.setValue("update/lastversion", maxVersion.toString()); s.setValue("update/lastversion", maxVersion.toString());
@ -1206,9 +1336,9 @@ void RPC::refreshPrice() {
}); });
} }
void RPC::shutdownZcashd() { void RPC::shutdownHushd() {
// Shutdown embedded hushd if it was started // Shutdown embedded hushd if it was started
if (ezcashd == nullptr || ezcashd->processId() == 0 || conn == nullptr) { if (ehushd == nullptr || ehushd->processId() == 0 || conn == nullptr) {
// No hushd running internally, just return // No hushd running internally, just return
return; return;
} }
@ -1247,10 +1377,10 @@ void RPC::shutdownZcashd() {
QObject::connect(&waiter, &QTimer::timeout, [&] () { QObject::connect(&waiter, &QTimer::timeout, [&] () {
waitCount++; waitCount++;
if ((ezcashd->atEnd() && ezcashd->processId() == 0) || if ((ehushd->atEnd() && ehushd->processId() == 0) ||
ezcashd->state() == QProcess::NotRunning || ehushd->state() == QProcess::NotRunning ||
waitCount > 30 || waitCount > 30 ||
conn->config->zcashDaemon) { // If hushd is daemon, then we don't have to do anything else conn->config->hushDaemon) { // If hushd is daemon, then we don't have to do anything else
qDebug() << "Ended"; qDebug() << "Ended";
waiter.stop(); waiter.stop();
QTimer::singleShot(1000, [&]() { d.accept(); }); QTimer::singleShot(1000, [&]() { d.accept(); });

53
src/rpc.h

@ -1,19 +1,20 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef RPCCLIENT_H #ifndef RPCCLIENT_H
#define RPCCLIENT_H #define RPCCLIENT_H
#include "precompiled.h" #include "precompiled.h"
#include "balancestablemodel.h" #include "balancestablemodel.h"
#include "txtablemodel.h" #include "txtablemodel.h"
#include "peerstablemodel.h"
#include "bannedpeerstablemodel.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "connection.h" #include "connection.h"
class Turnstile;
struct TransactionItem { struct TransactionItem {
QString type; QString type;
qint64 datetime; qint64 datetime;
QString address; QString address;
QString txid; QString txid;
double amount; double amount;
@ -22,6 +23,29 @@ struct TransactionItem {
QString memo; QString memo;
}; };
struct BannedPeerItem {
QString address;
QString subnet;
qint64 banned_until;
};
struct PeerItem {
qint64 peerid;
QString type;
qint64 conntime;
QString address;
qint64 asn;
QString tls_cipher;
bool tls_verified;
qint64 banscore;
qint64 protocolversion;
QString subver;
qint64 bytes_received;
qint64 bytes_sent;
double pingtime;
};
struct WatchedTx { struct WatchedTx {
QString opid; QString opid;
Tx tx; Tx tx;
@ -36,12 +60,13 @@ public:
~RPC(); ~RPC();
void setConnection(Connection* c); void setConnection(Connection* c);
void setEZcashd(std::shared_ptr<QProcess> p); void setEHushd(std::shared_ptr<QProcess> p);
const QProcess* getEZcashD() { return ezcashd.get(); } const QProcess* getEHushD() { return ehushd.get(); }
void refresh(bool force = false); void refresh(bool force = false);
void refreshAddresses(); void refreshAddresses();
void refreshPeers();
void checkForUpdate(bool silent = true); void checkForUpdate(bool silent = true);
void refreshPrice(); void refreshPrice();
@ -54,12 +79,15 @@ public:
void fillTxJsonParams(QJsonArray& params, Tx tx); void fillTxJsonParams(QJsonArray& params, Tx tx);
void sendZTransaction(QJsonValue params, const std::function<void(QJsonValue)>& cb, const std::function<void(QString)>& err); void sendZTransaction(QJsonValue params, const std::function<void(QJsonValue)>& cb, const std::function<void(QString)>& err);
void shieldCoinbase(QJsonArray& params, const std::function<void(QJsonValue)>& cb, const std::function<void(QString)>& err);
void mergeToAddress(QJsonArray& params, const std::function<void(QJsonValue)>& cb, const std::function<void(QString)>& err);
void watchTxStatus(); void watchTxStatus();
const QMap<QString, WatchedTx> getWatchingTxns() { return watchingOps; } const QMap<QString, WatchedTx> getWatchingTxns() { return watchingOps; }
void addNewTxToWatch(const QString& newOpid, WatchedTx wtx); void addNewTxToWatch(const QString& newOpid, WatchedTx wtx);
const TxTableModel* getTransactionsModel() { return transactionsTableModel; } const TxTableModel* getTransactionsModel() { return transactionsTableModel; }
const PeersTableModel* getPeersModel() { return peersTableModel; }
const QList<QString>* getAllZAddresses() { return zaddresses; } const QList<QString>* getAllZAddresses() { return zaddresses; }
const QList<QString>* getAllTAddresses() { return taddresses; } const QList<QString>* getAllTAddresses() { return taddresses; }
const QList<UnspentOutput>* getUTXOs() { return utxos; } const QList<UnspentOutput>* getUTXOs() { return utxos; }
@ -76,16 +104,15 @@ public:
void importTPrivKey(QString addr, bool rescan, const std::function<void(QJsonValue)>& cb); void importTPrivKey(QString addr, bool rescan, const std::function<void(QJsonValue)>& cb);
void validateAddress(QString address, const std::function<void(QJsonValue)>& cb); void validateAddress(QString address, const std::function<void(QJsonValue)>& cb);
void shutdownZcashd(); void shutdownHushd();
void noConnection(); void noConnection();
bool isEmbedded() { return ezcashd != nullptr; } bool isEmbedded() { return ehushd != nullptr; }
QString getDefaultSaplingAddress(); QString getDefaultSaplingAddress();
QString getDefaultTAddress(); QString getDefaultTAddress();
void getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>)>); void getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>)>);
Turnstile* getTurnstile() { return turnstile; }
Connection* getConnection() { return conn; } Connection* getConnection() { return conn; }
private: private:
@ -107,12 +134,13 @@ private:
void getTransparentUnspent (const std::function<void(QJsonValue)>& cb); void getTransparentUnspent (const std::function<void(QJsonValue)>& cb);
void getZUnspent (const std::function<void(QJsonValue)>& cb); void getZUnspent (const std::function<void(QJsonValue)>& cb);
void getTransactions (const std::function<void(QJsonValue)>& cb); void getTransactions (const std::function<void(QJsonValue)>& cb);
void listBanned (const std::function<void(QJsonValue)>& cb);
void getPeerInfo (const std::function<void(QJsonValue)>& cb);
void getZAddresses (const std::function<void(QJsonValue)>& cb); void getZAddresses (const std::function<void(QJsonValue)>& cb);
void getTAddresses (const std::function<void(QJsonValue)>& cb); void getTAddresses (const std::function<void(QJsonValue)>& cb);
Connection* conn = nullptr; Connection* conn = nullptr;
std::shared_ptr<QProcess> ezcashd = nullptr; std::shared_ptr<QProcess> ehushd = nullptr;
QList<UnspentOutput>* utxos = nullptr; QList<UnspentOutput>* utxos = nullptr;
QMap<QString, double>* allBalances = nullptr; QMap<QString, double>* allBalances = nullptr;
QMap<QString, bool>* usedAddresses = nullptr; QMap<QString, bool>* usedAddresses = nullptr;
@ -122,6 +150,8 @@ private:
QMap<QString, WatchedTx> watchingOps; QMap<QString, WatchedTx> watchingOps;
TxTableModel* transactionsTableModel = nullptr; TxTableModel* transactionsTableModel = nullptr;
PeersTableModel* peersTableModel = nullptr;
BannedPeersTableModel* bannedPeersTableModel = nullptr;
BalancesTableModel* balancesTableModel = nullptr; BalancesTableModel* balancesTableModel = nullptr;
QTimer* timer; QTimer* timer;
@ -130,7 +160,6 @@ private:
Ui::MainWindow* ui; Ui::MainWindow* ui;
MainWindow* main; MainWindow* main;
Turnstile* turnstile;
// Current balance in the UI. If this number updates, then refresh the UI // Current balance in the UI. If this number updates, then refresh the UI
QString currentBalance; QString currentBalance;

2
src/scripts/dotranslations.sh

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright (c) 2019-2020 The Hush developers # Copyright (c) 2019-2021 The Hush developers
# Released under the GPLv3 # Released under the GPLv3
if [ -z $QT_STATIC ]; then if [ -z $QT_STATIC ]; then

11
src/scripts/make-binary-tarball.sh

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright (c) 2020 The Hush developers # Copyright (c) 2019-2021 The Hush developers
# Released under the GPLv3 # Released under the GPLv3
APP_VERSION=$(cat src/version.h | cut -d\" -f2) APP_VERSION=$(cat src/version.h | cut -d\" -f2)
@ -18,14 +18,11 @@ if [ -e $DIR ]; then
fi fi
mkdir -p $DIR mkdir -p $DIR
strip silentdragon strip silentdragon
strip komodod strip hushd
strip komodo-tx strip hush-tx
strip komodo-cli strip hush-cli
cp silentdragon $DIR cp silentdragon $DIR
cp komodod $DIR
cp komodo-cli $DIR
cp komodo-tx $DIR
cp hushd $DIR cp hushd $DIR
cp hush-cli $DIR cp hush-cli $DIR
cp hush-tx $DIR cp hush-tx $DIR

20
src/scripts/make-deb.sh

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright (c) 2019-2020 The Hush developers # Copyright (c) 2019-2021 The Hush developers
# Thanks to Zecwallet for the original code # Thanks to Zecwallet for the original code
# Released under the GPLv3 # Released under the GPLv3
@ -19,18 +19,18 @@ if [ -z $HUSH_DIR ]; then
exit 1; exit 1;
fi fi
if [ ! -f $HUSH_DIR/komodod ]; then if [ ! -f $HUSH_DIR/hushd ]; then
echo "Couldn't find komodod in $HUSH_DIR . Please build komodod." echo "Couldn't find hushd in $HUSH_DIR . Please build hushd."
exit 1; exit 1;
fi fi
if [ ! -f $HUSH_DIR/komodo-cli ]; then if [ ! -f $HUSH_DIR/hush-cli ]; then
echo "Couldn't find komodo-cli in $HUSH_DIR . Please build komodo-cli." echo "Couldn't find hush-cli in $HUSH_DIR . Please build hush-cli."
exit 1; exit 1;
fi fi
if [ ! -f $HUSH_DIR/komodo-tx ]; then if [ ! -f $HUSH_DIR/hush-tx ]; then
echo "Couldn't find komodo-tx in $HUSH_DIR . Please build komodo-tx." echo "Couldn't find hush-tx in $HUSH_DIR . Please build hush-tx."
exit 1; exit 1;
fi fi
@ -73,9 +73,6 @@ mkdir $DIR > /dev/null
strip silentdragon strip silentdragon
cp silentdragon $DIR > /dev/null cp silentdragon $DIR > /dev/null
cp $HUSH_DIR/artifacts/komodod $DIR > /dev/null
cp $HUSH_DIR/artifacts/komodo-cli $DIR > /dev/null
cp $HUSH_DIR/artifacts/komodo-tx $DIR > /dev/null
cp $HUSH_DIR/artifacts/hushd $DIR > /dev/null cp $HUSH_DIR/artifacts/hushd $DIR > /dev/null
cp $HUSH_DIR/artifacts/hush-cli $DIR > /dev/null cp $HUSH_DIR/artifacts/hush-cli $DIR > /dev/null
cp $HUSH_DIR/artifacts/hush-tx $DIR > /dev/null cp $HUSH_DIR/artifacts/hush-tx $DIR > /dev/null
@ -113,8 +110,7 @@ mkdir -p $debdir/usr/local/bin
cat src/scripts/control | sed "s/RELEASE_VERSION/$APP_VERSION/g" > $debdir/DEBIAN/control cat src/scripts/control | sed "s/RELEASE_VERSION/$APP_VERSION/g" > $debdir/DEBIAN/control
cp silentdragon $debdir/usr/local/bin/ cp silentdragon $debdir/usr/local/bin/
# TODO: how does this interact with hushd deb ? cp $HUSH_DIR/artifacts/hushd $debdir/usr/local/bin/hushd
cp $HUSH_DIR/artifacts/komodod $debdir/usr/local/bin/hush-komodod
mkdir -p $debdir/usr/share/pixmaps/ mkdir -p $debdir/usr/share/pixmaps/
cp res/silentdragon.xpm $debdir/usr/share/pixmaps/ cp res/silentdragon.xpm $debdir/usr/share/pixmaps/

2
src/scripts/make-only-deb.sh

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright (c) 2020 The Hush developers # Copyright (c) 2019-2021 The Hush developers
# Released under the GPLv3 # Released under the GPLv3
echo "Let There Be Debian Packages" echo "Let There Be Debian Packages"

2
src/scripts/mkmacdmg.sh

@ -1,4 +1,6 @@
#!/bin/bash #!/bin/bash
# Copyright (c) 2019-2021 The Hush developers
# Released under the GPLv3
# Accept the variables as command line arguments as well # Accept the variables as command line arguments as well
POSITIONAL=() POSITIONAL=()

2
src/scripts/mkrelease.sh

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright (c) 2019-2020 The Hush developers # Copyright (c) 2019-2021 The Hush developers
# Thanks to Zecwallet for the original code # Thanks to Zecwallet for the original code
# Released under the GPLv3 # Released under the GPLv3

2
src/scripts/signbinaries.sh

@ -1,4 +1,6 @@
#!/bin/bash #!/bin/bash
# Copyright (c) 2019-2021 The Hush developers
# Released under the GPLv3
# Accept the variables as command line arguments as well # Accept the variables as command line arguments as well
POSITIONAL=() POSITIONAL=()

19
src/sendtab.cpp

@ -1,4 +1,5 @@
// Copyright 2019-2020 Hush developers // Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "addressbook.h" #include "addressbook.h"
@ -505,24 +506,14 @@ Tx MainWindow::createTxFromSendPage() {
if (Settings::getInstance()->getAllowCustomFees()) { if (Settings::getInstance()->getAllowCustomFees()) {
tx.fee = ui->minerFeeAmt->text().toDouble(); tx.fee = ui->minerFeeAmt->text().toDouble();
} } else {
else {
tx.fee = Settings::getMinerFee(); tx.fee = Settings::getMinerFee();
} }
if (Settings::getInstance()->getAutoShield() && sendChangeToSapling) { if (Settings::getInstance()->getAutoShield() && sendChangeToSapling) {
auto saplingAddr = std::find_if(rpc->getAllZAddresses()->begin(), rpc->getAllZAddresses()->end(), [=](auto i) -> bool { auto saplingAddr = std::find_if(rpc->getAllZAddresses()->begin(), rpc->getAllZAddresses()->end(), [=](auto i) -> bool {
// We're finding a sapling address that is not one of the To addresses, because zcash doesn't allow duplicated addresses
// TODO: Should we disable this in Hush? What are the privacy and chain analysis considerations?
bool isSapling = Settings::getInstance()->isSaplingAddress(i); bool isSapling = Settings::getInstance()->isSaplingAddress(i);
if (!isSapling) return false; if (!isSapling) return false;
// Also check all the To addresses
for (auto t : tx.toAddrs) {
if (t.addr == i)
return false;
}
return true; return true;
}); });
@ -776,9 +767,10 @@ QString MainWindow::doSendTxValidations(Tx tx) {
} }
for (auto toAddr : tx.toAddrs) { for (auto toAddr : tx.toAddrs) {
//TODO: diff errors for completely invalid vs transparent? Educate.
if (!Settings::isValidAddress(toAddr.addr)) { if (!Settings::isValidAddress(toAddr.addr)) {
QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr); QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr);
return QString(tr("Recipient Address ")) % addr % tr(" is Invalid"); return QString(tr("Extreme Privacy! ")) % addr % tr(" is transparent. You must send to a zaddr.");
} }
// This technically shouldn't be possible, but issue #62 seems to have discovered a bug // This technically shouldn't be possible, but issue #62 seems to have discovered a bug
@ -788,7 +780,6 @@ QString MainWindow::doSendTxValidations(Tx tx) {
} }
} }
return QString(); return QString();
} }

2
src/senttxstore.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "senttxstore.h" #include "senttxstore.h"
#include "settings.h" #include "settings.h"

2
src/senttxstore.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef SENTTXSTORE_H #ifndef SENTTXSTORE_H
#define SENTTXSTORE_H #define SENTTXSTORE_H

20
src/settings.cpp

@ -1,4 +1,4 @@
// Copyright 2019-2020 Hush developers // Copyright 2019-2021 Hush developers
// Released under the GPLv3 // Released under the GPLv3
#include "mainwindow.h" #include "mainwindow.h"
#include "settings.h" #include "settings.h"
@ -35,8 +35,8 @@ void Settings::setAllowFetchPrices(bool allow) {
Explorer Settings::getExplorer() { Explorer Settings::getExplorer() {
// Load from the QT Settings. // Load from the QT Settings.
QSettings s; QSettings s;
//TODO: make it easy for people to use other explorers like komodod.com //TODO: make it easy for people to use other explorers
QString explorer = "https://explorer.myhush.org"; QString explorer = "https://explorer.hush.is";
auto txExplorerUrl = s.value("explorer/txExplorerUrl", explorer + "/tx/").toString(); auto txExplorerUrl = s.value("explorer/txExplorerUrl", explorer + "/tx/").toString();
auto addressExplorerUrl = s.value("explorer/addressExplorerUrl", explorer + "/address/").toString(); auto addressExplorerUrl = s.value("explorer/addressExplorerUrl", explorer + "/address/").toString();
@ -89,7 +89,7 @@ void Settings::saveRestoreTableHeader(QTableView* table, QDialog* d, QString tab
}); });
} }
void Settings::setUsingZcashConf(QString confLocation) { void Settings::setUsingHushConf(QString confLocation) {
if (!confLocation.isEmpty()) if (!confLocation.isEmpty())
_confLocation = confLocation; _confLocation = confLocation;
} }
@ -131,12 +131,12 @@ bool Settings::isTAddress(QString addr) {
return addr.startsWith("R"); return addr.startsWith("R");
} }
int Settings::getZcashdVersion() { int Settings::getHushdVersion() {
return _zcashdVersion; return _hushdVersion;
} }
void Settings::setZcashdVersion(int version) { void Settings::setHushdVersion(int version) {
_zcashdVersion = version; _hushdVersion = version;
} }
bool Settings::isSyncing() { bool Settings::isSyncing() {
@ -329,7 +329,7 @@ QString Settings::getDonationAddr() {
return "zs1aq4xnrkjlnxx0zesqye7jz3dfrf3rjh7q5z6u8l6mwyqqaam3gx3j2fkqakp33v93yavq46j83q"; return "zs1aq4xnrkjlnxx0zesqye7jz3dfrf3rjh7q5z6u8l6mwyqqaam3gx3j2fkqakp33v93yavq46j83q";
} }
bool Settings::addToZcashConf(QString confLocation, QString line) { bool Settings::addToHushConf(QString confLocation, QString line) {
QFile file(confLocation); QFile file(confLocation);
if (!file.open(QIODevice::ReadWrite | QIODevice::Append)) if (!file.open(QIODevice::ReadWrite | QIODevice::Append))
return false; return false;
@ -352,7 +352,7 @@ void Settings::set_currency_name(QString currency_name) {
} }
bool Settings::removeFromZcashConf(QString confLocation, QString option) { bool Settings::removeFromHushConf(QString confLocation, QString option) {
if (confLocation.isEmpty()) if (confLocation.isEmpty())
return false; return false;

17
src/settings.h

@ -1,4 +1,5 @@
// Copyright 2019 The Hush developers // Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef SETTINGS_H #ifndef SETTINGS_H
#define SETTINGS_H #define SETTINGS_H
@ -53,8 +54,8 @@ public:
bool isSyncing(); bool isSyncing();
void setSyncing(bool syncing); void setSyncing(bool syncing);
int getZcashdVersion(); int getHushdVersion();
void setZcashdVersion(int version); void setHushdVersion(int version);
void setUseEmbedded(bool r) { _useEmbedded = r; } void setUseEmbedded(bool r) { _useEmbedded = r; }
bool useEmbedded() { return _useEmbedded; } bool useEmbedded() { return _useEmbedded; }
@ -88,8 +89,8 @@ public:
QString get_currency_name(); QString get_currency_name();
void set_currency_name(QString currency_name); void set_currency_name(QString currency_name);
void setUsingZcashConf(QString confLocation); void setUsingHushConf(QString confLocation);
const QString& getZcashdConfLocation() { return _confLocation; } const QString& getHushdConfLocation() { return _confLocation; }
void setHUSHPrice(double p) { hushPrice = p; } void setHUSHPrice(double p) { hushPrice = p; }
void set_fiat_price(double p) { fiat_price = p; } void set_fiat_price(double p) { fiat_price = p; }
@ -135,8 +136,8 @@ public:
static bool isValidAddress(QString addr); static bool isValidAddress(QString addr);
static bool addToZcashConf(QString confLocation, QString line); static bool addToHushConf(QString confLocation, QString line);
static bool removeFromZcashConf(QString confLocation, QString option); static bool removeFromHushConf(QString confLocation, QString option);
static const QString labelRegExp; static const QString labelRegExp;
@ -157,7 +158,7 @@ private:
bool _isTestnet = false; bool _isTestnet = false;
bool _isSyncing = false; bool _isSyncing = false;
int _blockNumber = 0; int _blockNumber = 0;
int _zcashdVersion = 0; int _hushdVersion = 0;
bool _useEmbedded = false; bool _useEmbedded = false;
bool _headless = false; bool _headless = false;
int _peerConnections = 0; int _peerConnections = 0;

12
src/settings.ui

@ -162,7 +162,7 @@
</widget> </widget>
</item> </item>
<item row="16" column="0"> <item row="16" column="0">
<widget class="QLabel" name="label_20"> <widget class="QLabel" name="label_201">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -473,7 +473,7 @@
<item row="9" column="0" colspan="2"> <item row="9" column="0" colspan="2">
<widget class="QCheckBox" name="chkCheckUpdates"> <widget class="QCheckBox" name="chkCheckUpdates">
<property name="text"> <property name="text">
<string>Check github for updates at startup</string> <string>Check git.hush.is for updates at startup</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -555,7 +555,7 @@
<item row="10" column="0" colspan="2"> <item row="10" column="0" colspan="2">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="label_8">
<property name="text"> <property name="text">
<string>Connect to github on startup to check for updates</string> <string>Connect to git.hush.is on startup to check for updates</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -615,7 +615,7 @@
</rect> </rect>
</property> </property>
<property name="text"> <property name="text">
<string notr="true">https://explorer.myhush.org/tx/</string> <string notr="true">https://explorer.hush.is/tx/</string>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="label_15"> <widget class="QLabel" name="label_15">
@ -641,7 +641,7 @@
</rect> </rect>
</property> </property>
<property name="text"> <property name="text">
<string notr="true">https://explorer.myhush.org/address/</string> <string notr="true">https://explorer.hush.is/address/</string>
</property> </property>
</widget> </widget>
<widget class="QLabel" name="label_16"> <widget class="QLabel" name="label_16">
@ -693,7 +693,7 @@
</rect> </rect>
</property> </property>
<property name="text"> <property name="text">
<string notr="true">https://explorer.testnet.myhush.org/address/</string> <string notr="true">https://explorer.testnet.hush.is/address/</string>
</property> </property>
</widget> </widget>
</widget> </widget>

2
src/txtablemodel.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "txtablemodel.h" #include "txtablemodel.h"
#include "settings.h" #include "settings.h"
#include "rpc.h" #include "rpc.h"

2
src/txtablemodel.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef STRINGSTABLEMODEL_H #ifndef STRINGSTABLEMODEL_H
#define STRINGSTABLEMODEL_H #define STRINGSTABLEMODEL_H

2
src/validateaddress.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "validateaddress.h" #include "validateaddress.h"

2
src/validateaddress.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef VALIDATEADDRESS_H #ifndef VALIDATEADDRESS_H
#define VALIDATEADDRESS_H #define VALIDATEADDRESS_H

2
src/version.h

@ -1 +1 @@
#define APP_VERSION "1.0.0" #define APP_VERSION "1.3.0"

2
src/viewalladdresses.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "viewalladdresses.h" #include "viewalladdresses.h"
#include "settings.h" #include "settings.h"

4
src/viewalladdresses.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef VIEWALLADDRESSES_H #ifndef VIEWALLADDRESSES_H
#define VIEWALLADDRESSES_H #define VIEWALLADDRESSES_H
@ -21,4 +23,4 @@ private:
RPC* rpc; RPC* rpc;
}; };
#endif #endif

16
src/websockets.cpp

@ -1,6 +1,6 @@
// Copyright 2019-2020 Hush developers // Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "websockets.h" #include "websockets.h"
#include "rpc.h" #include "rpc.h"
#include "settings.h" #include "settings.h"
#include "ui_mobileappconnector.h" #include "ui_mobileappconnector.h"
@ -28,7 +28,7 @@ WSServer::WSServer(quint16 port, bool debug, QObject *parent) :
m_mainWindow = (MainWindow *) parent; m_mainWindow = (MainWindow *) parent;
if (m_pWebSocketServer->listen(QHostAddress::AnyIPv4, port)) { if (m_pWebSocketServer->listen(QHostAddress::AnyIPv4, port)) {
if (m_debug) if (m_debug)
qDebug() << "Echoserver listening on port" << port; qDebug() << "SD WebSocketServer listening on port" << port;
connect(m_pWebSocketServer, &QWebSocketServer::newConnection, connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
this, &WSServer::onNewConnection); this, &WSServer::onNewConnection);
connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &WSServer::closed); connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &WSServer::closed);
@ -37,7 +37,7 @@ WSServer::WSServer(quint16 port, bool debug, QObject *parent) :
WSServer::~WSServer() WSServer::~WSServer()
{ {
qDebug() << "Closing websocket server"; qDebug() << "Closing WebsocketServer";
m_pWebSocketServer->close(); m_pWebSocketServer->close();
qDeleteAll(m_clients.begin(), m_clients.end()); qDeleteAll(m_clients.begin(), m_clients.end());
qDebug() << "Deleted all websocket clients"; qDebug() << "Deleted all websocket clients";
@ -45,7 +45,7 @@ WSServer::~WSServer()
void WSServer::onNewConnection() void WSServer::onNewConnection()
{ {
qDebug() << "Websocket server: new connection"; qDebug() << "WebsocketServer: new connection";
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection(); QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
connect(pSocket, &QWebSocket::textMessageReceived, this, &WSServer::processTextMessage); connect(pSocket, &QWebSocket::textMessageReceived, this, &WSServer::processTextMessage);
@ -121,7 +121,9 @@ void ws_error() {
void WormholeClient::sslerrors(const QList<QSslError> &) void WormholeClient::sslerrors(const QList<QSslError> &)
{ {
qDebug() << "SSL errors occurred!"; //TODO: give more details. We only get semi-useful data and some errors
// should be ignored
qDebug() << "SSL errors occurred, lulz!";
//TODO: don't do this in prod //TODO: don't do this in prod
//m_webSocket->ignoreSslErrors(); //m_webSocket->ignoreSslErrors();
@ -131,7 +133,7 @@ void WormholeClient::connect() {
qDebug() << "Wormhole::connect"; qDebug() << "Wormhole::connect";
delete m_webSocket; delete m_webSocket;
m_webSocket = new QWebSocket(); m_webSocket = new QWebSocket();
QUrl wormhole = QUrl("wss://wormhole.myhush.org:443"); QUrl wormhole = QUrl("wss://wormhole.hush.is:443");
if (m_webSocket) { if (m_webSocket) {
QObject::connect(m_webSocket, &QWebSocket::connected, this, &WormholeClient::onConnected); QObject::connect(m_webSocket, &QWebSocket::connected, this, &WormholeClient::onConnected);

6
src/websockets.h

@ -1,12 +1,12 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef WEBSOCKETS_H #ifndef WEBSOCKETS_H
#define WEBSOCKETS_H #define WEBSOCKETS_H
#include "precompiled.h" #include "precompiled.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mobileappconnector.h" #include "ui_mobileappconnector.h"
QT_FORWARD_DECLARE_CLASS(QWebSocketServer) QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
QT_FORWARD_DECLARE_CLASS(QWebSocket) QT_FORWARD_DECLARE_CLASS(QWebSocket)
@ -172,6 +172,4 @@ private:
static AppDataModel* instance; static AppDataModel* instance;
}; };
#endif // WEBSOCKETS_H #endif // WEBSOCKETS_H

9
util/silentdragon.desktop

@ -0,0 +1,9 @@
[Desktop Entry]
Version=1.0
Name=Silent Dragon
Comment=Full-node wallet for HUSH cryptocurrency
Exec=/usr/bin/silentdragon
Icon=/opt/silentdragon/silentdragon.png
Terminal=false
Type=Application
Categories=Network;

2
win-build.sh

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright 2019-2020 The Hush Developers # Copyright 2019-2021 The Hush Developers
# Released under the GPLv3 # Released under the GPLv3
# This script will cross-compile windoze binaries, hopefully! # This script will cross-compile windoze binaries, hopefully!

Loading…
Cancel
Save