Browse Source

merge manually

pull/25/head^2
Denio 5 years ago
parent
commit
1f1a93006c
  1. 8
      README.md
  2. 6
      lib/Cargo.lock
  3. 2
      lib/Cargo.toml
  4. 9
      lib/src/lib.rs
  5. 4
      res/Info.plist
  6. 2
      src/about.ui
  7. 8
      src/connection.cpp
  8. 6
      src/connection.h
  9. 2
      src/connection.ui
  10. 47
      src/controller.cpp
  11. 3
      src/controller.h
  12. 16
      src/liteinterface.cpp
  13. 4
      src/liteinterface.h
  14. 2
      src/main.cpp
  15. 49
      src/mainwindow.cpp
  16. 15
      src/mainwindow.ui
  17. 27
      src/scripts/dounifiedbuild.ps1
  18. 12
      src/scripts/mkmacdmg.sh
  19. 13
      src/scripts/mkwininstaller.ps1
  20. 2
      src/scripts/signbinaries.sh
  21. 17
      src/scripts/zec-qt-wallet.wxs
  22. 2
      src/sendtab.cpp
  23. 4
      src/settings.cpp
  24. 13
      src/settings.h
  25. 71
      src/settings.ui
  26. 17
      src/txtablemodel.cpp

8
README.md

@ -18,6 +18,14 @@ This means your IP address is known to these servers. Enable Tor setting in Sile
Go to the releases page and grab the latest installers or binary. https://github.com/MyHush/SilentDragonLite/releases Go to the releases page and grab the latest installers or binary. https://github.com/MyHush/SilentDragonLite/releases
### Note Management
SilentDragonLite does automatic note and utxo management, which means it doesn't allow you to manually select which address to send outgoing transactions from. It follows these principles:
* Defaults to sending shielded transactions, even if you're sending to a transparent address
* Sapling funds need at least 2 confirmations before they can be spent
* Can select funds from multiple shielded addresses in the same transaction
* Will automatically shield your transparent funds at the first opportunity
* When sending an outgoing transaction to a shielded address, SilentDragonLite can decide to use the transaction to additionally shield your transparent funds (i.e., send your transparent funds to your own shielded address in the same transaction)
## Compiling from source ## Compiling from source
* SilentDragonLite is written in C++ 14, and can be compiled with g++/clang++/visual c++. * SilentDragonLite 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). * It also depends on Qt5, which you can get from [here](https://www.qt.io/download).

6
lib/Cargo.lock

@ -1051,7 +1051,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"silentdragonlitelib 0.1.0 (git+https://github.com/MyHush/silentdragonlite-cli?rev=099ad194dac6ee51474b3637d357aca0665a8181)", "silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=df119fdfff128baca006647851fcc6a2a14b7f92)",
] ]
[[package]] [[package]]
@ -1467,7 +1467,7 @@ dependencies = [
[[package]] [[package]]
name = "silentdragonlitelib" name = "silentdragonlitelib"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/MyHush/silentdragonlite-cli?rev=099ad194dac6ee51474b3637d357aca0665a8181#099ad194dac6ee51474b3637d357aca0665a8181" source = "git+https://github.com/DenioD/silentdragonlite-cli?rev=df119fdfff128baca006647851fcc6a2a14b7f92#df119fdfff128baca006647851fcc6a2a14b7f92"
dependencies = [ dependencies = [
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bellman 0.1.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)", "bellman 0.1.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)",
@ -2481,7 +2481,7 @@ dependencies = [
"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2"
"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35"
"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
"checksum silentdragonlitelib 0.1.0 (git+https://github.com/MyHush/silentdragonlite-cli?rev=099ad194dac6ee51474b3637d357aca0665a8181)" = "<none>" "checksum silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=df119fdfff128baca006647851fcc6a2a14b7f92)" = "<none>"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
"checksum sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585232e78a4fc18133eef9946d3080befdf68b906c51b621531c37e91787fa2b" "checksum sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585232e78a4fc18133eef9946d3080befdf68b906c51b621531c37e91787fa2b"

2
lib/Cargo.toml

@ -11,4 +11,4 @@ crate-type = ["staticlib"]
[dependencies] [dependencies]
libc = "0.2.58" libc = "0.2.58"
lazy_static = "1.4.0" lazy_static = "1.4.0"
silentdragonlitelib = { git = "https://github.com/MyHush/silentdragonlite-cli", rev = "099ad194dac6ee51474b3637d357aca0665a8181" } silentdragonlitelib = { git = "https://github.com/DenioD/silentdragonlite-cli", rev = "df119fdfff128baca006647851fcc6a2a14b7f92" }

9
lib/src/lib.rs

@ -57,6 +57,9 @@ pub extern fn litelib_initialize_new(dangerous: bool, server: *const c_char) ->
} }
}; };
// Initialize logging
let _ = lightclient.init_logging();
let seed = match lightclient.do_seed_phrase() { let seed = match lightclient.do_seed_phrase() {
Ok(s) => s.dump(), Ok(s) => s.dump(),
Err(e) => { Err(e) => {
@ -105,6 +108,9 @@ pub extern fn litelib_initialize_new_from_phrase(dangerous: bool, server: *const
} }
}; };
// Initialize logging
let _ = lightclient.init_logging();
LIGHTCLIENT.lock().unwrap().replace(Some(Arc::new(lightclient))); LIGHTCLIENT.lock().unwrap().replace(Some(Arc::new(lightclient)));
let c_str = CString::new("OK").unwrap(); let c_str = CString::new("OK").unwrap();
@ -137,6 +143,9 @@ pub extern fn litelib_initialize_existing(dangerous: bool, server: *const c_char
} }
}; };
// Initialize logging
let _ = lightclient.init_logging();
LIGHTCLIENT.lock().unwrap().replace(Some(Arc::new(lightclient))); LIGHTCLIENT.lock().unwrap().replace(Some(Arc::new(lightclient)));
let c_str = CString::new("OK").unwrap(); let c_str = CString::new("OK").unwrap();

