Browse Source

Merge branch 'dev'

pull/31/head v1.5.2
Duke Leto 3 years ago
parent
commit
2a22418779
  1. 27
      README.md
  2. 1
      application.qrc
  3. 85
      src/Chat/Chat.cpp
  4. 3
      src/Chat/Helper/ChatDelegator.h
  5. 9
      src/DataStore/ChatDataStore.cpp
  6. 39
      src/Model/ChatItem.cpp
  7. 2
      src/camount.cpp
  8. 54
      src/chatmodel.cpp
  9. 2
      src/connection.cpp
  10. 18
      src/contactmodel.cpp
  11. 279
      src/controller.cpp
  12. 2
      src/controller.h
  13. 108
      src/mainwindow.cpp
  14. 6
      src/recurring.cpp
  15. 11
      src/settings.cpp
  16. 6
      src/settings.h
  17. 2
      src/version.h
  18. 5
      src/websockets.cpp

27
README.md

@ -10,9 +10,6 @@
<a href="https://fosstodon.org/@myhushteam"> <a href="https://fosstodon.org/@myhushteam">
<img src="https://img.shields.io/badge/Mastodon-MyHushTeam-blue" <img src="https://img.shields.io/badge/Mastodon-MyHushTeam-blue"
alt="follow on Mastodon"></a> alt="follow on Mastodon"></a>
<a href="https://www.reddit.com/r/Myhush/">
<img src="https://img.shields.io/reddit/subreddit-subscribers/Myhush?style=social"
alt="MyHushTeam's Reddit"></a>
</p> </p>
SilentDragonLite is a lightwallet for HUSH ($HUSH) runs on Linux and Windows which does not require you to download the full blockchain. This is experimental software under active development! SilentDragonLite is a lightwallet for HUSH ($HUSH) runs on Linux and Windows which does not require you to download the full blockchain. This is experimental software under active development!
@ -44,20 +41,21 @@ Go to the [releases page](https://git.hush.is/hush/SilentDragonLite/releases) an
### Option 2: Compile Release Yourself ### Option 2: Compile Release Yourself
* 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) or install using your Linux version's package manager. * It also depends on Qt5, which you can get from [here](https://www.qt.io/download) or we recommend installing using your Linux version's package manager (if available).
* You'll need Rust v1.49 * **You'll need Rust v1.49**, so install it via [Rustup in Linux](https://rustup.rs/).
#### Building on Linux #### Building on Linux
**Nothing below will work without rust. Check that your system has rustc 1.49. If not then you need to use [Rustup in Linux](https://rustup.rs/).**
Compiling can take some time, so be patient and wait for it to finish. It will take potentially a long time for slower systems. Be Patient and please report compiler problems!
##### Ubuntu 18.04 and 20.04: ##### Ubuntu 18.04 and 20.04:
```shell script ```shell script
sudo apt-get -y install qt5-default qt5-qmake libqt5websockets5-dev qtcreator sudo apt-get -y install qt5-default qt5-qmake libqt5websockets5-dev qtcreator
git clone https://git.hush.is/hush/SilentDragonLite git clone https://git.hush.is/hush/SilentDragonLite
cd SilentDragonLite cd SilentDragonLite
# sometimes have to build the translations before building the binary
./build.sh linguist ./build.sh linguist
# the next step will take potentially a long time for slower systems
# Be Patient and please report compiler problems!
./build.sh ./build.sh
./SilentDragonLite ./SilentDragonLite
``` ```
@ -88,20 +86,9 @@ SilentDragonLite does automatic note and utxo management, which means it doesn't
## Support ## Support
```
git clone https://git.hush.is/hush/SilenDragonLite
cd SilentDragonLite
# the next step will take potentially a long time for slower systems
# Be Patient and please report compiler problems!
./build.sh
./SilentDragonLite
```
## Support
For support join us on [Telegram Support](https://hush.is/telegram_support), or our [Main Telegram](https://hush.is/telegram) or tweet at [@MyHushTeam](https://twitter.com/MyHushTeam), or toot at our [Mastodon](https://fosstodon.org/@myhushteam), or [file an issue](https://git.hush.is/hush/SilentDragonLite/issues). For support join us on [Telegram Support](https://hush.is/telegram_support), or our [Main Telegram](https://hush.is/telegram) or tweet at [@MyHushTeam](https://twitter.com/MyHushTeam), or toot at our [Mastodon](https://fosstodon.org/@myhushteam), or [file an issue](https://git.hush.is/hush/SilentDragonLite/issues).
You can also subscribe to our channel on [YouTube](https://hush.is/yt) You can also subscribe to our channels on [PeerTube](https://videos.hush.is), on [YouTube](https://hush.is/yt), or on [Odyssee/LBRY](https://odysee.com/@MyHushTeam:3).
## License ## License

1
application.qrc

@ -54,6 +54,7 @@
</qresource> </qresource>
<qresource prefix="/img"> <qresource prefix="/img">
<file>res/hushdlogo.png</file>
<file>res/hushdlogo.gif</file> <file>res/hushdlogo.gif</file>
<file>res/silentdragonlite-animated.gif</file> <file>res/silentdragonlite-animated.gif</file>
<file>res/silentdragonlite-animated-dark.gif</file> <file>res/silentdragonlite-animated-dark.gif</file>

85
src/Chat/Chat.cpp

@ -1,5 +1,5 @@
// Copyright 2019-2021 The Hush developers // Copyright 2019-2021 The Hush developers
// GPLv3 // Released under the GPLv3
#include "Chat.h" #include "Chat.h"
#include "../addressbook.h" #include "../addressbook.h"
@ -22,8 +22,7 @@ void ChatMemoEdit::updateDisplayChat() {
if (lenDisplayLabelchat) if (lenDisplayLabelchat)
lenDisplayLabelchat->setStyleSheet(""); lenDisplayLabelchat->setStyleSheet("");
} } else {
else {
// Overweight // Overweight
if (sendChatButton) if (sendChatButton)
sendChatButton->setEnabled(false); sendChatButton->setEnabled(false);
@ -50,6 +49,8 @@ ChatMemoEditRequest::ChatMemoEditRequest(QWidget* parent) : QTextEdit(parent) {
QObject::connect(this, &QTextEdit::textChanged, this, &ChatMemoEditRequest::updateDisplayChatRequest); QObject::connect(this, &QTextEdit::textChanged, this, &ChatMemoEditRequest::updateDisplayChatRequest);
} }
// TODO: unify this with updateDisplayChat()
void ChatMemoEditRequest::updateDisplayChatRequest() { void ChatMemoEditRequest::updateDisplayChatRequest() {
QString txt = this->toPlainText(); QString txt = this->toPlainText();
if (lenDisplayLabelchatRequest) if (lenDisplayLabelchatRequest)
@ -62,8 +63,7 @@ void ChatMemoEditRequest::updateDisplayChatRequest() {
if (lenDisplayLabelchatRequest) if (lenDisplayLabelchatRequest)
lenDisplayLabelchatRequest->setStyleSheet(""); lenDisplayLabelchatRequest->setStyleSheet("");
} } else {
else {
// Overweight // Overweight
if (sendRequestButton) if (sendRequestButton)
sendRequestButton->setEnabled(false); sendRequestButton->setEnabled(false);
@ -85,59 +85,68 @@ void ChatMemoEditRequest::SetSendRequestButton(QPushButton* button) {
void ChatMemoEditRequest::setLenDisplayLabelChatRequest(QLabel* label) { void ChatMemoEditRequest::setLenDisplayLabelChatRequest(QLabel* label) {
this->lenDisplayLabelchatRequest = label; this->lenDisplayLabelchatRequest = label;
} }
void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label) void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label)
{ {
QStandardItemModel *chat = new QStandardItemModel(); QStandardItemModel *chat = new QStandardItemModel();
DataStore::getChatDataStore()->dump(); // test to see if the chat items in datastore are correctly dumped to json DataStore::getChatDataStore()->dump(); // test to see if the chat items in datastore are correctly dumped to json
for (auto &p : AddressBook::getInstance()->getAllAddressLabels()) std::map<QString,int> seenTxids;
{
for (auto &c : DataStore::getChatDataStore()->getAllMemos())
{
if ( qDebug() << __func__ << ": looking at memos...";
(p.getName() == ui->contactNameMemo->text().trimmed()) && for (auto &contact : AddressBook::getInstance()->getAllAddressLabels())
(p.getPartnerAddress() == c.second.getAddress()) && {
(c.second.isOutgoing() == true)) for (auto &memo : DataStore::getChatDataStore()->getAllMemos()) {
if ( (contact.getName() == ui->contactNameMemo->text().trimmed()) &&
{ (contact.getPartnerAddress() == memo.second.getAddress()) &&
(memo.second.isOutgoing() == true)) {
QStandardItem *Items = new QStandardItem(c.second.toChatLine()); QStandardItem *Items = new QStandardItem(memo.second.toChatLine());
Items->setData(OUTGOING, Qt::UserRole + 1); Items->setData(OUTGOING, Qt::UserRole + 1);
qDebug() << __func__ << ": appending row to OUTGOING chatitems to contact " << contact.getName() << " with item " << Items;
chat->appendRow(Items); chat->appendRow(Items);
ui->listChat->setModel(chat); ui->listChat->setModel(chat);
} } else {
else
{
ui->listChat->setModel(chat); ui->listChat->setModel(chat);
} }
if ( qDebug() << __func__ << ": memo.first=" << memo.first;
(p.getName() == ui->contactNameMemo->text().trimmed()) && if ( (contact.getName() == ui->contactNameMemo->text().trimmed()) &&
(p.getMyAddress() == c.second.getAddress()) && (contact.getMyAddress() == memo.second.getAddress()) &&
(c.second.isOutgoing() == false) && (memo.second.isOutgoing() == false) &&
(c.second.getCid() == p.getCid()) (memo.second.getCid() == contact.getCid())
) ) {
{ QStandardItem *Items1 = new QStandardItem(memo.second.toChatLine());
QStandardItem *Items1 = new QStandardItem(c.second.toChatLine());
Items1->setData(INCOMING, Qt::UserRole + 1); Items1->setData(INCOMING, Qt::UserRole + 1);
chat->appendRow(Items1); qDebug() << __func__ << ": appending row to INCOMING chatitems to contact " << contact.getName() << "with txid=" << memo.second.getTxid() << " cid=" << contact.getCid() << " item " << Items1 << " memo=" << memo.second.getMemo();
ui->listChat->setModel(chat);
ui->memoTxtChat->setEnabled(true);
ui->emojiButton->setEnabled(true); if(seenTxids.count( memo.second.getTxid() ) > 0) {
ui->sendChatButton->setEnabled(true); // Do not render the same chat multiple times
// TODO: this should also look at outputindex to allow for multi-part memos, when that is supported
qDebug() << __func__ << ": INCOMING ignoring txid=" << memo.second.getTxid();
continue;
}
// TODO: better header memo detection
if (memo.second.getMemo().startsWith("{")) {
qDebug() << __func__ << ": ignoring header memo=" << memo.second.getMemo();
} else {
chat->appendRow(Items1);
ui->listChat->setModel(chat);
ui->memoTxtChat->setEnabled(true);
ui->emojiButton->setEnabled(true);
ui->sendChatButton->setEnabled(true);
seenTxids[ memo.second.getTxid() ] = 1;
}
} } else {
else
{
ui->listChat->setModel(chat); ui->listChat->setModel(chat);
} }
} }
} }
} }

3
src/Chat/Helper/ChatDelegator.h

@ -1,4 +1,4 @@
// Copyright 2019-2020 The Hush developers // Copyright 2019-2021 The Hush developers
// GPLv3 // GPLv3
#ifndef CHATDELEGATOR_H #ifndef CHATDELEGATOR_H
@ -42,6 +42,7 @@ inline ListViewDelegate::ListViewDelegate(QObject *parent): QAbstractItemDelegat
} }
//TODO: this data must be kept in sync with sizeHint(), refactor
inline void ListViewDelegate::paint(QPainter *painter, QStyleOptionViewItem const &option, QModelIndex const &index) const inline void ListViewDelegate::paint(QPainter *painter, QStyleOptionViewItem const &option, QModelIndex const &index) const
{ {
QTextDocument bodydoc; QTextDocument bodydoc;

9
src/DataStore/ChatDataStore.cpp

@ -160,14 +160,7 @@ std::map<QString, ChatItem> ChatDataStore::getAllMemos()
std::map<QString, ChatItem> filteredItems; std::map<QString, ChatItem> filteredItems;
for(auto &c: this->data) for(auto &c: this->data)
{ {
if ( if ((c.second.getMemo().startsWith("{") == false) && (c.second.getMemo().isEmpty() == false) ) {
(c.second.getMemo().startsWith("{") == false) &&
(c.second.getMemo().isEmpty() == false)
)
{
filteredItems[c.first] = c.second; filteredItems[c.first] = c.second;
} }
} }

39
src/Model/ChatItem.cpp

@ -163,22 +163,15 @@ QString ChatItem::toChatLine()
QString moneyTextRequest; QString moneyTextRequest;
myDateTime.setTime_t(_timestamp); myDateTime.setTime_t(_timestamp);
if (_notarize == true) if (_notarize == true) {
{
lock = "<b> <img src=':/icons/res/lock_orange.png'><b>"; lock = "<b> <img src=':/icons/res/lock_orange.png'><b>";
} else {
lock = "<b> <img src=':/icons/res/unlocked.png'><b>";
}
}else{ if ((_confirmations > 0) && (_notarize == false)) {
lock = "<b> <img src=':/icons/res/unlocked.png'><b>";
}
if ((_confirmations > 0) && (_notarize == false))
{
lock = "<b> <img src=':/icons/res/lock_green.png'><b>"; lock = "<b> <img src=':/icons/res/lock_green.png'><b>";
}else{} }
if (_memo.startsWith("Money transaction of :")) if (_memo.startsWith("Money transaction of :"))
{ {
@ -210,8 +203,6 @@ QString ChatItem::toChatLine()
}else{moneyTextRequest = ""; }else{moneyTextRequest = "";
moneyTextRequest = ""; } moneyTextRequest = ""; }
QString line = QString("<small>") + myDateTime.toString("yyyy-MM-dd hh:mm"); QString line = QString("<small>") + myDateTime.toString("yyyy-MM-dd hh:mm");
line += QString(lock) + QString(moneyText) + QString(moneyTextRequest) + QString("</small>"); line += QString(lock) + QString(moneyText) + QString(moneyTextRequest) + QString("</small>");
@ -223,16 +214,16 @@ QString ChatItem::toChatLine()
json ChatItem::toJson() json ChatItem::toJson()
{ {
json j; json j;
j["_timestamp"] = _timestamp; j["_timestamp"] = _timestamp;
j["_address"] = _address.toStdString(); j["_address"] = _address.toStdString();
j["_contact"] = _contact.toStdString(); j["_contact"] = _contact.toStdString();
j["_memo"] = _memo.toStdString(); j["_memo"] = _memo.toStdString();
j["_requestZaddr"] = _requestZaddr.toStdString(); j["_requestZaddr"] = _requestZaddr.toStdString();
j["_type"] = _type.toStdString(); j["_type"] = _type.toStdString();
j["_cid"] = _cid.toStdString(); j["_cid"] = _cid.toStdString();
j["_txid"] = _txid.toStdString(); j["_txid"] = _txid.toStdString();
j["_confirmations"] = _confirmations; j["_confirmations"] = _confirmations;
j["_outgoing"] = _outgoing; j["_outgoing"] = _outgoing;
return j; return j;
} }

2
src/camount.cpp

@ -43,7 +43,7 @@ double CAmount::getDblAmount() const
QString CAmount::toDecimalUSDString() const QString CAmount::toDecimalUSDString() const
{ {
double price = Settings::getInstance()->getZECPrice(); double price = Settings::getInstance()->getHUSHPrice();
return "$ " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2); return "$ " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
} }

54
src/chatmodel.cpp

@ -65,11 +65,12 @@ void ChatModel::addMessage(QString timestamp, ChatItem item)
void ChatModel::showMessages() void ChatModel::showMessages()
{ {
/*
for(auto &c : this->chatItems) for(auto &c : this->chatItems)
{ {
} }
*/
} }
void ChatModel::addAddressbylabel(QString address, QString label) void ChatModel::addAddressbylabel(QString address, QString label)
@ -79,11 +80,6 @@ void ChatModel::addAddressbylabel(QString address, QString label)
QString ChatModel::Addressbylabel(QString address) QString ChatModel::Addressbylabel(QString address)
{ {
for(auto& pair : this->AddressbyLabelMap)
{
}
if(this->AddressbyLabelMap.count(address) > 0) if(this->AddressbyLabelMap.count(address) > 0)
{ {
return this->AddressbyLabelMap[address]; return this->AddressbyLabelMap[address];
@ -306,11 +302,6 @@ void ChatModel::addconfirmations(QString tx, int confirmation)
QString ChatModel::getCidByTx(QString tx) QString ChatModel::getCidByTx(QString tx)
{ {
for(auto& pair : this->cidMap)
{
}
if(this->cidMap.count(tx) > 0) if(this->cidMap.count(tx) > 0)
{ {
return this->cidMap[tx]; return this->cidMap[tx];
@ -321,11 +312,6 @@ QString ChatModel::getCidByTx(QString tx)
QString ChatModel::getMemoByTx(QString tx) QString ChatModel::getMemoByTx(QString tx)
{ {
for(auto& pair : this->OldMemoByTx)
{
}
if(this->OldMemoByTx.count(tx) > 0) if(this->OldMemoByTx.count(tx) > 0)
{ {
return this->OldMemoByTx[tx]; return this->OldMemoByTx[tx];
@ -339,11 +325,6 @@ QString ChatModel::getMemoByTx(QString tx)
QString ChatModel::getHeaderByTx(QString tx) QString ChatModel::getHeaderByTx(QString tx)
{ {
for(auto& pair : this->headerMap)
{
}
if(this->headerMap.count(tx) > 0) if(this->headerMap.count(tx) > 0)
{ {
return this->headerMap[tx]; return this->headerMap[tx];
@ -354,11 +335,6 @@ QString ChatModel::getHeaderByTx(QString tx)
QString ChatModel::getConfirmationByTx(QString tx) QString ChatModel::getConfirmationByTx(QString tx)
{ {
for(auto& pair : this->confirmationsMap)
{
}
if(this->confirmationsMap.count(tx) > 0) if(this->confirmationsMap.count(tx) > 0)
{ {
return this->confirmationsMap[tx]; return this->confirmationsMap[tx];
@ -369,11 +345,6 @@ QString ChatModel::getConfirmationByTx(QString tx)
QString ChatModel::getrequestZaddrByTx(QString tx) QString ChatModel::getrequestZaddrByTx(QString tx)
{ {
for(auto& pair : this->requestZaddrMap)
{
}
if(this->requestZaddrMap.count(tx) > 0) if(this->requestZaddrMap.count(tx) > 0)
{ {
return this->requestZaddrMap[tx]; return this->requestZaddrMap[tx];
@ -477,20 +448,23 @@ Tx MainWindow::createTxFromChatPage() {
unsigned char pk[crypto_kx_PUBLICKEYBYTES]; unsigned char pk[crypto_kx_PUBLICKEYBYTES];
unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
if (crypto_kx_seed_keypair(pk,sk, if (crypto_kx_seed_keypair(pk,sk, MESSAGEAS1) !=0) {
MESSAGEAS1) !=0) { this->logger->write("Suspicious keypair, bail out ");
qDebug() << __func__<< ": Suspicious client public outgoing key from crypto_kx_seed_keypair, aborting!";
return tx;
}
this->logger->write("Suspicious keypair, bail out ");
}
////////////////Get the pubkey from Bob, so we can create the share key ////////////////Get the pubkey from Bob, so we can create the share key
const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1()); const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1());
const unsigned char *pubkeyBob = reinterpret_cast<const unsigned char *>(pubkeyBobArray.constData()); const unsigned char *pubkeyBob = reinterpret_cast<const unsigned char *>(pubkeyBobArray.constData());
/////Create the shared key for sending the message
if (crypto_kx_server_session_keys(server_rx, server_tx, /////Create the shared key for sending the message
pk, sk, pubkeyBob) != 0) {
this->logger->write("Suspicious client public send key, bail out "); if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0) {
this->logger->write("Suspicious client public send key, bail out ");
qDebug() << __func__ << ": Suspicious client public send key from crypto_kx_server_session_keys, aborting!";
return tx;
} }
@ -821,6 +795,8 @@ Tx MainWindow::createTxForSafeContactRequest()
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) { if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) {
this->logger->write("Suspicious client public contact request key, bail out "); this->logger->write("Suspicious client public contact request key, bail out ");
qDebug() << __func__ << ": Suspicious client public send key from crypto_kx_seed_keypair, aborting!";
return tx;
} }
QString publicKey = QByteArray(reinterpret_cast<const char*>(pk), crypto_kx_PUBLICKEYBYTES).toHex(); QString publicKey = QByteArray(reinterpret_cast<const char*>(pk), crypto_kx_PUBLICKEYBYTES).toHex();

2
src/connection.cpp

@ -267,6 +267,7 @@ void ConnectionLoader::doRPCSetConnection(Connection* conn)
try { try {
QFile plaintextWallet(dirwalletconnection); QFile plaintextWallet(dirwalletconnection);
main->logger->write("Path to Wallet.dat : " ); main->logger->write("Path to Wallet.dat : " );
qDebug() << __func__ << ": wallet path =" << plaintextWallet;
plaintextWallet.remove(); plaintextWallet.remove();
} catch (...) { } catch (...) {
@ -286,6 +287,7 @@ void ConnectionLoader::doRPCSetConnectionShield(Connection* conn)
try { try {
QFile plaintextWallet(dirwalletconnection); QFile plaintextWallet(dirwalletconnection);
main->logger->write("Path to Wallet.dat : " ); main->logger->write("Path to Wallet.dat : " );
qDebug() << __func__ << ": wallet path =" << plaintextWallet;
plaintextWallet.remove(); plaintextWallet.remove();
} catch (...) { } catch (...) {
main->logger->write("no Plaintext wallet.dat"); main->logger->write("no Plaintext wallet.dat");

18
src/contactmodel.cpp

@ -1,4 +1,4 @@
// Copyright 2019-2020 The Hush developers // Copyright 2019-2021 The Hush developers
// GPLv3 // GPLv3
#include "contactmodel.h" #include "contactmodel.h"
@ -18,11 +18,6 @@ void ContactModel::addLabel(QString addr, QString label)
QString ContactModel::getContactbyAddress(QString addr) QString ContactModel::getContactbyAddress(QString addr)
{ {
for(auto& pair : this->AddressMap)
{
}
if(this->AddressMap.count(addr) > 0) if(this->AddressMap.count(addr) > 0)
{ {
return this->AddressMap[addr]; return this->AddressMap[addr];
@ -65,9 +60,7 @@ void MainWindow::showRequesthush() {
for(auto &p : AddressBook::getInstance()->getAllAddressLabels()) for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
{ {
if (p.getName() == label) if (p.getName() == label) {
{
QString addr = p.getPartnerAddress(); QString addr = p.getPartnerAddress();
QString myzaddr = p.getMyAddress(); QString myzaddr = p.getMyAddress();
@ -135,7 +128,8 @@ void MainWindow::showRequesthush() {
} }
} }
if (d.exec() == QDialog::Accepted) {
if (d.exec() == QDialog::Accepted) {
// Construct a hush Payment URI with the data and pay it immediately. // Construct a hush Payment URI with the data and pay it immediately.
CAmount amount = CAmount::fromDecimalString(req.txtAmount->text()); CAmount amount = CAmount::fromDecimalString(req.txtAmount->text());
QString memoURI = "hush:" + req.lblAddressInfo->text() QString memoURI = "hush:" + req.lblAddressInfo->text()
@ -150,10 +144,6 @@ void MainWindow::showRequesthush() {
// sapling address // sapling address
this->payhushURI(sendURI, req.lblAddressInfo->text()); this->payhushURI(sendURI, req.lblAddressInfo->text());
} }
} }

279
src/controller.cpp

@ -1,5 +1,5 @@
// Copyright 2019-2020 The Hush developers // Copyright 2019-2021 The Hush developers
// GPLv3 // Released under the GPLv3
#include "controller.h" #include "controller.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -42,7 +42,7 @@ Controller::Controller(MainWindow* main)
priceTimer = new QTimer(main); priceTimer = new QTimer(main);
QObject::connect(priceTimer, &QTimer::timeout, [=]() { QObject::connect(priceTimer, &QTimer::timeout, [=]() {
if (Settings::getInstance()->getAllowFetchPrices()) if (Settings::getInstance()->getAllowFetchPrices())
refreshZECPrice(); refreshHUSHPrice();
}); });
priceTimer->start(Settings::priceRefreshSpeed); // Every 5 Min priceTimer->start(Settings::priceRefreshSpeed); // Every 5 Min
@ -89,7 +89,7 @@ void Controller::setConnection(Connection* c)
// If we're allowed to get the Hush Price, get the prices // If we're allowed to get the Hush Price, get the prices
if (Settings::getInstance()->getAllowFetchPrices()) { if (Settings::getInstance()->getAllowFetchPrices()) {
refreshZECPrice(); refreshHUSHPrice();
supplyUpdate(); supplyUpdate();
} }
@ -369,7 +369,7 @@ void Controller::getInfoThenRefresh(bool force)
if (Settings::getInstance()->get_currency_name() == "USD") if (Settings::getInstance()->get_currency_name() == "USD")
{ {
double price = Settings::getInstance()->getZECPrice(); double price = Settings::getInstance()->getHUSHPrice();
double volume = Settings::getInstance()->getUSDVolume(); double volume = Settings::getInstance()->getUSDVolume();
double cap = Settings::getInstance()->getUSDCAP(); double cap = Settings::getInstance()->getUSDCAP();
main->statusLabel->setText( main->statusLabel->setText(
@ -546,7 +546,7 @@ void Controller::getInfoThenRefresh(bool force)
else else
{ {
main->statusLabel->setText( main->statusLabel->setText(
" HUSH/USD=$" + QString::number(Settings::getInstance()->getZECPrice(),'f',2 ) " HUSH/USD=$" + QString::number(Settings::getInstance()->getHUSHPrice(),'f',2 )
); );
ui->volumeExchange->setText( ui->volumeExchange->setText(
" $ " + QString::number((double) Settings::getInstance()->getUSDVolume() ,'f',2) " $ " + QString::number((double) Settings::getInstance()->getUSDVolume() ,'f',2)
@ -662,29 +662,29 @@ void Controller::updateUI(bool anyUnconfirmed)
void Controller::supplyUpdate() { void Controller::supplyUpdate() {
qDebug()<<"Supply"; qDebug()<< __func__ << ": updating supply";
// Get the total supply and render it with thousand decimal
zrpc->fetchSupply([=] (const json& reply) {
int supply = reply["supply"].get<json::number_integer_t>();
int zfunds = reply["zfunds"].get<json::number_integer_t>();
int total = reply["total"].get<json::number_integer_t>();;
if (
Settings::getInstance()->get_currency_name() == "EUR" ||
Settings::getInstance()->get_currency_name() == "CHF" ||
Settings::getInstance()->get_currency_name() == "RUB"
)
{
ui->supply_taddr->setText((QLocale(QLocale::German).toString(supply)+ " HUSH"));
ui->supply_zaddr->setText((QLocale(QLocale::German).toString(zfunds)+ " HUSH"));
ui->supply_total->setText((QLocale(QLocale::German).toString(total)+ " HUSH"));
} else {
ui->supply_taddr->setText("HUSH " + (QLocale(QLocale::English).toString(supply)));
ui->supply_zaddr->setText("HUSH " +(QLocale(QLocale::English).toString(zfunds)));
ui->supply_total->setText("HUSH " +(QLocale(QLocale::English).toString(total)));
}
}); // Get the total supply and render it with thousand decimal
zrpc->fetchSupply([=] (const json& reply) {
int supply = reply["supply"].get<json::number_integer_t>();
int zfunds = reply["zfunds"].get<json::number_integer_t>();
int total = reply["total"].get<json::number_integer_t>();;
if (Settings::getInstance()->get_currency_name() == "EUR" ||
Settings::getInstance()->get_currency_name() == "CHF" ||
Settings::getInstance()->get_currency_name() == "RUB"
) {
// TODO: assuming German locale is incorrect
ui->supply_taddr->setText((QLocale(QLocale::German).toString(supply)+ " HUSH"));
ui->supply_zaddr->setText((QLocale(QLocale::German).toString(zfunds)+ " HUSH"));
ui->supply_total->setText((QLocale(QLocale::German).toString(total)+ " HUSH"));
} else {
// TODO: assuming English locale is incorrect as well
ui->supply_taddr->setText("HUSH " + (QLocale(QLocale::English).toString(supply)));
ui->supply_zaddr->setText("HUSH " +(QLocale(QLocale::English).toString(zfunds)));
ui->supply_total->setText("HUSH " +(QLocale(QLocale::English).toString(total)));
}
qDebug() << __func__ << ": supply=" << supply;
});
} }
@ -720,9 +720,9 @@ void Controller::processUnspent(const json& reply, QMap<QString, CAmount>* balan
void Controller::updateUIBalances() void Controller::updateUIBalances()
{ {
CAmount balT = getModel()->getBalT(); CAmount balT = getModel()->getBalT();
CAmount balZ = getModel()->getBalZ(); CAmount balZ = getModel()->getBalZ();
CAmount balVerified = getModel()->getBalVerified(); CAmount balVerified = getModel()->getBalVerified();
CAmount balSpendable = getModel()->getBalSpendable(); CAmount balSpendable = getModel()->getBalSpendable();
// Reduce the BalanceZ by the pending outgoing amount. We're adding // Reduce the BalanceZ by the pending outgoing amount. We're adding
@ -743,6 +743,7 @@ void Controller::updateUIBalances()
ui->balSpendable->setText(balSpendable.toDecimalhushString()); ui->balSpendable->setText(balSpendable.toDecimalhushString());
ui->balTotal->setText(balTotal.toDecimalhushString()); ui->balTotal->setText(balTotal.toDecimalhushString());
//TODO: refactor this madness into functions like SD uses, with currency as a variable
if (Settings::getInstance()->get_currency_name() == "USD") if (Settings::getInstance()->get_currency_name() == "USD")
{ {
ui->balSheilded->setToolTip(balZ.toDecimalUSDString()); ui->balSheilded->setToolTip(balZ.toDecimalUSDString());
@ -921,10 +922,11 @@ void Controller::refreshBalances()
}); });
} }
void Controller::refreshTransactions() { void Controller::refreshTransactions() {
if (!zrpc->haveConnection()) if (!zrpc->haveConnection())
return noConnection(); return noConnection();
qDebug() << __func__ << ": fetchTransactions";
zrpc->fetchTransactions([=] (json reply) { zrpc->fetchTransactions([=] (json reply) {
QList<TransactionItem> txdata; QList<TransactionItem> txdata;
@ -948,15 +950,13 @@ void Controller::refreshTransactions() {
// First, check if there's outgoing metadata // First, check if there's outgoing metadata
if (!it["outgoing_metadata"].is_null()) { if (!it["outgoing_metadata"].is_null()) {
for (auto o: it["outgoing_metadata"].get<json::array_t>()) for (auto o: it["outgoing_metadata"].get<json::array_t>()) {
{
// if (chatModel->getCidByTx(txid) == QString("0xdeadbeef")){ // if (chatModel->getCidByTx(txid) == QString("0xdeadbeef")){
QString address; QString address;
address = QString::fromStdString(o["address"]); address = QString::fromStdString(o["address"]);
// Sent items are -ve // Sent items are negative
CAmount amount = CAmount::fromqint64(-1* o["value"].get<json::number_unsigned_t>()); CAmount amount = CAmount::fromqint64(-1* o["value"].get<json::number_unsigned_t>());
// Check for Memos // Check for Memos
@ -973,15 +973,14 @@ void Controller::refreshTransactions() {
} }
QString memo; QString memo;
QString cid; QString cid = "";
QString headerbytes; QString headerbytes = "";
QString publickey; QString publickey = "";
if (!o["memo"].is_null()) { if (!o["memo"].is_null()) {
memo = QString::fromStdString(o["memo"].get<json::string_t>()); memo = QString::fromStdString(o["memo"].get<json::string_t>());
if (memo.startsWith("{")) { if (memo.startsWith("{")) {
try try {
{
QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8()); QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8());
cid = headermemo["cid"].toString(); cid = headermemo["cid"].toString();
@ -990,51 +989,32 @@ void Controller::refreshTransactions() {
chatModel->addCid(txid, cid); chatModel->addCid(txid, cid);
chatModel->addHeader(txid, headerbytes); chatModel->addHeader(txid, headerbytes);
} } catch (...) {
catch (...) qDebug() << "Invalid JSON in memo detected! memo=" << memo;
{
// on any exception caught
} }
} }
bool isNotarized; bool isNotarized = false;;
if (confirmations > getLag()) if (confirmations > getLag())
{ {
isNotarized = true; isNotarized = true;
} }
else
{
isNotarized = false;
}
if (chatModel->getCidByTx(txid) != QString("0xdeadbeef")) if (chatModel->getCidByTx(txid) != QString("0xdeadbeef"))
{ {
cid = chatModel->getCidByTx(txid); cid = chatModel->getCidByTx(txid);
} }
else
{
cid = "";
}
if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")) if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef"))
{ {
headerbytes = chatModel->getHeaderByTx(txid); headerbytes = chatModel->getHeaderByTx(txid);
} }
else
{
headerbytes = "";
}
if (main->getPubkeyByAddress(address) != QString("0xdeadbeef")) if (main->getPubkeyByAddress(address) != QString("0xdeadbeef"))
{ {
publickey = main->getPubkeyByAddress(address); publickey = main->getPubkeyByAddress(address);
} }
else
{
publickey = "";
}
/////We need to filter out Memos smaller then the ciphertext size, or it will dump /////We need to filter out Memos smaller then the ciphertext size, or it will dump
if ((memo.startsWith("{") == false) && (headerbytes.length() > 20)) if ((memo.startsWith("{") == false) && (headerbytes.length() > 20))
@ -1059,10 +1039,11 @@ void Controller::refreshTransactions() {
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0)
{ {
main->logger->write("Keypair outgoing error"); main->logger->write("Keypair outgoing error");
qDebug() << "refreshTransactions: crypto_kx_seed_keypair error";
continue;
} }
unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
////////////////Get the pubkey from Bob, so we can create the share key ////////////////Get the pubkey from Bob, so we can create the share key
@ -1071,6 +1052,8 @@ void Controller::refreshTransactions() {
if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0) if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0)
{ {
main->logger->write("Suspicious client public outgoing key, bail out "); main->logger->write("Suspicious client public outgoing key, bail out ");
qDebug() << "refreshTransactions: Suspicious client public outgoing key, aborting!";
continue;
} }
const QByteArray ba = QByteArray::fromHex(memo.toUtf8()); const QByteArray ba = QByteArray::fromHex(memo.toUtf8());
@ -1105,20 +1088,20 @@ void Controller::refreshTransactions() {
// crypto_secretstream_xchacha20poly1305_keygen(client_rx); // crypto_secretstream_xchacha20poly1305_keygen(client_rx);
if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, server_tx) != 0) { if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, server_tx) != 0) {
/* Invalid header, no need to go any further */ /* Invalid header, no need to go any further */
qDebug() << "refreshTransactions: crypto_secretstream_xchacha20poly1305_init_pull error!";
continue;
} }
if (crypto_secretstream_xchacha20poly1305_pull if (crypto_secretstream_xchacha20poly1305_pull(&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
(&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
/* Invalid/incomplete/corrupted ciphertext - abort */ /* Invalid/incomplete/corrupted ciphertext - abort */
qDebug() << "refreshTransactions: crypto_secretstream_xchacha20poly1305_pull error!";
continue;
} }
std::string decryptedMemo(reinterpret_cast<char*>(decrypted),MESSAGE1_LEN); std::string decryptedMemo(reinterpret_cast<char*>(decrypted),MESSAGE1_LEN);
memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size()); memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size());
} } else {
else
{
memodecrypt = ""; memodecrypt = "";
} }
@ -1140,6 +1123,7 @@ void Controller::refreshTransactions() {
false false
); );
qDebug() << "refreshTransactions: adding chatItem with memodecrypt=" << memodecrypt;
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
// updateUIBalances(); // updateUIBalances();
} }
@ -1163,9 +1147,7 @@ void Controller::refreshTransactions() {
"send", datetime, address, txid,confirmations, items "send", datetime, address, txid,confirmations, items
}); });
} } else {
else
{
{ // Incoming Transaction { // Incoming Transaction
address = (it["address"].is_null() ? "" : QString::fromStdString(it["address"])); address = (it["address"].is_null() ? "" : QString::fromStdString(it["address"]));
@ -1175,10 +1157,9 @@ void Controller::refreshTransactions() {
if (!it["memo"].is_null()) { if (!it["memo"].is_null()) {
memo = QString::fromStdString(it["memo"]); memo = QString::fromStdString(it["memo"]);
} }
items.push_back(TransactionItemDetail{ items.push_back(TransactionItemDetail{ address,
address,
CAmount::fromqint64(it["amount"].get<json::number_integer_t>()), CAmount::fromqint64(it["amount"].get<json::number_integer_t>()),
memo memo
}); });
TransactionItem tx{ TransactionItem tx{
@ -1186,117 +1167,86 @@ void Controller::refreshTransactions() {
}; };
txdata.push_back(tx); txdata.push_back(tx);
QString type; QString type = "";
QString publickey; QString publickey = "";
QString headerbytes; QString headerbytes = "";
QString cid; QString cid = "";
QString requestZaddr; QString requestZaddr = "";
QString contactname; QString contactname = "";
bool isContact; bool isContact = false;
if (!it["memo"].is_null()) { if (!it["memo"].is_null()) {
if (memo.startsWith("{")) { if (memo.startsWith("{")) {
try try {
{
QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8()); QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8());
cid = headermemo["cid"].toString(); cid = headermemo["cid"].toString();
type = headermemo["t"].toString(); type = headermemo["t"].toString();
requestZaddr = headermemo["z"].toString(); requestZaddr = headermemo["z"].toString();
headerbytes = headermemo["e"].toString(); headerbytes = headermemo["e"].toString();
publickey = headermemo["p"].toString(); publickey = headermemo["p"].toString();
chatModel->addCid(txid, cid); chatModel->addCid(txid, cid);
chatModel->addrequestZaddr(txid, requestZaddr); chatModel->addrequestZaddr(txid, requestZaddr);
chatModel->addHeader(txid, headerbytes); chatModel->addHeader(txid, headerbytes);
if (publickey.length() > 10){ // TODO: better validation of valid public key
main->addPubkey(requestZaddr, publickey); if (publickey.length() > 10){
} main->addPubkey(requestZaddr, publickey);
}
} catch (...) {
qDebug() << __func__ << ": Invalid JSON in memo! memo=" << memo.toUtf8();
} }
catch (...) }
{
// on any exception
}
}
if (chatModel->getCidByTx(txid) != QString("0xdeadbeef")) if (chatModel->getCidByTx(txid) != QString("0xdeadbeef"))
{ {
cid = chatModel->getCidByTx(txid); cid = chatModel->getCidByTx(txid);
} }
else
{
cid = "";
}
if (chatModel->getrequestZaddrByTx(txid) != QString("0xdeadbeef")) if (chatModel->getrequestZaddrByTx(txid) != QString("0xdeadbeef"))
{ {
requestZaddr = chatModel->getrequestZaddrByTx(txid); requestZaddr = chatModel->getrequestZaddrByTx(txid);
} }
else
{
requestZaddr = "";
}
if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")) if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef"))
{ {
headerbytes = chatModel->getHeaderByTx(txid); headerbytes = chatModel->getHeaderByTx(txid);
} }
else
{
headerbytes = "";
}
if (main->getPubkeyByAddress(requestZaddr) != QString("0xdeadbeef")) if (main->getPubkeyByAddress(requestZaddr) != QString("0xdeadbeef"))
{ {
publickey = main->getPubkeyByAddress(requestZaddr); publickey = main->getPubkeyByAddress(requestZaddr);
} }
else
{
publickey = "";
}
if (contactModel->getContactbyAddress(requestZaddr) != QString("0xdeadbeef")) if (contactModel->getContactbyAddress(requestZaddr) != QString("0xdeadbeef"))
{ {
isContact = true; isContact = true;
contactname = contactModel->getContactbyAddress(requestZaddr); contactname = contactModel->getContactbyAddress(requestZaddr);
} }
else
{
isContact = false;
contactname = "";
}
bool isNotarized; bool isNotarized = false;
if (confirmations > getLag()) if (confirmations > getLag())
{ {
isNotarized = true; isNotarized = true;
} }
else
{
isNotarized = false;
}
int position = it["position"].get<json::number_integer_t>(); int position = it["position"].get<json::number_integer_t>();
int ciphercheck = memo.length() - crypto_secretstream_xchacha20poly1305_ABYTES; int ciphercheck = memo.length() - crypto_secretstream_xchacha20poly1305_ABYTES;
qDebug() << __func__ << ": position=" << position << " headerbytes=" << headerbytes
<< " ciphercheck=" << ciphercheck << " for memo=" << memo;
if ((memo.startsWith("{") == false) && (headerbytes > 0) && (ciphercheck > 0)) if ((memo.startsWith("{") == false) && (headerbytes > 0) && (ciphercheck > 0))
{ {
if (chatModel->getMemoByTx(txid) == QString("0xdeadbeef")) if (chatModel->getMemoByTx(txid) == QString("0xdeadbeef")) {
{
if (position == 1) if (position == 1)
{ {
chatModel->addMemo(txid, headerbytes); chatModel->addMemo(txid, headerbytes);
} } else {
else
{
// //
} }
@ -1319,6 +1269,8 @@ void Controller::refreshTransactions() {
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0)
{ {
main->logger->write("Suspicious outgoing key pair, bail out "); main->logger->write("Suspicious outgoing key pair, bail out ");
qDebug() << "refreshTransactions: (incoming) crypto_kx_seed_keypair error!";
continue;
} }
unsigned char client_rx[crypto_kx_SESSIONKEYBYTES], client_tx[crypto_kx_SESSIONKEYBYTES]; unsigned char client_rx[crypto_kx_SESSIONKEYBYTES], client_tx[crypto_kx_SESSIONKEYBYTES];
@ -1326,10 +1278,11 @@ void Controller::refreshTransactions() {
////////////////Get the pubkey from Bob, so we can create the share key ////////////////Get the pubkey from Bob, so we can create the share key
/////Create the shared key for sending the message /////Create the shared key for sending the message
if (crypto_kx_client_session_keys(client_rx, client_tx, pk, sk, pubkeyBob) != 0) if (crypto_kx_client_session_keys(client_rx, client_tx, pk, sk, pubkeyBob) != 0)
{ {
main->logger->write("Suspicious client public incoming key, bail out "); main->logger->write("Suspicious client public incoming key, bail out ");
qDebug() << "refreshTransactions: (incoming) crypto_kx_client_session_keys error!";
continue;
} }
const QByteArray ba = QByteArray::fromHex(memo.toUtf8()); const QByteArray ba = QByteArray::fromHex(memo.toUtf8());
@ -1361,11 +1314,14 @@ void Controller::refreshTransactions() {
// crypto_secretstream_xchacha20poly1305_keygen(client_rx); // crypto_secretstream_xchacha20poly1305_keygen(client_rx);
if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, client_rx) != 0) { if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, client_rx) != 0) {
main->logger->write("Invalid header incoming, no need to go any further "); main->logger->write("Invalid header incoming, no need to go any further ");
qDebug() <<"refreshTransactions: (incoming) crypto_secretstream_xchacha20poly1305_init_pull error! memo=" << memo;
continue;
} }
if (crypto_secretstream_xchacha20poly1305_pull if (crypto_secretstream_xchacha20poly1305_pull(&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
(&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
main->logger->write("Invalid/incomplete/corrupted ciphertext - abort"); main->logger->write("Invalid/incomplete/corrupted ciphertext - abort");
qDebug() << "refreshTransactions: (incoming) crypto_secretstream_xchacha20poly1305_pull error! memo=" << memo;
continue;
} }
std::string decryptedMemo(reinterpret_cast<char*>(decrypted),MESSAGE1_LEN); std::string decryptedMemo(reinterpret_cast<char*>(decrypted),MESSAGE1_LEN);
@ -1375,8 +1331,7 @@ void Controller::refreshTransactions() {
memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size()); memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size());
// } ////Give us the output of the decrypted message as debug to see if it was successfully
//////////////Give us the output of the decrypted message as debug to see if it was successfully
ChatItem item = ChatItem( ChatItem item = ChatItem(
datetime, datetime,
@ -1393,17 +1348,18 @@ void Controller::refreshTransactions() {
isContact isContact
); );
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); auto iid = ChatIDGenerator::getInstance()->generateID(item);
qDebug() << "refreshTransactions: adding chatItem with item id=" << iid << " memodecrypt=" << memodecrypt;
DataStore::getChatDataStore()->setData(iid, item);
} } else {
else qDebug() << __func__ << ": ignoring txid="<< txid;
{
//
} }
} //} else if (memo.startsWith("{")) {
else //qDebug() << __func__ << ": ignoring a header memo";
{ } else {
// Add a chatitem for the initial CR
ChatItem item = ChatItem( ChatItem item = ChatItem(
datetime, datetime,
address, address,
@ -1418,7 +1374,9 @@ void Controller::refreshTransactions() {
isNotarized, isNotarized,
isContact isContact
); );
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); auto iid = ChatIDGenerator::getInstance()->generateID(item);
qDebug() << "refreshTransactions: adding chatItem for initial CR with item id="<< iid << " memo='" << memo << "'";
DataStore::getChatDataStore()->setData(iid, item);
} }
} }
} }
@ -1444,9 +1402,9 @@ void Controller::refreshTransactions() {
// Update model data, which updates the table view // Update model data, which updates the table view
transactionsTableModel->replaceData(txdata); transactionsTableModel->replaceData(txdata);
qDebug() << __func__ << ": calling renderChatBox";
chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat); chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat);
ui->listChat->verticalScrollBar()->setValue( ui->listChat->verticalScrollBar()->setValue(ui->listChat->verticalScrollBar()->maximum());
ui->listChat->verticalScrollBar()->maximum());
}); });
@ -1454,17 +1412,16 @@ void Controller::refreshTransactions() {
void Controller::refreshChat(QListView *listWidget, QLabel *label) void Controller::refreshChat(QListView *listWidget, QLabel *label)
{ {
qDebug() << __func__ << ": calling renderChatBox";
chat->renderChatBox(ui, listWidget, label); chat->renderChatBox(ui, listWidget, label);
ui->listChat->verticalScrollBar()->setValue( ui->listChat->verticalScrollBar()->setValue(ui->listChat->verticalScrollBar()->maximum());
ui->listChat->verticalScrollBar()->maximum());
} }
void Controller::refreshContacts(QListView *listWidget) void Controller::refreshContacts(QListView *listWidget)
{ {
contactModel->renderContactList(listWidget); contactModel->renderContactList(listWidget);
ui->listChat->verticalScrollBar()->setValue( ui->listChat->verticalScrollBar()->setValue(ui->listChat->verticalScrollBar()->maximum());
ui->listChat->verticalScrollBar()->maximum());
} }
// If the wallet is encrpyted and locked, we need to unlock it // If the wallet is encrpyted and locked, we need to unlock it
@ -1670,7 +1627,7 @@ void Controller::checkForUpdate(bool silent)
} }
// Get the hush->USD price from coinmarketcap using their API // Get the hush->USD price from coinmarketcap using their API
void Controller::refreshZECPrice() void Controller::refreshHUSHPrice()
{ {
if (!zrpc->haveConnection()) if (!zrpc->haveConnection())
return noConnection(); return noConnection();
@ -1696,7 +1653,7 @@ void Controller::refreshZECPrice()
else else
qDebug() << reply->errorString(); qDebug() << reply->errorString();
Settings::getInstance()->setZECPrice(0); Settings::getInstance()->setHUSHPrice(0);
Settings::getInstance()->setEURPrice(0); Settings::getInstance()->setEURPrice(0);
Settings::getInstance()->setBTCPrice(0); Settings::getInstance()->setBTCPrice(0);
Settings::getInstance()->setCNYPrice(0); Settings::getInstance()->setCNYPrice(0);
@ -1737,7 +1694,7 @@ void Controller::refreshZECPrice()
auto parsed = json::parse(all, nullptr, false); auto parsed = json::parse(all, nullptr, false);
if (parsed.is_discarded()) if (parsed.is_discarded())
{ {
Settings::getInstance()->setZECPrice(0); Settings::getInstance()->setHUSHPrice(0);
Settings::getInstance()->setEURPrice(0); Settings::getInstance()->setEURPrice(0);
Settings::getInstance()->setBTCPrice(0); Settings::getInstance()->setBTCPrice(0);
Settings::getInstance()->setCNYPrice(0); Settings::getInstance()->setCNYPrice(0);
@ -1780,7 +1737,7 @@ void Controller::refreshZECPrice()
{ {
qDebug() << "Found hush key in price json"; qDebug() << "Found hush key in price json";
qDebug() << "HUSH = $" << QString::number((double)hush["usd"]); qDebug() << "HUSH = $" << QString::number((double)hush["usd"]);
Settings::getInstance()->setZECPrice( hush["usd"] ); Settings::getInstance()->setHUSHPrice( hush["usd"] );
} }
if (hush["eur"] >= 0) if (hush["eur"] >= 0)
@ -1984,7 +1941,7 @@ void Controller::refreshZECPrice()
} }
// If nothing, then set the price to 0; // If nothing, then set the price to 0;
Settings::getInstance()->setZECPrice(0); Settings::getInstance()->setHUSHPrice(0);
Settings::getInstance()->setEURPrice(0); Settings::getInstance()->setEURPrice(0);
Settings::getInstance()->setBTCPrice(0); Settings::getInstance()->setBTCPrice(0);
Settings::getInstance()->setCNYPrice(0); Settings::getInstance()->setCNYPrice(0);

2
src/controller.h

@ -46,7 +46,7 @@ public:
int _lag; int _lag;
void checkForUpdate(bool silent = true); void checkForUpdate(bool silent = true);
void refreshZECPrice(); void refreshHUSHPrice();
void refreshEURPrice(); void refreshEURPrice();
void refreshBTCPrice(); void refreshBTCPrice();
void refreshCNYPrice(); void refreshCNYPrice();

108
src/mainwindow.cpp

@ -86,15 +86,17 @@ MainWindow::MainWindow(QWidget *parent) :
}else{} }else{}
logger = new Logger(this, QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite-wallet.log")); logger = new Logger(this, QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite-wallet.log"));
// Check for encryption // Check for encryption
if(fileExists(dirwalletenc)) if(fileExists(dirwalletenc))
{ {
qDebug() << __func__ << ": decrypting wallet=" << dirwalletenc;
this->removeWalletEncryptionStartUp(); this->removeWalletEncryptionStartUp();
} }
ui->memoTxtChat->setAutoFillBackground(false); ui->memoTxtChat->setAutoFillBackground(false);
ui->memoTxtChat->setPlaceholderText("Send Message (you can only write messages after the initial message from your contact)"); // TODO: make this HTML with some emoji
ui->memoTxtChat->setPlaceholderText("Send Memo (you can only write memo after the initial message from your contact)");
ui->memoTxtChat->setTextColor(Qt::white); ui->memoTxtChat->setTextColor(Qt::white);
// Status Bar // Status Bar
@ -115,7 +117,7 @@ MainWindow::MainWindow(QWidget *parent) :
// File a bug // File a bug
QObject::connect(ui->actionFile_a_bug, &QAction::triggered, [=]() { QObject::connect(ui->actionFile_a_bug, &QAction::triggered, [=]() {
QDesktopServices::openUrl(QUrl("https://git.hush.is/hush/SilentDragonLite/issues/new")); QDesktopServices::openUrl(QUrl("https://hush.is/tg_support"));
}); });
// Set up check for updates action // Set up check for updates action
@ -168,24 +170,13 @@ MainWindow::MainWindow(QWidget *parent) :
// Rescan // Rescan
QObject::connect(ui->actionRescan, &QAction::triggered, [=]() { QObject::connect(ui->actionRescan, &QAction::triggered, [=]() {
/* QFile file(dirwalletenc);
QFile file1(dirwallet);
if(fileExists(dirwalletenc))
{
file.remove();
file1.remove();
}*/
Ui_Restore restoreSeed; Ui_Restore restoreSeed;
QDialog dialog(this); QDialog dialog(this);
restoreSeed.setupUi(&dialog); restoreSeed.setupUi(&dialog);
Settings::saveRestore(&dialog); Settings::saveRestore(&dialog);
rpc->fetchSeed([=](json reply) { rpc->fetchSeed([=](json reply) {
if (isJsonError(reply)) { if (isJsonError(reply)) {
return; return;
} }
@ -197,7 +188,7 @@ MainWindow::MainWindow(QWidget *parent) :
QString birthday = QString::number(reply["birthday"].get<json::number_unsigned_t>()); QString birthday = QString::number(reply["birthday"].get<json::number_unsigned_t>());
restoreSeed.birthday->setPlainText(birthday); restoreSeed.birthday->setPlainText(birthday);
}); });
QObject::connect(restoreSeed.restore, &QPushButton::clicked, [&](){ QObject::connect(restoreSeed.restore, &QPushButton::clicked, [&](){
@ -554,10 +545,8 @@ void MainWindow::removeWalletEncryption() {
QObject::connect(ed.txtConfirmPassword, &QLineEdit::textChanged, fnPasswordEdited); QObject::connect(ed.txtConfirmPassword, &QLineEdit::textChanged, fnPasswordEdited);
QObject::connect(ed.txtPassword, &QLineEdit::textChanged, fnPasswordEdited); QObject::connect(ed.txtPassword, &QLineEdit::textChanged, fnPasswordEdited);
if (d.exec() == QDialog::Accepted) if (d.exec() == QDialog::Accepted) {
{
QString passphraseBlank = ed.txtPassword->text(); // data comes from user inputs QString passphraseBlank = ed.txtPassword->text(); // data comes from user inputs
QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL"); QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL");
int length = passphrase.length(); int length = passphrase.length();
@ -574,18 +563,17 @@ void MainWindow::removeWalletEncryption() {
#define hash ((const unsigned char *) sequence1) #define hash ((const unsigned char *) sequence1)
#define PASSWORD sequence #define PASSWORD sequence
#define KEY_LEN crypto_box_SEEDBYTES #define KEY_LEN crypto_box_SEEDBYTES
unsigned char key[KEY_LEN]; unsigned char key[KEY_LEN];
if (crypto_pwhash if (crypto_pwhash(key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
(key, sizeof key, PASSWORD, strlen(PASSWORD), hash, crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE, crypto_pwhash_ALG_DEFAULT) != 0) {
crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */ /* out of memory */
} qDebug() << "crypto_pwhash failed!";
return;
}
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
@ -598,9 +586,7 @@ void MainWindow::removeWalletEncryption() {
QFile filencrypted(dirwalletenc); QFile filencrypted(dirwalletenc);
QFile wallet(dirwallet); QFile wallet(dirwallet);
if (wallet.size() > 0) if (wallet.size() > 0) {
{
QMessageBox::information(this, tr("Wallet decryption Success"), QMessageBox::information(this, tr("Wallet decryption Success"),
QString("Successfully delete the encryption"), QString("Successfully delete the encryption"),
QMessageBox::Ok QMessageBox::Ok
@ -608,7 +594,7 @@ void MainWindow::removeWalletEncryption() {
filencrypted.remove(); filencrypted.remove();
}else{ } else {
QMessageBox::critical(this, tr("Wallet Encryption Failed"), QMessageBox::critical(this, tr("Wallet Encryption Failed"),
QString("False password, please try again"), QString("False password, please try again"),
@ -840,7 +826,7 @@ void MainWindow::setupSettingsModal() {
// List of default servers // List of default servers
settings.cmbServer->addItem("https://lite.hush.is"); settings.cmbServer->addItem("https://lite.hush.is");
settings.cmbServer->addItem("https://lite.hush.community"); settings.cmbServer->addItem("https://lite.hush.land");
settings.cmbServer->addItem("https://devo.crabdance.com"); settings.cmbServer->addItem("https://devo.crabdance.com");
//settings.cmbServer->addItem("https://hush.leto.net:5420"); //settings.cmbServer->addItem("https://hush.leto.net:5420");
//TODO: seperate lists of https/Tor servers, only show user or attempt //TODO: seperate lists of https/Tor servers, only show user or attempt
@ -935,7 +921,7 @@ void MainWindow::donate() {
QString key = keys->first(); QString key = keys->first();
QString key1 = key + QString(" ") + QString("0"); QString key1 = key + QString(" ") + QString("0");
keys->pop_front(); keys->pop_front();
bool rescan = keys->isEmpty(); //bool rescan = keys->isEmpty();
if (key.startsWith("SK") || key.startsWith("secret")) { if (key.startsWith("SK") || key.startsWith("secret")) {
rpc->importZPrivKey(key, [=] (auto) { this->doImport(keys); }); rpc->importZPrivKey(key, [=] (auto) { this->doImport(keys); });
@ -1205,11 +1191,6 @@ void MainWindow::addPubkey(QString requestZaddr, QString pubkey)
QString MainWindow::getPubkeyByAddress(QString requestZaddr) QString MainWindow::getPubkeyByAddress(QString requestZaddr)
{ {
for(auto& pair : this->pubkeyMap)
{
}
if(this->pubkeyMap.count(requestZaddr) > 0) if(this->pubkeyMap.count(requestZaddr) > 0)
{ {
return this->pubkeyMap[requestZaddr]; return this->pubkeyMap[requestZaddr];
@ -1363,7 +1344,7 @@ void MainWindow::setupBalancesTab() {
} }
void MainWindow::setuphushdTab() { void MainWindow::setuphushdTab() {
ui->hushdlogo->setBasePixmap(QPixmap(":/img/res/hushdlogo.gif")); ui->hushdlogo->setBasePixmap(QPixmap(":/img/res/hushdlogo.png"));
} }
void MainWindow::setupTransactionsTab() { void MainWindow::setupTransactionsTab() {
@ -1900,21 +1881,22 @@ Tx MainWindow::createTxFromSendChatPage() {
unsigned char pk[crypto_kx_PUBLICKEYBYTES]; unsigned char pk[crypto_kx_PUBLICKEYBYTES];
unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
if (crypto_kx_seed_keypair(pk,sk, if (crypto_kx_seed_keypair(pk,sk, MESSAGEAS1) !=0) {
MESSAGEAS1) !=0) { this->logger->write("Suspicious keypair, bail out ");
qDebug() << __func__ << ": Suspicious client public send key from crypto_kx_seed_keypair, aborting!";
this->logger->write("Suspicious keypair, bail out "); return tx;
} }
////////////////Get the pubkey from Bob, so we can create the share key ////////////////Get the pubkey from Bob, so we can create the share key
const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1()); const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1());
const unsigned char *pubkeyBob = reinterpret_cast<const unsigned char *>(pubkeyBobArray.constData()); const unsigned char *pubkeyBob = reinterpret_cast<const unsigned char *>(pubkeyBobArray.constData());
/////Create the shared key for sending the message /////Create the shared key for sending the message
if (crypto_kx_server_session_keys(server_rx, server_tx, if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0) {
pk, sk, pubkeyBob) != 0) { this->logger->write("Suspicious client public send key, bail out ");
this->logger->write("Suspicious client public send key, bail out "); qDebug() << __func__ << ": Suspicious client public send key from crypto_kx_server_session_keys, aborting!";
} return tx;
}
// Let's try to preserve Unicode characters // Let's try to preserve Unicode characters
@ -1953,10 +1935,8 @@ Tx MainWindow::createTxFromSendChatPage() {
/////Ciphertext Memo /////Ciphertext Memo
QString memo = QByteArray(reinterpret_cast<const char*>(ciphertext), CIPHERTEXT_LEN).toHex(); QString memo = QByteArray(reinterpret_cast<const char*>(ciphertext), CIPHERTEXT_LEN).toHex();
tx.toAddrs.push_back(ToFields{addr, amtHm, hmemo}); tx.toAddrs.push_back(ToFields{addr, amtHm, hmemo});
tx.toAddrs.push_back(ToFields{addr, amt, memo}); tx.toAddrs.push_back(ToFields{addr, amt, memo});
} }
} }
@ -2189,21 +2169,22 @@ Tx MainWindow::createTxFromSendRequestChatPage() {
unsigned char pk[crypto_kx_PUBLICKEYBYTES]; unsigned char pk[crypto_kx_PUBLICKEYBYTES];
unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
if (crypto_kx_seed_keypair(pk,sk, if (crypto_kx_seed_keypair(pk,sk, MESSAGEAS1) !=0) {
MESSAGEAS1) !=0) { this->logger->write("Suspicious keypair, bail out ");
qDebug() << __func__<< ": Suspicious client public outgoing key from crypto_kx_seed_keypair, aborting!";
this->logger->write("Suspicious keypair, bail out "); return tx;
} }
////////////////Get the pubkey from Bob, so we can create the share key ////////////////Get the pubkey from Bob, so we can create the share key
const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1()); const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1());
const unsigned char *pubkeyBob = reinterpret_cast<const unsigned char *>(pubkeyBobArray.constData()); const unsigned char *pubkeyBob = reinterpret_cast<const unsigned char *>(pubkeyBobArray.constData());
/////Create the shared key for sending the message /////Create the shared key for sending the message
if (crypto_kx_server_session_keys(server_rx, server_tx, if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0) {
pk, sk, pubkeyBob) != 0) { this->logger->write("Suspicious client public send key, bail out ");
this->logger->write("Suspicious client public send key, bail out "); qDebug() << __func__ << ": Suspicious client public send key from crypto_kx_server_session_keys, aborting!";
} return tx;
}
// Let's try to preserve Unicode characters // Let's try to preserve Unicode characters
@ -2433,7 +2414,7 @@ void MainWindow::addNewZaddr(bool sapling) {
ui->listReceiveAddresses->insertItem(0, addr); ui->listReceiveAddresses->insertItem(0, addr);
ui->listReceiveAddresses->setCurrentIndex(0); ui->listReceiveAddresses->setCurrentIndex(0);
ui->statusBar->showMessage(QString::fromStdString("Created new zAddr") % ui->statusBar->showMessage(QString::fromStdString("Created new zaddr") %
(sapling ? "(Sapling)" : "(Sprout)"), (sapling ? "(Sapling)" : "(Sprout)"),
10 * 1000); 10 * 1000);
} }
@ -2795,11 +2776,8 @@ void MainWindow::slot_change_currency(const QString& currency_name)
{ {
saved_currency_name = Settings::getInstance()->get_currency_name(); saved_currency_name = Settings::getInstance()->get_currency_name();
} } catch (...) {
catch (...) saved_currency_name = "BTC";
{
saved_currency_name = "USD";
} }
} }
@ -2861,6 +2839,8 @@ void MainWindow::on_givemeZaddr_clicked()
}); });
} }
// TODO: The way emoji work really need to change, this is madness
void MainWindow::on_emojiButton_clicked() void MainWindow::on_emojiButton_clicked()
{ {
@ -2977,8 +2957,6 @@ QObject::connect(emoji.sd, &QPushButton::clicked, [&] () {
}); });
emojiDialog.exec(); emojiDialog.exec();
} }

6
src/recurring.cpp

@ -279,7 +279,7 @@ void Recurring::updateInfoWithTx(RecurringPaymentInfo* r, Tx tx) {
r->fromAddr = tx.fromAddr; r->fromAddr = tx.fromAddr;
if (r->currency.isEmpty() || r->currency == "USD") { if (r->currency.isEmpty() || r->currency == "USD") {
r->currency = "USD"; r->currency = "USD";
r->amt = tx.toAddrs[0].amount.toqint64() * Settings::getInstance()->getZECPrice(); r->amt = tx.toAddrs[0].amount.toqint64() * Settings::getInstance()->getHUSHPrice();
} }
else { else {
r->currency = Settings::getTokenName(); r->currency = Settings::getTokenName();
@ -547,7 +547,7 @@ void Recurring::executeRecurringPayment(MainWindow* main, RecurringPaymentInfo r
double amount = rpi.amt; double amount = rpi.amt;
if (rpi.currency == "USD") { if (rpi.currency == "USD") {
// If there is no price, then fail the payment // If there is no price, then fail the payment
if (Settings::getInstance()->getZECPrice() == 0) { if (Settings::getInstance()->getHUSHPrice() == 0) {
for (auto paymentNumber: paymentNumbers) { for (auto paymentNumber: paymentNumbers) {
updatePaymentItem(rpi.getHash(), paymentNumber, updatePaymentItem(rpi.getHash(), paymentNumber,
"", QObject::tr("No hush price was available to convert from USD"), "", QObject::tr("No hush price was available to convert from USD"),
@ -559,7 +559,7 @@ void Recurring::executeRecurringPayment(MainWindow* main, RecurringPaymentInfo r
} }
// Translate it into hush // Translate it into hush
amount = rpi.amt / Settings::getInstance()->getZECPrice(); amount = rpi.amt / Settings::getInstance()->getHUSHPrice();
} }
// Build a Tx // Build a Tx

11
src/settings.cpp

@ -30,6 +30,11 @@ Config Settings::getSettings() {
bool sticky = s.value("connection/stickyServer").toBool(); bool sticky = s.value("connection/stickyServer").toBool();
bool torOnly = s.value("connection/torOnly").toBool(); bool torOnly = s.value("connection/torOnly").toBool();
while (server.endsWith("/")) {
// trailing slashes make Rust sad
server.chop(1);
}
// Users that have old configs generated from old SDLs will have this hostname // Users that have old configs generated from old SDLs will have this hostname
if(server == malicious or server == (QString("https://") + malicious)) { if(server == malicious or server == (QString("https://") + malicious)) {
qDebug() << "Replacing malicious SDL server with " << server; qDebug() << "Replacing malicious SDL server with " << server;
@ -139,8 +144,8 @@ bool Settings::isSaplingActive() {
return (isTestnet() && getBlockNumber() > 0) || (!isTestnet() && getBlockNumber() > 0); return (isTestnet() && getBlockNumber() > 0) || (!isTestnet() && getBlockNumber() > 0);
} }
double Settings::getZECPrice() { double Settings::getHUSHPrice() {
return ZECPrice; return HUSHPrice;
} }
double Settings::getEURPrice() { double Settings::getEURPrice() {
return EURPrice; return EURPrice;
@ -303,7 +308,7 @@ QString Settings::getRandomServer() {
//"https://thisisdown3.example.com", //"https://thisisdown3.example.com",
//"https://thisisdown4.example.com", //"https://thisisdown4.example.com",
//"https://thisisdown5.example.com", //"https://thisisdown5.example.com",
"https://lite.hush.community", "https://lite.hush.land"
}; };
// we don't need cryptographic random-ness, but we want // we don't need cryptographic random-ness, but we want

6
src/settings.h

@ -76,7 +76,7 @@ public:
bool isSaplingActive(); bool isSaplingActive();
void setZECPrice(double p) { ZECPrice = p; } void setHUSHPrice(double p) { HUSHPrice = p; }
void setEURPrice(double p) { EURPrice = p; } void setEURPrice(double p) { EURPrice = p; }
void setBTCPrice(double p) { BTCPrice = p; } void setBTCPrice(double p) { BTCPrice = p; }
void setCNYPrice(double p) { CNYPrice = p; } void setCNYPrice(double p) { CNYPrice = p; }
@ -109,7 +109,7 @@ public:
void setINRCAP(double p) { INRCAP = p; } void setINRCAP(double p) { INRCAP = p; }
void setGBPCAP(double p) { GBPCAP = p; } void setGBPCAP(double p) { GBPCAP = p; }
void setAUDCAP(double p) { AUDCAP = p; } void setAUDCAP(double p) { AUDCAP = p; }
double getZECPrice(); double getHUSHPrice();
double getEURPrice(); double getEURPrice();
double getBTCPrice(); double getBTCPrice();
double getCNYPrice(); double getCNYPrice();
@ -195,7 +195,7 @@ private:
bool _useEmbedded = false; bool _useEmbedded = false;
bool _headless = false; bool _headless = false;
double ZECPrice = 0.0; double HUSHPrice = 0.0;
double BTCPrice = 0.0; double BTCPrice = 0.0;
double EURPrice = 0.0; double EURPrice = 0.0;
double CNYPrice = 0.0; double CNYPrice = 0.0;

2
src/version.h

@ -1,3 +1,3 @@
// Copyright 2019-2021 The Hush developers // Copyright 2019-2021 The Hush developers
// Released under the GPLv3 // Released under the GPLv3
#define APP_VERSION "1.5.0" #define APP_VERSION "1.5.2"

5
src/websockets.cpp

@ -904,7 +904,10 @@ void AppDataServer::processGetInfo(QJsonObject jobj, MainWindow* mainWindow, std
{"maxspendable", maxSpendable.toDecimalDouble()}, {"maxspendable", maxSpendable.toDecimalDouble()},
{"maxzspendable", maxZSpendable.toDecimalDouble()}, {"maxzspendable", maxZSpendable.toDecimalDouble()},
{"tokenName", Settings::getTokenName()}, {"tokenName", Settings::getTokenName()},
{"zecprice", Settings::getInstance()->getZECPrice()}, // changing this to hushprice is a backward incompatible change that requires
// changing SDL, litewalletd and SDA in unison, and would break older clients
// so we just leave it for now
{"zecprice", Settings::getInstance()->getHUSHPrice()},
{"serverversion", QString(APP_VERSION)} {"serverversion", QString(APP_VERSION)}
}).toJson(); }).toJson();
pClient->sendTextMessage(encryptOutgoing(r)); pClient->sendTextMessage(encryptOutgoing(r));

Loading…
Cancel
Save