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
komodo-cli
komodod
hush-cli
hushd
*.mak
Makefile
Makefile.*
@ -29,12 +31,7 @@ src/ui_*.h
workspace.code-workspace
x64/
*.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
# 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
[![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">
<a href="https://twitter.com/MyHushTeam">
@ -21,7 +18,15 @@
SilentDragon desktop wallet for HUSH runs on Linux, Windows and macOS.
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
@ -29,20 +34,21 @@ SilentDragon contacts a few different external websites to get various
bits of data.
* coingecko.com for price data API
* explorer.myhush.org for explorer links
* explorer.hush.is for explorer links
* 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
in SilentDragon to prevent this, or better yet, use TAILS: https://tails.boum.org/
# 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
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.
@ -53,41 +59,45 @@ Pass `--no-embedded` to disable the embedded hushd and force SilentDragon to con
## Compiling from source
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
[here](https://www.qt.io/download). Note that if you are compiling from source,
you won't get the embedded hushd by default. You can either run an external
c++. It also depends on Qt5, which you can get from [here](https://www.qt.io/download)
or within your operating system package manager. Note that if you are compiling
from source, you won't get the embedded hushd by default. You can either run an external
hushd, or compile hushd as well.
### 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
git clone https://github.com/MyHush/SilentDragon.git
git clone https://git.hush.is/hush/SilentDragon
cd SilentDragon
./build.sh linguist # compile translations
./build.sh linguist
./build.sh
./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
git clone https://github.com/MyHush/SilentDragon.git
git clone https://git.hush.is/hush/SilentDragon
cd SilentDragon
./build.sh linguist # compile translations
./build.sh linguist
./build.sh release
./silentdragon
```
### 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
```
git clone https://github.com/MyHush/SilentDragon.git
```shell script
git clone https://git.hush.is/hush/SilentDragon
cd SilentDragon
c:\Qt5\bin\qmake.exe silentdragon.pro -spec win32-msvc CONFIG+=debug
nmake
@ -96,7 +106,7 @@ debug\SilentDragon.exe
```
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
```
@ -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.
```
git clone https://github.com/MyHush/SilentDragon.git
TODO: Suggestions on installing qt5 deps on a Mac
```shell script
git clone https://git.hush.is/hush/SilentDragon
cd SilentDragon
qmake silentdragon.pro CONFIG+=debug
# These commands require qmake to be installed
./build.sh linguist
./build.sh
make
./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
these four files in your Git repo:
```
ln -s ../hush3/src/hushd
ln -s ../hush3/src/komodod
ln -s ../hush3/src/komodo-cli
```shell script
ln -s ../hush3/src/hushd
ln -s ../hush3/src/hush-cli
```
The above assumes silentdragon and hush3 git repos are in the same directory. File names on Windows will need to be tweaked.
### 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>
</qresource>
<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/silentdragon-animated.gif</file>
<file>res/silentdragon-animated-dark.gif</file>
@ -17,6 +18,7 @@
<file>res/silentdragon-animated-startup-dark.gif</file>
</qresource>
<qresource prefix="/translations">
<file>res/silentdragon_be.qm</file>
<file>res/silentdragon_bg.qm</file>
<file>res/silentdragon_de.qm</file>
<file>res/silentdragon_es.qm</file>
@ -27,6 +29,7 @@
<file>res/silentdragon_it.qm</file>
<file>res/silentdragon_id.qm</file>
<file>res/silentdragon_nl.qm</file>
<file>res/silentdragon_pl.qm</file>
<file>res/silentdragon_pt.qm</file>
<file>res/silentdragon_ro.qm</file>
<file>res/silentdragon_ru.qm</file>

BIN
asmap.dat

Binary file not shown.

8
build.sh

@ -1,5 +1,5 @@
#!/bin/bash
# Copyright 2019-2020 The Hush Developers
# Copyright 2018-2021 The Hush Developers
# Released under the GPLv3
set -e
@ -15,6 +15,12 @@ else
JOBS=1
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)
echo "Compiling SilentDragon $VERSION with $JOBS threads..."
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>
<string>logo.icns</string>
<key>CFBundleIdentifier</key>
<string>com.myhush.silentdragon</string>
<string>com.hush.silentdragon</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<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
*/
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;
color: #fff;

2
res/libsodium/buildlibsodium.sh

@ -1,5 +1,5 @@
#!/bin/bash
# Copyright (c) 2019-2020 The Hush developers
# Copyright (c) 2019-2021 The Hush developers
# Released under the GPLv3
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>
<location filename="../src/mainwindow.ui" line="1453"/>
<source>&amp;Hush Discord</source>
<source>&amp;Hush Telegram</source>
<translation type="unfinished"></translation>
</message>
<message>
@ -434,7 +434,7 @@
</message>
<message>
<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>
</message>
<message>
@ -1519,7 +1519,7 @@ Would you like to visit the releases page?</source>
</message>
<message>
<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>
</message>
<message>
@ -1564,7 +1564,7 @@ Would you like to visit the releases page?</source>
</message>
<message>
<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>
</message>
<message>
@ -1760,7 +1760,7 @@ Would you like to visit the releases page?</source>
</message>
</context>
<context>
<name>createZcashConf</name>
<name>createHushConf</name>
<message>
<location filename="../src/createzcashconfdialog.ui" line="14"/>
<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
# Copyright 2019-2020 The Hush Developers
# Copyright 2019-2021 The Hush Developers
./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
#
#-------------------------------------------------
QT += core gui network
@ -51,6 +49,8 @@ SOURCES += \
src/sendtab.cpp \
src/senttxstore.cpp \
src/txtablemodel.cpp \
src/peerstablemodel.cpp \
src/bannedpeerstablemodel.cpp \
src/qrcodelabel.cpp \
src/connection.cpp \
src/fillediconlabel.cpp \
@ -75,6 +75,8 @@ HEADERS += \
src/3rdparty/qrcode/QrSegment.hpp \
src/settings.h \
src/txtablemodel.h \
src/peerstablemodel.h \
src/bannedpeerstablemodel.h \
src/senttxstore.h \
src/qrcodelabel.h \
src/connection.h \
@ -111,7 +113,8 @@ FORMS += \
src/requestdialog.ui
TRANSLATIONS = res/silentdragon_bg.ts \
TRANSLATIONS = res/silentdragon_be.ts \
res/silentdragon_bg.ts \
res/silentdragon_de.ts \
res/silentdragon_es.ts \
res/silentdragon_fi.ts \
@ -121,6 +124,7 @@ TRANSLATIONS = res/silentdragon_bg.ts \
res/silentdragon_id.ts \
res/silentdragon_it.ts \
res/silentdragon_nl.ts \
res/silentdragon_pl.ts \
res/silentdragon_pt.ts \
res/silentdragon_ro.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
#define sodium_H
#include "sodium/version.h"
#include "sodium/core.h"
#include "sodium/crypto_aead_aes256gcm.h"
#include "sodium/crypto_aead_chacha20poly1305.h"

10
src/about.ui

@ -53,13 +53,13 @@
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;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 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-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, 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; 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;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: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: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'; 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'; 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; 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

2
src/addressbook.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "addressbook.h"
#include "ui_addressbook.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
#define ADDRESSBOOK_H
@ -66,4 +68,4 @@ private:
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 "addressbook.h"
#include "settings.h"
@ -36,4 +38,4 @@ void AddressCombo::insertItem(int index, const QString& text, double bal) {
QString txt = AddressBook::addLabelToAddress(text) %
"(" % Settings::getDisplayFormat(bal) % ")";
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
#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 "addressbook.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
#define BALANCESTABLEMODEL_H
@ -31,4 +33,4 @@ private:
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
// GPLv3
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "connection.h"
#include "mainwindow.h"
#include "settings.h"
#include "ui_connection.h"
#include "ui_createzcashconfdialog.h"
#include "rpc.h"
#include "precompiled.h"
ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) {
this->main = main;
this->rpc = rpc;
@ -52,28 +50,28 @@ void ConnectionLoader::loadConnection() {
void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
// Priority 1: Ensure all params are present.
if (!verifyParams()) {
downloadParams([=]() { this->doAutoConnect(); });
qDebug() << "Cannot find sapling params!";
return;
}
// 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"));
if (config.get() != nullptr) {
auto connection = makeConnection(config);
refreshZcashdState(connection, [=] () {
// Refused connection. So try and start embedded zcashd
refreshHushdState(connection, [=] () {
// Refused connection. So try and start embedded hushd
if (Settings::getInstance()->useEmbedded()) {
if (tryEzcashdStart) {
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
main->logger->write("Embedded hushd started up, trying autoconnect in 1 sec");
QTimer::singleShot(1000, [=]() { doAutoConnect(); } );
} else {
if (config->zcashDaemon) {
if (config->hushDaemon) {
// hushd is configured to run as a daemon, so we must wait for a few seconds
// to let it 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
// and see if that works, else throw an error
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 {
// 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");
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 "
"with SilentDragon\n\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"
"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.") %
(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);
@ -116,7 +114,7 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
} else {
if (Settings::getInstance()->useEmbedded()) {
// HUSH3.conf was not found, so create one
createZcashConf();
createHushConf();
} else {
// Fall back to manual connect
doManualConnect();
@ -144,17 +142,17 @@ QString randomPassword() {
/**
* This will create a new HUSH3.conf and download params if they cannot be found
*/
void ConnectionLoader::createZcashConf() {
main->logger->write("createZcashConf");
void ConnectionLoader::createHushConf() {
main->logger->write(__func__);
auto confLocation = zcashConfWritableLocation();
auto confLocation = hushConfWritableLocation();
QFileInfo fi(confLocation);
QDialog d(main);
Ui_createZcashConf ui;
Ui_createHushConf ui;
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.btnPickDir->setEnabled(false);
@ -202,7 +200,7 @@ void ConnectionLoader::createZcashConf() {
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 << "rpcuser=hush\n";
out << "rpcpassword=" % randomPassword() << "\n";
@ -217,6 +215,10 @@ void ConnectionLoader::createZcashConf() {
// Consolidation is now defaulted to ON for new wallets
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()) {
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) {
auto fnSaveFileName = [&] (QUrl url) {
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())
return false;
@ -343,8 +332,8 @@ bool ConnectionLoader::startEmbeddedZcashd() {
// Static because it needs to survive even after this method returns.
static QString processStdErrOutput;
if (ezcashd != nullptr) {
if (ezcashd->state() == QProcess::NotRunning) {
if (ehushd != nullptr) {
if (ehushd->state() == QProcess::NotRunning) {
if (!processStdErrOutput.isEmpty()) {
QMessageBox::critical(main, QObject::tr("hushd error"), "hushd said: " + processStdErrOutput,
QMessageBox::Ok);
@ -358,9 +347,9 @@ bool ConnectionLoader::startEmbeddedZcashd() {
QDir appPath(QCoreApplication::applicationDirPath());
#ifdef Q_OS_WIN64
auto hushdProgram = appPath.absoluteFilePath("komodod.exe");
auto hushdProgram = appPath.absoluteFilePath("hushd.exe");
#else
auto hushdProgram = appPath.absoluteFilePath("komodod");
auto hushdProgram = appPath.absoluteFilePath("hushd");
#endif
//if (!QFile(hushdProgram).exists()) {
@ -372,48 +361,59 @@ bool ConnectionLoader::startEmbeddedZcashd() {
main->logger->write("Found hushd at " + hushdProgram);
}
ezcashd = std::shared_ptr<QProcess>(new QProcess(main));
QObject::connect(ezcashd.get(), &QProcess::started, [=] () {
ehushd = std::shared_ptr<QProcess>(new QProcess(main));
QObject::connect(ehushd.get(), &QProcess::started, [=] () {
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) {
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;
});
std::weak_ptr<QProcess> weak_obj(ezcashd);
std::weak_ptr<QProcess> weak_obj(ehushd);
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();
ptr_main->logger->write("hushd stderr:" + output);
processStdErrOutput.append(output);
});
// 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(" ");
// Finally, actually start the full node
// Finally, actually start the full node
#ifdef Q_OS_LINUX
qDebug() << "Starting on Linux: " + hushdProgram + " " + params;
ezcashd->start(hushdProgram, arguments);
ehushd->start(hushdProgram, arguments);
#elif defined(Q_OS_DARWIN)
qDebug() << "Starting on Darwin: " + hushdProgram + " " + params;
ezcashd->start(hushdProgram, arguments);
ehushd->start(hushdProgram, arguments);
#elif defined(Q_OS_WIN64)
qDebug() << "Starting on Win64: " + hushdProgram + " " + params;
ezcashd->setWorkingDirectory(appPath.absolutePath());
ezcashd->start(hushdProgram, arguments);
ehushd->setWorkingDirectory(appPath.absolutePath());
ehushd->start(hushdProgram, arguments);
#else
qDebug() << "Starting on Unknown OS(!): " + hushdProgram + " " + params;
ezcashd->setWorkingDirectory(appPath.absolutePath());
ezcashd->start(hushdProgram, arguments);
ehushd->setWorkingDirectory(appPath.absolutePath());
ehushd->start(hushdProgram, arguments);
#endif // Q_OS_LINUX
main->logger->write("Started via " + hushdProgram + " " + params);
@ -436,7 +436,7 @@ void ConnectionLoader::doManualConnect() {
}
auto connection = makeConnection(config);
refreshZcashdState(connection, [=] () {
refreshHushdState(connection, [=] () {
QString explanation = QString()
% 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.");
@ -449,7 +449,7 @@ void ConnectionLoader::doManualConnect() {
}
void ConnectionLoader::doRPCSetConnection(Connection* conn) {
rpc->setEZcashd(ezcashd);
rpc->setEHushd(ehushd);
rpc->setConnection(conn);
d->accept();
@ -476,7 +476,7 @@ Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> c
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");
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);
main->logger->write("Waiting for hushd to come online.");
// 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.
*/
void ConnectionLoader::showError(QString explanation) {
rpc->setEZcashd(nullptr);
rpc->setEHushd(nullptr);
rpc->noConnection();
QMessageBox::critical(main, QObject::tr("Connection Error"), explanation, QMessageBox::Ok);
d->close();
}
QString ConnectionLoader::locateZcashConfFile() {
QString ConnectionLoader::locateHushConfFile() {
#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)
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
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
main->logger->write("Found HUSH3.conf at " + 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
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)
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
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
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);
}
@ -650,11 +663,11 @@ bool ConnectionLoader::verifyParams() {
/**
* Try to automatically detect a HUSH3/HUSH3.conf file in the correct location and load parameters
*/
std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectZcashConf() {
auto confLocation = locateZcashConfFile();
std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectHushConf() {
auto confLocation = locateHushConfFile();
if (confLocation.isNull()) {
// No Zcash file, just return with nothing
// No file, just return with nothing
return nullptr;
}
@ -666,14 +679,14 @@ std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectZcashConf() {
QTextStream in(&file);
auto zcashconf = new ConnectionConfig();
zcashconf->host = "127.0.0.1";
zcashconf->connType = ConnectionType::DetectedConfExternalZcashD;
zcashconf->usingZcashConf = true;
zcashconf->zcashDir = QFileInfo(confLocation).absoluteDir().absolutePath();
zcashconf->zcashDaemon = false;
auto hushconf = new ConnectionConfig();
hushconf->host = "127.0.0.1";
hushconf->connType = ConnectionType::DetectedConfExternalHushD;
hushconf->usingHushConf = true;
hushconf->hushDir = QFileInfo(confLocation).absoluteDir().absolutePath();
hushconf->hushDaemon = false;
Settings::getInstance()->setUsingZcashConf(confLocation);
Settings::getInstance()->setUsingHushConf(confLocation);
while (!in.atEnd()) {
QString line = in.readLine();
@ -682,43 +695,43 @@ std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectZcashConf() {
QString value = line.right(line.length() - s - 1).trimmed();
if (name == "rpcuser") {
zcashconf->rpcuser = value;
hushconf->rpcuser = value;
}
if (name == "rpcpassword") {
zcashconf->rpcpassword = value;
hushconf->rpcpassword = value;
}
if (name == "rpcport") {
zcashconf->port = value;
hushconf->port = value;
}
if (name == "daemon" && value == "1") {
zcashconf->zcashDaemon = true;
hushconf->hushDaemon = true;
}
if (name == "proxy") {
zcashconf->proxy = value;
hushconf->proxy = value;
}
if (name == "consolidation") {
zcashconf->consolidation = value;
hushconf->consolidation = value;
}
if (name == "deletetx") {
zcashconf->deletetx = value;
hushconf->deletetx = value;
}
if (name == "zindex") {
zcashconf->zindex = value;
hushconf->zindex = value;
}
if (name == "testnet" &&
value == "1" &&
zcashconf->port.isEmpty()) {
zcashconf->port = "18232";
hushconf->port.isEmpty()) {
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 (zcashconf->port.isEmpty()) zcashconf->port = "18031";
if (hushconf->port.isEmpty()) hushconf->port = "18031";
file.close();
// 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
#define CONNECTION_H
@ -8,9 +10,9 @@
class RPC;
enum ConnectionType {
DetectedConfExternalZcashD = 1,
DetectedConfExternalHushD = 1,
UISettingsZCashD,
InternalZcashD
InternalHushD
};
struct ConnectionConfig {
@ -18,9 +20,9 @@ struct ConnectionConfig {
QString port;
QString rpcuser;
QString rpcpassword;
bool usingZcashConf;
bool zcashDaemon;
QString zcashDir;
bool usingHushConf;
bool hushDaemon;
QString hushDir;
QString proxy;
QString consolidation;
QString deletetx;
@ -40,7 +42,7 @@ public:
void loadConnection();
private:
std::shared_ptr<ConnectionConfig> autoDetectZcashConf();
std::shared_ptr<ConnectionConfig> autoDetectHushConf();
std::shared_ptr<ConnectionConfig> loadFromSettings();
Connection* makeConnection(std::shared_ptr<ConnectionConfig> config);
@ -48,24 +50,24 @@ private:
void doAutoConnect(bool tryEzcashdStart = true);
void doManualConnect();
void createZcashConf();
QString locateZcashConfFile();
QString zcashConfWritableLocation();
void createHushConf();
QString locateHushConfFile();
QString hushConfWritableLocation();
QString zcashParamsDir();
bool verifyParams();
void downloadParams(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 showInformation(QString info, QString detail = "");
void doRPCSetConnection(Connection* conn);
std::shared_ptr<QProcess> ezcashd;
std::shared_ptr<QProcess> ehushd;
QDialog* d;
Ui_ConnectionDialog* connD;

8
src/createzcashconfdialog.ui

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

4
src/fillediconlabel.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "fillediconlabel.h"
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);
QLabel::setPixmap(p);
}
}

4
src/fillediconlabel.h

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

4
src/logger.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef LOGGER_H
#define LOGGER_H
@ -20,4 +22,4 @@ public slots:
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
// GPLv3
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include <singleapplication.h>
#include "precompiled.h"
#include "mainwindow.h"
#include "rpc.h"
#include "settings.h"
#include "version.h"
class SignalHandler
@ -224,7 +222,7 @@ public:
// If there was a payment URI on the command line, pay it
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
@ -232,7 +230,7 @@ public:
QString uri(msg);
// 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

293
src/mainwindow.cpp

@ -1,4 +1,4 @@
// Copyright 2019-2020 The Hush Developers
// Copyright 2019-2021 The Hush Developers
// Released under the GPLv3
#include "mainwindow.h"
#include "addressbook.h"
@ -22,7 +22,6 @@
#include "requestdialog.h"
#include "websockets.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
@ -48,16 +47,11 @@ MainWindow::MainWindow(QWidget *parent) :
// Settings editor
setupSettingsModal();
// Set up exit action
// Set up actions
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->actionDiscord, &QAction::triggered, this, &MainWindow::discord);
QObject::connect(ui->actionTelegram, &QAction::triggered, this, &MainWindow::telegram);
QObject::connect(ui->actionReportBug, &QAction::triggered, this, &MainWindow::reportbug);
QObject::connect(ui->actionWebsite, &QAction::triggered, this, &MainWindow::website);
// Set up check for updates action
@ -73,7 +67,7 @@ MainWindow::MainWindow(QWidget *parent) :
// Pay Hush URI
QObject::connect(ui->actionPay_URI, &QAction::triggered, [=] () {
payZcashURI();
payHushURI();
});
// Import Private Key
@ -109,7 +103,7 @@ MainWindow::MainWindow(QWidget *parent) :
about.setupUi(&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);
aboutDialog.exec();
@ -125,6 +119,7 @@ MainWindow::MainWindow(QWidget *parent) :
setupMarketTab();
//setupChatTab();
setupHushTab();
setupPeersTab();
rpc = new RPC(this);
qDebug() << "Created RPC";
@ -200,7 +195,7 @@ void MainWindow::closeEvent(QCloseEvent* event) {
s.sync();
// Let the RPC know to shut down any running service.
rpc->shutdownZcashd();
rpc->shutdownHushd();
// Bubble up
if (event)
@ -339,7 +334,7 @@ void MainWindow::setupSettingsModal() {
isUsingTor = !rpc->getConnection()->config->proxy.isEmpty();
}
settings.chkTor->setChecked(isUsingTor);
if (rpc->getEZcashD() == nullptr) {
if (rpc->getEHushD() == nullptr) {
settings.chkTor->setEnabled(false);
settings.lblTor->setEnabled(false);
QString tooltip = tr("Tor configuration is available only when running an embedded hushd.");
@ -351,8 +346,8 @@ void MainWindow::setupSettingsModal() {
bool isUsingConsolidation = false;
int size = 0;
QDir zcashdir(rpc->getConnection()->config->zcashDir);
QFile WalletSize(zcashdir.filePath("wallet.dat"));
QDir hushdir(rpc->getConnection()->config->hushDir);
QFile WalletSize(hushdir.filePath("wallet.dat"));
if (WalletSize.open(QIODevice::ReadOnly)){
size = WalletSize.size() / 1000000; //when file does open.
//QString size1 = QString::number(size) ;
@ -363,7 +358,7 @@ void MainWindow::setupSettingsModal() {
isUsingConsolidation = !rpc->getConnection()->config->consolidation.isEmpty() == true;
}
settings.chkConso->setChecked(isUsingConsolidation);
if (rpc->getEZcashD() == nullptr) {
if (rpc->getEHushD() == nullptr) {
settings.chkConso->setEnabled(false);
}
@ -374,7 +369,7 @@ void MainWindow::setupSettingsModal() {
isUsingDeletetx = !rpc->getConnection()->config->deletetx.isEmpty() == true;
}
settings.chkDeletetx->setChecked(isUsingDeletetx);
if (rpc->getEZcashD() == nullptr) {
if (rpc->getEHushD() == nullptr) {
settings.chkDeletetx->setEnabled(false);
}
@ -385,7 +380,7 @@ void MainWindow::setupSettingsModal() {
isUsingZindex = !rpc->getConnection()->config->zindex.isEmpty() == true;
}
settings.chkzindex->setChecked(isUsingZindex);
if (rpc->getEZcashD() == nullptr) {
if (rpc->getEHushD() == nullptr) {
settings.chkzindex->setEnabled(false);
}
@ -394,9 +389,9 @@ void MainWindow::setupSettingsModal() {
settings.port->setValidator(&validator);
// If values are coming from HUSH3.conf, then disable all the fields
auto zcashConfLocation = Settings::getInstance()->getZcashdConfLocation();
if (!zcashConfLocation.isEmpty()) {
settings.confMsg->setText("Settings are being read from \n" + zcashConfLocation);
auto hushConfLocation = Settings::getInstance()->getHushdConfLocation();
if (!hushConfLocation.isEmpty()) {
settings.confMsg->setText("Settings are being read from \n" + hushConfLocation);
settings.hostname->setEnabled(false);
settings.port->setEnabled(false);
settings.rpcuser->setEnabled(false);
@ -455,7 +450,7 @@ void MainWindow::setupSettingsModal() {
if (!isUsingTor && settings.chkTor->isChecked()) {
// 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";
QMessageBox::information(this, tr("Enable Tor"),
@ -465,7 +460,7 @@ void MainWindow::setupSettingsModal() {
if (isUsingTor && !settings.chkTor->isChecked()) {
// If "use tor" was previously checked and now is unchecked
Settings::removeFromZcashConf(zcashConfLocation, "proxy");
Settings::removeFromHushConf(hushConfLocation, "proxy");
rpc->getConnection()->config->proxy.clear();
QMessageBox::information(this, tr("Disable Tor"),
@ -473,7 +468,7 @@ void MainWindow::setupSettingsModal() {
QMessageBox::Ok);
}
if (zcashConfLocation.isEmpty()) {
if (hushConfLocation.isEmpty()) {
// Save settings
Settings::getInstance()->saveSettings(
settings.hostname->text(),
@ -496,55 +491,55 @@ void MainWindow::setupSettingsModal() {
bool showRestartInfo = false;
bool showReindexInfo = false;
if (settings.chkRescan->isChecked()) {
Settings::addToZcashConf(zcashConfLocation, "rescan=1");
Settings::addToHushConf(hushConfLocation, "rescan=1");
showRestartInfo = true;
}
if (settings.chkReindex->isChecked()) {
Settings::addToZcashConf(zcashConfLocation, "reindex=1");
Settings::addToHushConf(hushConfLocation, "reindex=1");
showRestartInfo = true;
}
if (!rpc->getConnection()->config->consolidation.isEmpty()==false) {
if (settings.chkConso->isChecked()) {
Settings::addToZcashConf(zcashConfLocation, "consolidation=1");
Settings::addToHushConf(hushConfLocation, "consolidation=1");
showRestartInfo = true;
}
}
if (!rpc->getConnection()->config->consolidation.isEmpty()) {
if (settings.chkConso->isChecked() == false) {
Settings::removeFromZcashConf(zcashConfLocation, "consolidation");
Settings::removeFromHushConf(hushConfLocation, "consolidation");
showRestartInfo = true;
}
}
if (!rpc->getConnection()->config->deletetx.isEmpty() == false) {
if (settings.chkDeletetx->isChecked()) {
Settings::addToZcashConf(zcashConfLocation, "deletetx=1");
Settings::addToHushConf(hushConfLocation, "deletetx=1");
showRestartInfo = true;
}
}
if (!rpc->getConnection()->config->deletetx.isEmpty()) {
if (settings.chkDeletetx->isChecked() == false) {
Settings::removeFromZcashConf(zcashConfLocation, "deletetx");
Settings::removeFromHushConf(hushConfLocation, "deletetx");
showRestartInfo = true;
}
}
if (!rpc->getConnection()->config->zindex.isEmpty() == false) {
if (settings.chkzindex->isChecked()) {
Settings::addToZcashConf(zcashConfLocation, "zindex=1");
Settings::addToZcashConf(zcashConfLocation, "reindex=1");
Settings::addToHushConf(hushConfLocation, "zindex=1");
Settings::addToHushConf(hushConfLocation, "reindex=1");
showReindexInfo = true;
}
}
if (!rpc->getConnection()->config->zindex.isEmpty()) {
if (settings.chkzindex->isChecked() == false) {
Settings::removeFromZcashConf(zcashConfLocation, "zindex");
Settings::addToZcashConf(zcashConfLocation, "reindex=1");
Settings::removeFromHushConf(hushConfLocation, "zindex");
Settings::addToHushConf(hushConfLocation, "reindex=1");
showReindexInfo = true;
}
}
@ -579,18 +574,18 @@ void MainWindow::addressBook() {
AddressBook::open(this);
}
void MainWindow::discord() {
QString url = "https://myhush.org/discord/";
void MainWindow::telegram() {
QString url = "https://hush.is/tg";
QDesktopServices::openUrl(QUrl(url));
}
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));
}
void MainWindow::website() {
QString url = "https://myhush.org";
QString url = "https://hush.is";
QDesktopServices::openUrl(QUrl(url));
}
@ -608,9 +603,7 @@ void MainWindow::donate() {
ui->tabWidget->setCurrentIndex(1);
}
/**
* Validate an address
*/
// Validate an address
void MainWindow::validateAddress() {
// Make sure everything is up and running
if (!getRPC() || !getRPC()->getConnection())
@ -699,7 +692,7 @@ void MainWindow::balancesReady() {
// process it.
if (!pendingURIPayment.isEmpty()) {
qDebug() << "Paying hush URI";
payZcashURI(pendingURIPayment);
payHushURI(pendingURIPayment);
pendingURIPayment = "";
}
@ -710,7 +703,7 @@ bool MainWindow::eventFilter(QObject *object, QEvent *event) {
if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event);
if (!fileEvent->url().isEmpty())
payZcashURI(fileEvent->url().toString());
payHushURI(fileEvent->url().toString());
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
// will prompt for one. If the myAddr is empty, then the default from address is used to send
// 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 (!uiPaymentsReady) {
qDebug() << "Payment UI not ready, waiting for UI to pay URI";
@ -844,15 +837,15 @@ void MainWindow::backupWalletDat() {
if (!rpc->getConnection())
return;
QDir zcashdir(rpc->getConnection()->config->zcashDir);
QDir hushdir(rpc->getConnection()->config->hushDir);
QString backupDefaultName = "hush-wallet-backup-" + QDateTime::currentDateTime().toString("yyyyMMdd") + ".dat";
if (Settings::getInstance()->isTestnet()) {
zcashdir.cd("testnet3");
hushdir.cd("testnet3");
backupDefaultName = "testnet-" + backupDefaultName;
}
QFile wallet(zcashdir.filePath("wallet.dat"));
QFile wallet(hushdir.filePath("wallet.dat"));
if (!wallet.exists()) {
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);
@ -1068,6 +1061,69 @@ void MainWindow::setupBalancesTab() {
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"), [=] () {
this->exportKeys(addr);
});
@ -1122,6 +1178,7 @@ void MainWindow::setupBalancesTab() {
QDesktopServices::openUrl(QUrl(url));
});
//TODO: should this be kept?
menu.addAction(tr("Convert Address"), [=] () {
QString url;
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() {
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() {

12
src/mainwindow.h

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

92
src/mainwindow.ui

@ -915,6 +915,7 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>Transactions</string>
@ -932,6 +933,73 @@
</item>
</layout>
</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">
<attribute name="title">
<string>Market</string>
@ -1078,7 +1146,7 @@
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<layout class="QGridLayout" name="gridLayout_51">
<item row="5" column="0" colspan="3">
<widget class="QLabel" name="label_14">
<property name="text">
@ -1176,6 +1244,7 @@
</property>
</widget>
</item>
<!--
<item row="10" column="0">
<widget class="QLabel" name="kmdversionlabel">
<property name="text">
@ -1183,6 +1252,7 @@
</property>
</widget>
</item>
-->
<item row="10" column="2">
<widget class="QLabel" name="kmdversion">
<property name="text">
@ -1540,7 +1610,7 @@
<string>&amp;Help</string>
</property>
<addaction name="actionDonate"/>
<addaction name="actionDiscord"/>
<addaction name="actionTelegram"/>
<addaction name="actionWebsite"/>
<addaction name="actionCheck_for_Updates"/>
<addaction name="actionReportBug"/>
@ -1563,8 +1633,8 @@
</widget>
<addaction name="menuFile"/>
<addaction name="menu_Edit"/>
<addaction name="menuHelp"/>
<addaction name="menuApps"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionExit">
@ -1579,7 +1649,7 @@
</action>
<action name="actionReportBug">
<property name="text">
<string>&amp;Report a bug on Github</string>
<string>&amp;Report a bug</string>
</property>
</action>
<action name="actionSettings">
@ -1595,9 +1665,9 @@
<string>&amp;Send Duke Feedback</string>
</property>
</action>
<action name="actionDiscord">
<action name="actionTelegram">
<property name="text">
<string>&amp;Hush Discord</string>
<string>&amp;Hush Telegram</string>
</property>
</action>
<action name="actionWebsite">
@ -1607,15 +1677,7 @@
</action>
<action name="actionCheck_for_Updates">
<property name="text">
<string>Check github.com 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>
<string>Check git.hush.is for &amp;updates</string>
</property>
</action>
<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"
MemoEdit::MemoEdit(QWidget* parent) : QPlainTextEdit(parent) {
@ -49,4 +51,4 @@ void MemoEdit::includeReplyTo(QString addr) {
return;
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
#define MEMOEDIT_H
@ -20,4 +22,4 @@ private:
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 "ui_mobileappconnector.h"

2
src/mobileappconnector.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef 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
/* 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"
QRCodeLabel::QRCodeLabel(QWidget *parent) :
@ -54,4 +56,4 @@ QPixmap QRCodeLabel::scaledPixmap() const {
void QRCodeLabel::setQrcodeString(QString stra) {
str = stra;
QLabel::setPixmap(scaledPixmap());
}
}

2
src/qrcodelabel.h

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

4
src/recurring.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef RECURRING_H
#define RECURRING_H
@ -33,4 +35,4 @@ public:
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 "ui_requestdialog.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."));
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
// 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
#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
#include "rpc.h"
#include "addressbook.h"
#include "settings.h"
#include "senttxstore.h"
#include "version.h"
#include "websockets.h"
RPC::RPC(MainWindow* main) {
auto cl = new ConnectionLoader(main, this);
@ -16,7 +14,7 @@ RPC::RPC(MainWindow* main) {
QTimer::singleShot(1, [=]() { cl->loadConnection(); });
this->main = main;
this->ui = main->ui;
this->ui = main->ui;
// Setup balances table model
balancesTableModel = new BalancesTableModel(main->ui->balancesTable);
@ -27,12 +25,24 @@ RPC::RPC(MainWindow* main) {
main->ui->transactionsTable->setModel(transactionsTableModel);
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
priceTimer = new QTimer(main);
QObject::connect(priceTimer, &QTimer::timeout, [=]() {
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
timer = new QTimer(main);
@ -48,8 +58,9 @@ RPC::RPC(MainWindow* main) {
//qDebug() << "Watching tx status";
watchTxStatus();
});
// Start at every 10s. When an operation is pending, this will change to every second
txTimer->start(Settings::updateSpeed);
qDebug() << __func__ << "Done settings up all timers";
usedAddresses = new QMap<QString, bool>();
}
@ -60,6 +71,8 @@ RPC::~RPC() {
delete transactionsTableModel;
delete balancesTableModel;
delete peersTableModel;
delete bannedPeersTableModel;
delete utxos;
delete allBalances;
@ -70,12 +83,8 @@ RPC::~RPC() {
delete conn;
}
void RPC::setEZcashd(std::shared_ptr<QProcess> p) {
ezcashd = p;
if (ezcashd && ui->tabWidget->widget(4) == nullptr) {
ui->tabWidget->addTab(main->zcashdtab, "zcashd");
}
void RPC::setEHushd(std::shared_ptr<QProcess> p) {
ehushd = p;
}
// 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.");
// See if we need to remove the reindex/rescan flags from the zcash.conf file
auto zcashConfLocation = Settings::getInstance()->getZcashdConfLocation();
Settings::removeFromZcashConf(zcashConfLocation, "rescan");
Settings::removeFromZcashConf(zcashConfLocation, "reindex");
// See if we need to remove the reindex/rescan flags from the conf file
auto hushConfLocation = Settings::getInstance()->getHushdConfLocation();
Settings::removeFromHushConf(hushConfLocation, "rescan");
Settings::removeFromHushConf(hushConfLocation, "reindex");
// Refresh the UI
refreshPrice();
checkForUpdate();
//checkForUpdate();
// Force update, because this might be coming from a settings update
// where we need to immediately refresh
@ -241,11 +250,57 @@ void RPC::getBalance(const std::function<void(QJsonValue)>& 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) {
QString method = "listtransactions";
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,
const std::function<void(QString)>& err) {
QJsonObject payload = {
@ -572,21 +627,21 @@ void RPC::getInfoThenRefresh(bool force) {
int notarized = reply["notarized"].toInt();
int protocolversion = reply["protocolversion"].toInt();
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];
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 ntztxid = reply["notarizedtxid"].toString();
QString kmdver = reply["KMDversion"].toString();
Settings::getInstance()->setZcashdVersion(version);
Settings::getInstance()->setHushdVersion(version);
ui->longestchain->setText(QString::number(longestchain));
ui->notarizedhashvalue->setText( ntzhash );
ui->notarizedtxidvalue->setText( ntztxid );
ui->lagvalue->setText( QString::number(lag) );
ui->version->setText( QString::number(version) );
ui->kmdversion->setText( kmdver );
ui->protocolversion->setText( QString::number(protocolversion) );
ui->p2pport->setText( QString::number(p2pport) );
ui->rpcport->setText( QString::number(rpcport) );
@ -597,6 +652,7 @@ void RPC::getInfoThenRefresh(bool force) {
lastBlock = curBlock;
refreshBalances();
refreshPeers();
refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans()
refreshTransactions();
}
@ -621,7 +677,8 @@ void RPC::getInfoThenRefresh(bool force) {
conn->doRPCIgnoreError(makePayload(method), [=](const QJsonValue& reply) {
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
@ -707,7 +764,7 @@ void RPC::getInfoThenRefresh(bool force) {
else {
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()) {
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() {
if (conn == nullptr)
return noConnection();
@ -1025,12 +1152,15 @@ void RPC::watchTxStatus() {
}
void RPC::checkForUpdate(bool silent) {
// Disable update checks for now
// TODO: Use Gitea API
return;
qDebug() << "checking for updates";
if (conn == nullptr)
return noConnection();
QUrl cmcURL("https://api.github.com/repos/MyHush/SilentDragon/releases");
QUrl cmcURL("https://git.hush.is/hush/SilentDragon/releases");
QNetworkRequest req;
req.setUrl(cmcURL);
@ -1074,7 +1204,7 @@ void RPC::checkForUpdate(bool silent) {
.arg(currentVersion.toString()),
QMessageBox::Yes, QMessageBox::Cancel);
if (ans == QMessageBox::Yes) {
QDesktopServices::openUrl(QUrl("https://github.com/MyHush/SilentDragon/releases"));
QDesktopServices::openUrl(QUrl("https://git.hush.is/hush/SilentDragon/releases"));
} else {
// If the user selects cancel, don't bother them again for this version
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
if (ezcashd == nullptr || ezcashd->processId() == 0 || conn == nullptr) {
if (ehushd == nullptr || ehushd->processId() == 0 || conn == nullptr) {
// No hushd running internally, just return
return;
}
@ -1247,10 +1377,10 @@ void RPC::shutdownZcashd() {
QObject::connect(&waiter, &QTimer::timeout, [&] () {
waitCount++;
if ((ezcashd->atEnd() && ezcashd->processId() == 0) ||
ezcashd->state() == QProcess::NotRunning ||
if ((ehushd->atEnd() && ehushd->processId() == 0) ||
ehushd->state() == QProcess::NotRunning ||
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";
waiter.stop();
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
#define RPCCLIENT_H
#include "precompiled.h"
#include "balancestablemodel.h"
#include "txtablemodel.h"
#include "peerstablemodel.h"
#include "bannedpeerstablemodel.h"
#include "ui_mainwindow.h"
#include "mainwindow.h"
#include "connection.h"
class Turnstile;
struct TransactionItem {
QString type;
qint64 datetime;
qint64 datetime;
QString address;
QString txid;
double amount;
@ -22,6 +23,29 @@ struct TransactionItem {
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 {
QString opid;
Tx tx;
@ -36,12 +60,13 @@ public:
~RPC();
void setConnection(Connection* c);
void setEZcashd(std::shared_ptr<QProcess> p);
const QProcess* getEZcashD() { return ezcashd.get(); }
void setEHushd(std::shared_ptr<QProcess> p);
const QProcess* getEHushD() { return ehushd.get(); }
void refresh(bool force = false);
void refreshAddresses();
void refreshPeers();
void checkForUpdate(bool silent = true);
void refreshPrice();
@ -54,12 +79,15 @@ public:
void fillTxJsonParams(QJsonArray& params, Tx tx);
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();
const QMap<QString, WatchedTx> getWatchingTxns() { return watchingOps; }
void addNewTxToWatch(const QString& newOpid, WatchedTx wtx);
const TxTableModel* getTransactionsModel() { return transactionsTableModel; }
const PeersTableModel* getPeersModel() { return peersTableModel; }
const QList<QString>* getAllZAddresses() { return zaddresses; }
const QList<QString>* getAllTAddresses() { return taddresses; }
const QList<UnspentOutput>* getUTXOs() { return utxos; }
@ -76,16 +104,15 @@ public:
void importTPrivKey(QString addr, bool rescan, const std::function<void(QJsonValue)>& cb);
void validateAddress(QString address, const std::function<void(QJsonValue)>& cb);
void shutdownZcashd();
void shutdownHushd();
void noConnection();
bool isEmbedded() { return ezcashd != nullptr; }
bool isEmbedded() { return ehushd != nullptr; }
QString getDefaultSaplingAddress();
QString getDefaultTAddress();
void getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>)>);
Turnstile* getTurnstile() { return turnstile; }
Connection* getConnection() { return conn; }
private:
@ -107,12 +134,13 @@ private:
void getTransparentUnspent (const std::function<void(QJsonValue)>& cb);
void getZUnspent (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 getTAddresses (const std::function<void(QJsonValue)>& cb);
Connection* conn = nullptr;
std::shared_ptr<QProcess> ezcashd = nullptr;
std::shared_ptr<QProcess> ehushd = nullptr;
QList<UnspentOutput>* utxos = nullptr;
QMap<QString, double>* allBalances = nullptr;
QMap<QString, bool>* usedAddresses = nullptr;
@ -122,6 +150,8 @@ private:
QMap<QString, WatchedTx> watchingOps;
TxTableModel* transactionsTableModel = nullptr;
PeersTableModel* peersTableModel = nullptr;
BannedPeersTableModel* bannedPeersTableModel = nullptr;
BalancesTableModel* balancesTableModel = nullptr;
QTimer* timer;
@ -130,7 +160,6 @@ private:
Ui::MainWindow* ui;
MainWindow* main;
Turnstile* turnstile;
// Current balance in the UI. If this number updates, then refresh the UI
QString currentBalance;

2
src/scripts/dotranslations.sh

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

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

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

20
src/scripts/make-deb.sh

@ -1,5 +1,5 @@
#!/bin/bash
# Copyright (c) 2019-2020 The Hush developers
# Copyright (c) 2019-2021 The Hush developers
# Thanks to Zecwallet for the original code
# Released under the GPLv3
@ -19,18 +19,18 @@ if [ -z $HUSH_DIR ]; then
exit 1;
fi
if [ ! -f $HUSH_DIR/komodod ]; then
echo "Couldn't find komodod in $HUSH_DIR . Please build komodod."
if [ ! -f $HUSH_DIR/hushd ]; then
echo "Couldn't find hushd in $HUSH_DIR . Please build hushd."
exit 1;
fi
if [ ! -f $HUSH_DIR/komodo-cli ]; then
echo "Couldn't find komodo-cli in $HUSH_DIR . Please build komodo-cli."
if [ ! -f $HUSH_DIR/hush-cli ]; then
echo "Couldn't find hush-cli in $HUSH_DIR . Please build hush-cli."
exit 1;
fi
if [ ! -f $HUSH_DIR/komodo-tx ]; then
echo "Couldn't find komodo-tx in $HUSH_DIR . Please build komodo-tx."
if [ ! -f $HUSH_DIR/hush-tx ]; then
echo "Couldn't find hush-tx in $HUSH_DIR . Please build hush-tx."
exit 1;
fi
@ -73,9 +73,6 @@ mkdir $DIR > /dev/null
strip silentdragon
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/hush-cli $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
cp silentdragon $debdir/usr/local/bin/
# TODO: how does this interact with hushd deb ?
cp $HUSH_DIR/artifacts/komodod $debdir/usr/local/bin/hush-komodod
cp $HUSH_DIR/artifacts/hushd $debdir/usr/local/bin/hushd
mkdir -p $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
# Copyright (c) 2020 The Hush developers
# Copyright (c) 2019-2021 The Hush developers
# Released under the GPLv3
echo "Let There Be Debian Packages"

2
src/scripts/mkmacdmg.sh

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

2
src/scripts/mkrelease.sh

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

2
src/scripts/signbinaries.sh

@ -1,4 +1,6 @@
#!/bin/bash
# Copyright (c) 2019-2021 The Hush developers
# Released under the GPLv3
# Accept the variables as command line arguments as well
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 "ui_mainwindow.h"
#include "addressbook.h"
@ -505,24 +506,14 @@ Tx MainWindow::createTxFromSendPage() {
if (Settings::getInstance()->getAllowCustomFees()) {
tx.fee = ui->minerFeeAmt->text().toDouble();
}
else {
} else {
tx.fee = Settings::getMinerFee();
}
if (Settings::getInstance()->getAutoShield() && sendChangeToSapling) {
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);
if (!isSapling) return false;
// Also check all the To addresses
for (auto t : tx.toAddrs) {
if (t.addr == i)
return false;
}
return true;
});
@ -776,9 +767,10 @@ QString MainWindow::doSendTxValidations(Tx tx) {
}
for (auto toAddr : tx.toAddrs) {
//TODO: diff errors for completely invalid vs transparent? Educate.
if (!Settings::isValidAddress(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
@ -788,7 +780,6 @@ QString MainWindow::doSendTxValidations(Tx tx) {
}
}
return QString();
}

2
src/senttxstore.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "senttxstore.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
#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
#include "mainwindow.h"
#include "settings.h"
@ -35,8 +35,8 @@ void Settings::setAllowFetchPrices(bool allow) {
Explorer Settings::getExplorer() {
// Load from the QT Settings.
QSettings s;
//TODO: make it easy for people to use other explorers like komodod.com
QString explorer = "https://explorer.myhush.org";
//TODO: make it easy for people to use other explorers
QString explorer = "https://explorer.hush.is";
auto txExplorerUrl = s.value("explorer/txExplorerUrl", explorer + "/tx/").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())
_confLocation = confLocation;
}
@ -131,12 +131,12 @@ bool Settings::isTAddress(QString addr) {
return addr.startsWith("R");
}
int Settings::getZcashdVersion() {
return _zcashdVersion;
int Settings::getHushdVersion() {
return _hushdVersion;
}
void Settings::setZcashdVersion(int version) {
_zcashdVersion = version;
void Settings::setHushdVersion(int version) {
_hushdVersion = version;
}
bool Settings::isSyncing() {
@ -329,7 +329,7 @@ QString Settings::getDonationAddr() {
return "zs1aq4xnrkjlnxx0zesqye7jz3dfrf3rjh7q5z6u8l6mwyqqaam3gx3j2fkqakp33v93yavq46j83q";
}
bool Settings::addToZcashConf(QString confLocation, QString line) {
bool Settings::addToHushConf(QString confLocation, QString line) {
QFile file(confLocation);
if (!file.open(QIODevice::ReadWrite | QIODevice::Append))
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())
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
#define SETTINGS_H
@ -53,8 +54,8 @@ public:
bool isSyncing();
void setSyncing(bool syncing);
int getZcashdVersion();
void setZcashdVersion(int version);
int getHushdVersion();
void setHushdVersion(int version);
void setUseEmbedded(bool r) { _useEmbedded = r; }
bool useEmbedded() { return _useEmbedded; }
@ -88,8 +89,8 @@ public:
QString get_currency_name();
void set_currency_name(QString currency_name);
void setUsingZcashConf(QString confLocation);
const QString& getZcashdConfLocation() { return _confLocation; }
void setUsingHushConf(QString confLocation);
const QString& getHushdConfLocation() { return _confLocation; }
void setHUSHPrice(double p) { hushPrice = p; }
void set_fiat_price(double p) { fiat_price = p; }
@ -135,8 +136,8 @@ public:
static bool isValidAddress(QString addr);
static bool addToZcashConf(QString confLocation, QString line);
static bool removeFromZcashConf(QString confLocation, QString option);
static bool addToHushConf(QString confLocation, QString line);
static bool removeFromHushConf(QString confLocation, QString option);
static const QString labelRegExp;
@ -157,7 +158,7 @@ private:
bool _isTestnet = false;
bool _isSyncing = false;
int _blockNumber = 0;
int _zcashdVersion = 0;
int _hushdVersion = 0;
bool _useEmbedded = false;
bool _headless = false;
int _peerConnections = 0;

12
src/settings.ui

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

2
src/txtablemodel.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#include "txtablemodel.h"
#include "settings.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
#define STRINGSTABLEMODEL_H

2
src/validateaddress.cpp

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

2
src/validateaddress.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef 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 "settings.h"

4
src/viewalladdresses.h

@ -1,3 +1,5 @@
// Copyright 2019-2021 The Hush developers
// Released under the GPLv3
#ifndef VIEWALLADDRESSES_H
#define VIEWALLADDRESSES_H
@ -21,4 +23,4 @@ private:
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 "rpc.h"
#include "settings.h"
#include "ui_mobileappconnector.h"
@ -28,7 +28,7 @@ WSServer::WSServer(quint16 port, bool debug, QObject *parent) :
m_mainWindow = (MainWindow *) parent;
if (m_pWebSocketServer->listen(QHostAddress::AnyIPv4, port)) {
if (m_debug)
qDebug() << "Echoserver listening on port" << port;
qDebug() << "SD WebSocketServer listening on port" << port;
connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
this, &WSServer::onNewConnection);
connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &WSServer::closed);
@ -37,7 +37,7 @@ WSServer::WSServer(quint16 port, bool debug, QObject *parent) :
WSServer::~WSServer()
{
qDebug() << "Closing websocket server";
qDebug() << "Closing WebsocketServer";
m_pWebSocketServer->close();
qDeleteAll(m_clients.begin(), m_clients.end());
qDebug() << "Deleted all websocket clients";
@ -45,7 +45,7 @@ WSServer::~WSServer()
void WSServer::onNewConnection()
{
qDebug() << "Websocket server: new connection";
qDebug() << "WebsocketServer: new connection";
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
connect(pSocket, &QWebSocket::textMessageReceived, this, &WSServer::processTextMessage);
@ -121,7 +121,9 @@ void ws_error() {
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
//m_webSocket->ignoreSslErrors();
@ -131,7 +133,7 @@ void WormholeClient::connect() {
qDebug() << "Wormhole::connect";
delete m_webSocket;
m_webSocket = new QWebSocket();
QUrl wormhole = QUrl("wss://wormhole.myhush.org:443");
QUrl wormhole = QUrl("wss://wormhole.hush.is:443");
if (m_webSocket) {
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
#define WEBSOCKETS_H
#include "precompiled.h"
#include "mainwindow.h"
#include "ui_mobileappconnector.h"
QT_FORWARD_DECLARE_CLASS(QWebSocketServer)
QT_FORWARD_DECLARE_CLASS(QWebSocket)
@ -172,6 +172,4 @@ private:
static AppDataModel* instance;
};
#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
# Copyright 2019-2020 The Hush Developers
# Copyright 2019-2021 The Hush Developers
# Released under the GPLv3
# This script will cross-compile windoze binaries, hopefully!

Loading…
Cancel
Save