4
res/Info.plist

@ -9,7 +9,7 @@
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>logo.icns</string> <string>logo.icns</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.yourcompany.silentdragon</string> <string>com.yourcompany.SilentDragonLite</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
@ -39,4 +39,4 @@
<key>NSUIElement</key> <key>NSUIElement</key>
<true/> <true/>
</dict> </dict>
</plist> </plist>

2
src/about.ui

@ -17,7 +17,7 @@
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
<string notr="true">SilentDragon Lite</string> <string notr="true">SilentDragonLite</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>

8
src/connection.cpp

@ -42,14 +42,14 @@ void ConnectionLoader::doAutoConnect() {
qDebug() << "Doing autoconnect"; qDebug() << "Doing autoconnect";
auto config = std::shared_ptr<ConnectionConfig>(new ConnectionConfig()); auto config = std::shared_ptr<ConnectionConfig>(new ConnectionConfig());
config->dangerous = true; config->dangerous = false;
config->server = Settings::getInstance()->getSettings().server; config->server = Settings::getInstance()->getSettings().server;
// Initialize the library // Initialize the library
main->logger->write(QObject::tr("Attempting to initialize library with ") + config->server); main->logger->write(QObject::tr("Attempting to initialize library with ") + config->server);
// Check to see if there's an existing wallet // Check to see if there's an existing wallet
if (litelib_wallet_exists(Settings::getChainName().toStdString().c_str())) { if (litelib_wallet_exists(Settings::getDefaultChainName().toStdString().c_str())) {
main->logger->write(QObject::tr("Using existing wallet.")); main->logger->write(QObject::tr("Using existing wallet."));
char* resp = litelib_initialize_existing(config->dangerous, config->server.toStdString().c_str()); char* resp = litelib_initialize_existing(config->dangerous, config->server.toStdString().c_str());
QString response = litelib_process_response(resp); QString response = litelib_process_response(resp);
@ -68,9 +68,10 @@ void ConnectionLoader::doAutoConnect() {
auto me = this; auto me = this;
// After the lib is initialized, try to do get info // After the lib is initialized, try to do get info
connection->doRPC("info", "", [=](auto) { connection->doRPC("info", "", [=](auto reply) {
// If success, set the connection // If success, set the connection
main->logger->write("Connection is online."); main->logger->write("Connection is online.");
connection->setInfo(reply);
isSyncing = new QAtomicInteger<bool>(); isSyncing = new QAtomicInteger<bool>();
isSyncing->store(true); isSyncing->store(true);
@ -138,7 +139,6 @@ Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> c
// Update the UI with the status // Update the UI with the status
void ConnectionLoader::showInformation(QString info, QString detail) { void ConnectionLoader::showInformation(QString info, QString detail) {
qDebug() << "Showing info " << info << ":" << detail;
connD->status->setText(info); connD->status->setText(info);
connD->statusDetail->setText(detail); connD->statusDetail->setText(detail);

6
src/connection.h

@ -123,8 +123,12 @@ public:
void showTxError(const QString& error); void showTxError(const QString& error);
json getInfo() { return serverInfo; }
void setInfo(const json& info) { serverInfo = info; }
private: private:
bool shutdownInProgress = false; bool shutdownInProgress = false;
json serverInfo;
}; };
#endif #endif

2
src/connection.ui

@ -14,7 +14,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>silentdragon</string> <string>SilentDragonLite</string>
</property> </property>
<property name="modal"> <property name="modal">
<bool>true</bool> <bool>true</bool>

47
src/controller.cpp

@ -135,34 +135,44 @@ void Controller::refresh(bool force) {
getInfoThenRefresh(force); getInfoThenRefresh(force);
} }
void Controller::processInfo(const json& info) {
// Testnet?
QString chainName;
if (!info["chain_name"].is_null()) {
chainName = QString::fromStdString(info["chain_name"].get<json::string_t>());
Settings::getInstance()->setTestnet(chainName == "test");
};
QString version = QString::fromStdString(info["version"].get<json::string_t>());
Settings::getInstance()->sethushdVersion(version);
// Recurring pamynets are testnet only
if (!Settings::getInstance()->isTestnet())
main->disableRecurring();
}
void Controller::getInfoThenRefresh(bool force) { void Controller::getInfoThenRefresh(bool force) {
if (!zrpc->haveConnection()) if (!zrpc->haveConnection())
return noConnection(); return noConnection();
static bool prevCallSucceeded = false; static bool prevCallSucceeded = false;
zrpc->fetchInfo([=] (const json& reply) { zrpc->fetchLatestBlock([=] (const json& reply) {
prevCallSucceeded = true; prevCallSucceeded = true;
// Testnet? int curBlock = reply["height"].get<json::number_integer_t>();
QString chainName;
if (!reply["chain_name"].is_null()) {
chainName = QString::fromStdString(reply["chain_name"].get<json::string_t>());
Settings::getInstance()->setTestnet(chainName == "test");
};
// Recurring pamynets are testnet only
if (!Settings::getInstance()->isTestnet())
main->disableRecurring();
int curBlock = reply["latest_block_height"].get<json::number_integer_t>();
bool doUpdate = force || (model->getLatestBlock() != curBlock); bool doUpdate = force || (model->getLatestBlock() != curBlock);
model->setLatestBlock(curBlock); model->setLatestBlock(curBlock);
ui->blockHeight->setText(QString::number(curBlock)); ui->blockHeight->setText(QString::number(curBlock));
main->logger->write(QString("Refresh. curblock ") % QString::number(curBlock) % ", update=" % (doUpdate ? "true" : "false") );
// Connected, so display checkmark. // Connected, so display checkmark.
auto tooltip = Settings::getInstance()->getSettings().server + "\n" + QString::fromStdString(reply.dump()); auto tooltip = Settings::getInstance()->getSettings().server + "\n" +
QString::fromStdString(zrpc->getConnection()->getInfo().dump());
QIcon i(":/icons/res/connected.gif"); QIcon i(":/icons/res/connected.gif");
QString chainName = Settings::getInstance()->isTestnet() ? "test" : "main";
main->statusLabel->setText(chainName + "(" + QString::number(curBlock) + ")"); main->statusLabel->setText(chainName + "(" + QString::number(curBlock) + ")");
// use currency ComboBox as input // use currency ComboBox as input
@ -196,13 +206,6 @@ void Controller::getInfoThenRefresh(bool force) {
main->statusLabel->setToolTip(tooltip); main->statusLabel->setToolTip(tooltip);
main->statusIcon->setPixmap(i.pixmap(16, 16)); main->statusIcon->setPixmap(i.pixmap(16, 16));
main->statusIcon->setToolTip(tooltip); main->statusIcon->setToolTip(tooltip);
//int version = reply["version"].get<json::string_t>();
int version = 1;
Settings::getInstance()->sethushdVersion(version);
ui->Version->setText(QString::fromStdString(reply["version"].get<json::string_t>()));
ui->Vendor->setText(QString::fromStdString(reply["vendor"].get<json::string_t>()));
// See if recurring payments needs anything // See if recurring payments needs anything
Recurring::getInstance()->processPending(main); Recurring::getInstance()->processPending(main);

3
src/controller.h

@ -72,6 +72,8 @@ public:
void saveWallet(const std::function<void(json)>& cb) { zrpc->saveWallet(cb); } void saveWallet(const std::function<void(json)>& cb) { zrpc->saveWallet(cb); }
void clearWallet(const std::function<void(json)>& cb) { zrpc->clearWallet(cb); }
void createNewZaddr(bool sapling, const std::function<void(json)>& cb) { void createNewZaddr(bool sapling, const std::function<void(json)>& cb) {
unlockIfEncrypted([=] () { unlockIfEncrypted([=] () {
zrpc->createNewZaddr(sapling, cb); zrpc->createNewZaddr(sapling, cb);
@ -117,6 +119,7 @@ public:
QString getDefaultTAddress(); QString getDefaultTAddress();
private: private:
void processInfo(const json&);
void refreshBalances(); void refreshBalances();
void refreshTransactions(); void refreshTransactions();

16
src/liteinterface.cpp

@ -84,6 +84,13 @@ void LiteInterface::saveWallet(const std::function<void(json)>& cb) {
conn->doRPCWithDefaultErrorHandling("save", "", cb); conn->doRPCWithDefaultErrorHandling("save", "", cb);
} }
void LiteInterface::clearWallet(const std::function<void(json)>& cb) {
if (conn == nullptr)
return;
conn->doRPCWithDefaultErrorHandling("clear", "", cb);
}
void LiteInterface::unlockWallet(QString password, const std::function<void(json)>& cb) { void LiteInterface::unlockWallet(QString password, const std::function<void(json)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
@ -130,6 +137,15 @@ void LiteInterface::fetchInfo(const std::function<void(json)>& cb,
conn->doRPC("info", "", cb, err); conn->doRPC("info", "", cb, err);
} }
void LiteInterface::fetchLatestBlock(const std::function<void(json)>& cb,
const std::function<void(QString)>& err) {
if (conn == nullptr)
return;
conn->doRPC("height", "", cb, err);
}
/** /**
* Method to get all the private keys for both z and t addresses. It will make 2 batch calls, * Method to get all the private keys for both z and t addresses. It will make 2 batch calls,
* combine the result, and call the callback with a single list containing both the t-addr and z-addr * combine the result, and call the callback with a single list containing both the t-addr and z-addr

4
src/liteinterface.h

@ -44,6 +44,9 @@ public:
void fetchInfo(const std::function<void(json)>& cb, void fetchInfo(const std::function<void(json)>& cb,
const std::function<void(QString)>& err); const std::function<void(QString)>& err);
void fetchLatestBlock(const std::function<void(json)>& cb,
const std::function<void(QString)>& err);
void fetchBalance(const std::function<void(json)>& cb); void fetchBalance(const std::function<void(json)>& cb);
@ -56,6 +59,7 @@ public:
void fetchSeed(const std::function<void(json)>&); void fetchSeed(const std::function<void(json)>&);
void saveWallet(const std::function<void(json)>& cb); void saveWallet(const std::function<void(json)>& cb);
void clearWallet(const std::function<void(json)>& cb);
void fetchWalletEncryptionStatus(const std::function<void(json)>& cb); void fetchWalletEncryptionStatus(const std::function<void(json)>& cb);
void encryptWallet(QString password, const std::function<void(json)>& cb); void encryptWallet(QString password, const std::function<void(json)>& cb);

2
src/main.cpp

@ -205,7 +205,7 @@ public:
w = new MainWindow(); w = new MainWindow();
w->setWindowTitle("SilentDragon Lite v" + QString(APP_VERSION)); w->setWindowTitle("SilentDragonLite v" + QString(APP_VERSION));
// If there was a payment URI on the command line, pay it // If there was a payment URI on the command line, pay it
if (parser.positionalArguments().length() > 0) { if (parser.positionalArguments().length() > 0) {

49
src/mainwindow.cpp

@ -16,6 +16,7 @@
#include "connection.h" #include "connection.h"
#include "requestdialog.h" #include "requestdialog.h"
#include "websockets.h" #include "websockets.h"
#include <QRegularExpression>
using json = nlohmann::json; using json = nlohmann::json;
@ -108,6 +109,20 @@ MainWindow::MainWindow(QWidget *parent) :
AppDataServer::getInstance()->connectAppDialog(this); AppDataServer::getInstance()->connectAppDialog(this);
}); });
// Rescan
QObject::connect(ui->actionRescan, &QAction::triggered, [=]() {
// To rescan, we clear the wallet state, and then reload the connection
// This will start a sync, and show the scanning status.
getRPC()->clearWallet([=] (auto) {
// Save the wallet
getRPC()->saveWallet([=] (auto) {
// Then reload the connection. The ConnectionLoader deletes itself.
auto cl = new ConnectionLoader(this, rpc);
cl->loadConnection();
});
});
});
// Address Book // Address Book
QObject::connect(ui->action_Address_Book, &QAction::triggered, this, &MainWindow::addressBook); QObject::connect(ui->action_Address_Book, &QAction::triggered, this, &MainWindow::addressBook);
@ -438,19 +453,17 @@ void MainWindow::setupSettingsModal() {
// Fetch prices // Fetch prices
settings.chkFetchPrices->setChecked(Settings::getInstance()->getAllowFetchPrices()); settings.chkFetchPrices->setChecked(Settings::getInstance()->getAllowFetchPrices());
// List of default servers
settings.cmbServer->addItem("https://hush-lightwallet.de:443");
settings.cmbServer->addItem("https://hush-lightwallet.de:443");
// Load current values into the dialog // Load current values into the dialog
auto conf = Settings::getInstance()->getSettings(); auto conf = Settings::getInstance()->getSettings();
settings.txtServer->setText(conf.server); settings.cmbServer->setCurrentText(conf.server);
// Connection tab by default // Connection tab by default
settings.tabWidget->setCurrentIndex(0); settings.tabWidget->setCurrentIndex(0);
// Enable the troubleshooting options only if using embedded hushd
if (!rpc->isEmbedded()) {
settings.chkRescan->setEnabled(false);
settings.chkRescan->setToolTip(tr("You're using an external hushd. Please restart hushd with -rescan"));
}
if (settingsDialog.exec() == QDialog::Accepted) { if (settingsDialog.exec() == QDialog::Accepted) {
// Check for updates // Check for updates
Settings::getInstance()->setCheckForUpdates(settings.chkCheckUpdates->isChecked()); Settings::getInstance()->setCheckForUpdates(settings.chkCheckUpdates->isChecked());
@ -459,14 +472,22 @@ void MainWindow::setupSettingsModal() {
Settings::getInstance()->setAllowFetchPrices(settings.chkFetchPrices->isChecked()); Settings::getInstance()->setAllowFetchPrices(settings.chkFetchPrices->isChecked());
// Save the server // Save the server
Settings::getInstance()->saveSettings(settings.txtServer->text().trimmed()); bool reloadConnection = false;
if (conf.server != settings.cmbServer->currentText().trimmed()) {
reloadConnection = true;
}
Settings::getInstance()->saveSettings(settings.cmbServer->currentText().trimmed());
if (false /* connection needs reloading?*/) { if (reloadConnection) {
// Save settings // Save settings
Settings::getInstance()->saveSettings(settings.txtServer->text()); Settings::getInstance()->saveSettings(settings.cmbServer->currentText());
auto cl = new ConnectionLoader(this, rpc); // Save the wallet
cl->loadConnection(); getRPC()->saveWallet([=] (auto) {
// Then reload the connection. The ConnectionLoader deletes itself.
auto cl = new ConnectionLoader(this, rpc);
cl->loadConnection();
});
} }
} }
}); });
@ -474,7 +495,7 @@ void MainWindow::setupSettingsModal() {
void MainWindow::addressBook() { void MainWindow::addressBook() {
// Check to see if there is a target. // Check to see if there is a target.
QRegExp re("Address[0-9]+", Qt::CaseInsensitive); QRegularExpression re("Address[0-9]+", QRegularExpression::CaseInsensitiveOption);
for (auto target: ui->sendToWidgets->findChildren<QLineEdit *>(re)) { for (auto target: ui->sendToWidgets->findChildren<QLineEdit *>(re)) {
if (target->hasFocus()) { if (target->hasFocus()) {
AddressBook::open(this, target); AddressBook::open(this, target);

15
src/mainwindow.ui

@ -11,7 +11,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>silentdragon</string> <string>SilentDragonLite</string>
</property> </property>
<property name="windowIcon"> <property name="windowIcon">
<iconset resource="../application.qrc"> <iconset resource="../application.qrc">
@ -399,8 +399,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1226</width> <width>1162</width>
<height>504</height> <height>344</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="sendToLayout"> <layout class="QVBoxLayout" name="sendToLayout">
@ -1095,7 +1095,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1274</width> <width>1274</width>
<height>22</height> <height>39</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">
@ -1139,6 +1139,8 @@
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionEncrypt_Wallet"/> <addaction name="actionEncrypt_Wallet"/>
<addaction name="actionRemove_Wallet_Encryption"/> <addaction name="actionRemove_Wallet_Encryption"/>
<addaction name="separator"/>
<addaction name="actionRescan"/>
</widget> </widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
<addaction name="menu_Edit"/> <addaction name="menu_Edit"/>
@ -1245,6 +1247,11 @@
<string>Remove Wallet Encryption</string> <string>Remove Wallet Encryption</string>
</property> </property>
</action> </action>
<action name="actionRescan">
<property name="text">
<string>Rescan</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>

27
src/scripts/dounifiedbuild.ps1

@ -2,16 +2,17 @@
param ( param (
[Parameter(Mandatory=$true)][string]$version, [Parameter(Mandatory=$true)][string]$version,
[Parameter(Mandatory=$true)][string]$prev, [Parameter(Mandatory=$true)][string]$prev,
[Parameter(Mandatory=$true)][string]$certificate,
[Parameter(Mandatory=$true)][string]$server, [Parameter(Mandatory=$true)][string]$server,
[Parameter(Mandatory=$true)][string]$winserver [Parameter(Mandatory=$true)][string]$winserver
) )
Write-Host "[Initializing]" Write-Host "[Initializing]"
Remove-Item -Force -ErrorAction Ignore ./artifacts/linux-binaries-silentdragon-v$version.tar.gz Remove-Item -Force -ErrorAction Ignore ./artifacts/linux-binaries-SilentDragonLite-v$version.tar.gz
Remove-Item -Force -ErrorAction Ignore ./artifacts/linux-deb-silentdragon-v$version.deb Remove-Item -Force -ErrorAction Ignore ./artifacts/linux-deb-SilentDragonLite-v$version.deb
Remove-Item -Force -ErrorAction Ignore ./artifacts/Windows-binaries-silentdragon-v$version.zip Remove-Item -Force -ErrorAction Ignore ./artifacts/Windows-binaries-SilentDragonLite-v$version.zip
Remove-Item -Force -ErrorAction Ignore ./artifacts/Windows-installer-silentdragon-v$version.msi Remove-Item -Force -ErrorAction Ignore ./artifacts/Windows-installer-SilentDragonLite-v$version.msi
Remove-Item -Force -ErrorAction Ignore ./artifacts/macOS-silentdragon-v$version.dmg Remove-Item -Force -ErrorAction Ignore ./artifacts/macOS-SilentDragonLite-v$version.dmg
Remove-Item -Force -ErrorAction Ignore ./artifacts/signatures-v$version.tar.gz Remove-Item -Force -ErrorAction Ignore ./artifacts/signatures-v$version.tar.gz
@ -27,7 +28,7 @@ Write-Host ""
Write-Host "[Building on Mac]" Write-Host "[Building on Mac]"
bash src/scripts/mkmacdmg.sh --qt_path ~/Qt/5.11.1/clang_64/ --version $version --hush_path ~/prod/hush bash src/scripts/mkmacdmg.sh --qt_path ~/Qt/5.11.1/clang_64/ --version $version --certificate "$certificate"
if (! $?) { if (! $?) {
Write-Output "[Error]" Write-Output "[Error]"
exit 1; exit 1;
@ -37,9 +38,11 @@ Write-Host ""
Write-Host "[Building Linux + Windows]" Write-Host "[Building Linux + Windows]"
Write-Host -NoNewline "Copying files.........." Write-Host -NoNewline "Copying files.........."
# Cleanup some local files to aid copying
rm -rf lib/target/
ssh $server "rm -rf /tmp/zqwbuild" ssh $server "rm -rf /tmp/zqwbuild"
ssh $server "mkdir /tmp/zqwbuild" ssh $server "mkdir /tmp/zqwbuild"
scp -r src/ singleapplication/ res/ ./silentdragonlite.pro ./application.qrc ./LICENSE ./README.md ${server}:/tmp/zqwbuild/ | Out-Null scp -r src/ singleapplication/ res/ ./silentdragon-lite.pro ./application.qrc ./LICENSE ./README.md ${server}:/tmp/zqwbuild/ | Out-Null
ssh $server "dos2unix -q /tmp/zqwbuild/src/scripts/mkrelease.sh" | Out-Null ssh $server "dos2unix -q /tmp/zqwbuild/src/scripts/mkrelease.sh" | Out-Null
ssh $server "dos2unix -q /tmp/zqwbuild/src/version.h" ssh $server "dos2unix -q /tmp/zqwbuild/src/version.h"
Write-Host "[OK]" Write-Host "[OK]"
@ -86,11 +89,11 @@ Write-Host "[OK]"
# Finally, test to make sure all files exist # Finally, test to make sure all files exist
Write-Host -NoNewline "Checking Build........." Write-Host -NoNewline "Checking Build........."
if (! (Test-Path ./artifacts/linux-binaries-silentdragon-v$version.tar.gz) -or if (! (Test-Path ./artifacts/linux-binaries-SilentDragonLite-v$version.tar.gz) -or
! (Test-Path ./artifacts/linux-deb-silentdragon-v$version.deb) -or ! (Test-Path ./artifacts/linux-deb-SilentDragonLite-v$version.deb) -or
! (Test-Path ./artifacts/Windows-binaries-silentdragon-v$version.zip) -or ! (Test-Path ./artifacts/Windows-binaries-SilentDragonLite-v$version.zip) -or
! (Test-Path ./artifacts/macOS-silentdragon-v$version.dmg) -or ! (Test-Path ./artifacts/macOS-SilentDragonLite-v$version.dmg) -or
! (Test-Path ./artifacts/Windows-installer-silentdragon-v$version.msi) ) { ! (Test-Path ./artifacts/Windows-installer-SilentDragonLite-v$version.msi) ) {
Write-Host "[Error]" Write-Host "[Error]"
exit 1; exit 1;
} }

12
src/scripts/mkmacdmg.sh

@ -12,8 +12,8 @@ case $key in
shift # past argument shift # past argument
shift # past value shift # past value
;; ;;
-z|--hush_path) -c|--certificate)
hush_DIR="$2" CERTIFICATE="$2"
shift # past argument shift # past argument
shift # past value shift # past value
;; ;;
@ -35,6 +35,11 @@ if [ -z $QT_PATH ]; then
exit 1; exit 1;
fi fi
if [ -z $CERTIFICATE ]; then
echo "CERTIFICATE is not set. Please set it the name of the MacOS developer certificate to sign the binary with";
exit 1;
fi
if [ -z $APP_VERSION ]; then if [ -z $APP_VERSION ]; then
echo "APP_VERSION is not set. Please set it to the current release version of the app"; echo "APP_VERSION is not set. Please set it to the current release version of the app";
exit 1; exit 1;
@ -70,7 +75,8 @@ echo -n "Deploying.............."
mkdir artifacts >/dev/null 2>&1 mkdir artifacts >/dev/null 2>&1
rm -f artifcats/Silentdragonlite.dmg >/dev/null 2>&1 rm -f artifcats/Silentdragonlite.dmg >/dev/null 2>&1
rm -f artifacts/rw* >/dev/null 2>&1 rm -f artifacts/rw* >/dev/null 2>&1
$QT_PATH/bin/macdeployqt Silentdragonlite.app $QT_PATH/bin/macdeployqt SilentDragonLite.app
codesign --deep --force --verify --verbose -s "$CERTIFICATE" --options runtime --timestamp SilentDragonLite.app/
echo "[OK]" echo "[OK]"

13
src/scripts/mkwininstaller.ps1

@ -2,16 +2,13 @@ param (
[Parameter(Mandatory=$true)][string]$version [Parameter(Mandatory=$true)][string]$version
) )
$target="silentdragon-v$version" $target="SilentDragonLite-v$version"
Remove-Item -Path release/wininstaller -Recurse -ErrorAction Ignore | Out-Null Remove-Item -Path release/wininstaller -Recurse -ErrorAction Ignore | Out-Null
New-Item release/wininstaller -itemtype directory | Out-Null New-Item release/wininstaller -itemtype directory | Out-Null
Copy-Item release/$target/silentdragon.exe release/wininstaller/ Copy-Item release/$target/SilentDragonLite.exe release/wininstaller/
Copy-Item release/$target/LICENSE release/wininstaller/ Copy-Item release/$target/LICENSE release/wininstaller/
Copy-Item release/$target/README.md release/wininstaller/
Copy-Item release/$target/hushd.exe release/wininstaller/
Copy-Item release/$target/hush-cli.exe release/wininstaller/
Get-Content src/scripts/silentdragonlite.wxs | ForEach-Object { $_ -replace "RELEASE_VERSION", "$version" } | Out-File -Encoding utf8 release/wininstaller/silentdragonlite.wxs Get-Content src/scripts/silentdragonlite.wxs | ForEach-Object { $_ -replace "RELEASE_VERSION", "$version" } | Out-File -Encoding utf8 release/wininstaller/silentdragonlite.wxs
@ -20,10 +17,10 @@ if (!$?) {
exit 1; exit 1;
} }
light.exe -ext WixUIExtension -cultures:en-us release/wininstaller/silentdragonlite.wixobj -out release/wininstaller/silentdragon.msi light.exe -ext WixUIExtension -cultures:en-us release/wininstaller/SilentDragonLite.wixobj -out release/wininstaller/SilentDragonLite.msi
if (!$?) { if (!$?) {
exit 1; exit 1;
} }
New-Item artifacts -itemtype directory -Force | Out-Null New-Item artifacts -itemtype directory -Force | Out-Null
Copy-Item release/wininstaller/silentdragon.msi ./artifacts/Windows-installer-$target.msi Copy-Item release/wininstaller/SilentDragonLite.msi ./artifacts/Windows-installer-$target.msi

2
src/scripts/signbinaries.sh

@ -35,7 +35,7 @@ rm -f signatures-v$APP_VERSION.tar.gz
# sha256sum the binaries # sha256sum the binaries
gsha256sum *$APP_VERSION* > sha256sum-v$APP_VERSION.txt gsha256sum *$APP_VERSION* > sha256sum-v$APP_VERSION.txt
for i in $( ls *silentdragon-v$APP_VERSION* sha256sum-v$APP_VERSION* ); do for i in $( ls *SilentDragonLite-v$APP_VERSION* sha256sum-v$APP_VERSION* ); do
echo "Signing" $i echo "Signing" $i
gpg --batch --output ../release/signatures/$i.sig --detach-sig $i gpg --batch --output ../release/signatures/$i.sig --detach-sig $i
done done

17
src/scripts/zec-qt-wallet.wxs

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="silentdragon vRELEASE_VERSION" Language="1033" Version="RELEASE_VERSION" Manufacturer="silentdragonlite-org" UpgradeCode="fb9bf166-b55f-46b5-a990-9189bdf64533"> <Product Id="*" Name="SilentDragonLite vRELEASE_VERSION" Language="1033" Version="RELEASE_VERSION" Manufacturer="silentdragonlite-org" UpgradeCode="fb9bf166-b55f-46b5-a990-9189bdf64533">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" /> <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." /> <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/> <MediaTemplate EmbedCab="yes"/>
<Icon Id="silentdragonlite.exe" SourceFile="res/icon.ico"/> <Icon Id="SilentDragonLite.exe" SourceFile="res/icon.ico"/>
<Property Id="ARPPRODUCTICON" Value="silentdragonlite.exe" /> <Property Id="ARPPRODUCTICON" Value="SilentDragonLite.exe" />
<Feature Id="ProductFeature" Title="silentdragonlite" Level="1"> <Feature Id="ProductFeature" Title="silentdragonlite" Level="1">
<ComponentGroupRef Id="ProductComponents" /> <ComponentGroupRef Id="ProductComponents" />
@ -55,24 +55,21 @@
<Fragment> <Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER"> <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="ProductComponent" Guid="0D210F5A-53E0-4E7E-CAAD-15A26995505E"> <Component Id="ProductComponent" Guid="0D210F5A-53E0-4E7E-CAAD-15A26995505E">
<File Source="silentdragon.exe" KeyPath="yes"> <File Source="SilentDragonLite.exe" KeyPath="yes">
<Shortcut Id="startMenuShotcut" Advertise="yes" Directory="ApplicationProgramsFolder" <Shortcut Id="startMenuShotcut" Advertise="yes" Directory="ApplicationProgramsFolder"
Name="silentdragon" WorkingDirectory="INSTALLFOLDER" Icon="silentdragonlite.exe" > Name="SilentDragonLite" WorkingDirectory="INSTALLFOLDER" Icon="SilentDragonLite.exe" >
</Shortcut> </Shortcut>
</File> </File>
<File Source="LICENSE" /> <File Source="LICENSE" />
<File Source="hushd.exe" />
<File Source="hush-cli.exe" />
<File Source="README.md" />
<RegistryKey Root="HKCR" Key="hush"> <RegistryKey Root="HKCR" Key="hush">
<RegistryValue Type="string" Name="URL Protocol" Value=""/> <RegistryValue Type="string" Name="URL Protocol" Value=""/>
<RegistryValue Type="string" Value="URL:hush URI protocol"/> <RegistryValue Type="string" Value="URL:hush URI protocol"/>
<RegistryKey Key="DefaultIcon"> <RegistryKey Key="DefaultIcon">
<RegistryValue Type="string" Value="silentdragon.exe" /> <RegistryValue Type="string" Value="SilentDragonLite.exe" />
</RegistryKey> </RegistryKey>
<RegistryKey Key="shell\open\command"> <RegistryKey Key="shell\open\command">
<RegistryValue Type="string" Value="&quot;[INSTALLFOLDER]silentdragon.exe&quot; &quot;%1&quot;" /> <RegistryValue Type="string" Value="&quot;[INSTALLFOLDER]SilentDragonLite.exe&quot; &quot;%1&quot;" />
</RegistryKey> </RegistryKey>
</RegistryKey> </RegistryKey>
</Component> </Component>

2
src/sendtab.cpp

@ -214,7 +214,7 @@ void MainWindow::updateLabelsAutoComplete() {
labelCompleter->setCaseSensitivity(Qt::CaseInsensitive); labelCompleter->setCaseSensitivity(Qt::CaseInsensitive);
// Then, find all the address fields and update the completer. // Then, find all the address fields and update the completer.
QRegExp re("Address[0-9]+", Qt::CaseInsensitive); QRegularExpression re("Address[0-9]+", QRegularExpression::CaseInsensitiveOption);
for (auto target: ui->sendToWidgets->findChildren<QLineEdit *>(re)) { for (auto target: ui->sendToWidgets->findChildren<QLineEdit *>(re)) {
target->setCompleter(labelCompleter); target->setCompleter(labelCompleter);
} }

4
src/settings.cpp

@ -74,11 +74,11 @@ bool Settings::isTAddress(QString addr) {
return addr.startsWith("R"); return addr.startsWith("R");
} }
int Settings::gethushdVersion() { QString Settings::gethushdVersion() {
return _hushdVersion; return _hushdVersion;
} }
void Settings::sethushdVersion(int version) { void Settings::sethushdVersion(QString version) {
_hushdVersion = version; _hushdVersion = version;
} }

13
src/settings.h

@ -42,8 +42,8 @@ public:
bool isSyncing(); bool isSyncing();
void setSyncing(bool syncing); void setSyncing(bool syncing);
int gethushdVersion(); QString gethushdVersion();
void sethushdVersion(int version); void sethushdVersion(QString version);
void setUseEmbedded(bool r) { _useEmbedded = r; } void setUseEmbedded(bool r) { _useEmbedded = r; }
bool useEmbedded() { return _useEmbedded; } bool useEmbedded() { return _useEmbedded; }
@ -119,13 +119,12 @@ public:
static bool isValidAddress(QString addr); static bool isValidAddress(QString addr);
static QString getChainName() { return QString("main"); } static QString getDefaultChainName() { return QString("main"); }
static const QString labelRegExp; static const QString labelRegExp;
static const int updateSpeed = 20 * 1000; // 20 sec static const int updateSpeed = 30 * 1000; // 30 sec
static const int quickUpdateSpeed = 5 * 1000; // 5 sec static const int priceRefreshSpeed = 5 * 60 * 1000; // 1 hr
static const int priceRefreshSpeed = 5 * 60 * 1000; // 5 mins
private: private:
// This class can only be accessed through Settings::getInstance() // This class can only be accessed through Settings::getInstance()
@ -138,7 +137,7 @@ private:
bool _isTestnet = false; bool _isTestnet = false;
bool _isSyncing = false; bool _isSyncing = false;
int _blockNumber = 0; int _blockNumber = 0;
int _hushdVersion = 0; QString _hushdVersion = 0;
bool _useEmbedded = false; bool _useEmbedded = false;
bool _headless = false; bool _headless = false;

71
src/settings.ui

@ -6,16 +6,10 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>540</width> <width>733</width>
<height>539</height> <height>539</height>
</rect> </rect>
</property> </property>
<property name="minimumSize">
<size>
<width>540</width>
<height>500</height>
</size>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Settings</string> <string>Settings</string>
</property> </property>
@ -52,19 +46,20 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Server</string> <string>Lightwallet Server</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="txtServer">
<property name="placeholderText">
<string/>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_2"/> <layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QComboBox" name="cmbServer">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
@ -298,50 +293,6 @@
</item> </item>
</widget> </widget>
</widget> </widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Troubleshooting</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="5" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Rescan the blockchain for any missing wallet transactions and to correct your wallet balance. This may take several hours. You need to restart hushWallet for this to take effect</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="chkRescan">
<property name="text">
<string>Rescan</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
<item> <item>

17
src/txtablemodel.cpp

@ -70,15 +70,18 @@ bool TxTableModel::exportToCsv(QString fileName) const {
} }
QString TxTableModel::concatMultipleMemos(const TransactionItem& dat) const { QString TxTableModel::concatMultipleMemos(const TransactionItem& dat) const {
// Concat all the memos if (dat.items.length() == 1) {
QString memo; return dat.items[0].memo;
for (auto item : dat.items) { } else {
if (!item.memo.trimmed().isEmpty()) { // Concat all the memos
memo += item.address + ": \"" + item.memo + "\"\n"; QString memo;
for (auto item : dat.items) {
if (!item.memo.trimmed().isEmpty()) {
memo += item.address + ": \"" + item.memo + "\"\n";
}
} }
return memo;
} }
return memo;
}; };
QVariant TxTableModel::data(const QModelIndex &index, int role) const { QVariant TxTableModel::data(const QModelIndex &index, int role) const {

Loading…
Cancel
Save