using json = nlohmann::json;
+
class FileSystem
{
private:
@@ -28,4 +29,4 @@ class FileSystem
};
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Model/ChatItem.cpp b/src/Model/ChatItem.cpp
index 66b5176..06d3ef7 100644
--- a/src/Model/ChatItem.cpp
+++ b/src/Model/ChatItem.cpp
@@ -158,6 +158,9 @@ QString ChatItem::toChatLine()
{
QDateTime myDateTime;
QString lock;
+ QString money;
+ QString moneyText;
+ QString moneyTextRequest;
myDateTime.setTime_t(_timestamp);
if (_notarize == true)
@@ -175,15 +178,48 @@ QString ChatItem::toChatLine()
{
lock = " ";
- }
+ }else{}
+
+ if (_memo.startsWith("Money transaction of :"))
+ {
+ if (_outgoing == true)
+ {
+
+ moneyText = QString("
") + QString("
") + QString(" Outgoing Money Transaction ") + QString(" ");
+ }else{
+
+
+ moneyText = QString("
") + QString("
") + QString(" Incoming Money Transaction ") + QString(" ");
+
+ }
+ }else{money = "";
+ moneyText = ""; }
+
+ if (_memo.startsWith("Request of :"))
+ {
+ if (_outgoing == true)
+ {
+
+ moneyTextRequest = QString("
") + QString("
") + QString(" Outgoing Hush Request ") + QString(" ");
+ }else{
+
+
+ moneyTextRequest = QString("
") + QString("
") + QString(" Incoming Hush Request ") + QString(" ");
+
+ }
+ }else{moneyTextRequest = "";
+ moneyTextRequest = ""; }
+
+
QString line = QString("") + myDateTime.toString("yyyy-MM-dd hh:mm");
- line += QString(lock) + QString("");
+ line += QString(lock) + QString(moneyText) + QString(moneyTextRequest) + QString("");
line +=QString("") + _memo.toHtmlEscaped() + QString("
");
return line;
}
+
json ChatItem::toJson()
{
json j;
@@ -203,4 +239,4 @@ json ChatItem::toJson()
ChatItem::~ChatItem()
{
-}
\ No newline at end of file
+}
diff --git a/src/Model/ChatItem.h b/src/Model/ChatItem.h
index 900c994..991868a 100644
--- a/src/Model/ChatItem.h
+++ b/src/Model/ChatItem.h
@@ -57,4 +57,4 @@ class ChatItem
~ChatItem();
};
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Model/ContactItem.cpp b/src/Model/ContactItem.cpp
index b542270..2188d05 100644
--- a/src/Model/ContactItem.cpp
+++ b/src/Model/ContactItem.cpp
@@ -95,4 +95,4 @@ json ContactItem::toJson()
j["_cid"] = _cid.toStdString();
j["_avatar"] = _avatar.toStdString();
return j;
-}
\ No newline at end of file
+}
diff --git a/src/Model/ContactItem.h b/src/Model/ContactItem.h
index e5e313d..9fdd7a4 100644
--- a/src/Model/ContactItem.h
+++ b/src/Model/ContactItem.h
@@ -37,4 +37,4 @@ public:
json toJson();
};
-#endif
\ No newline at end of file
+#endif
diff --git a/src/Model/ContactRequest.cpp b/src/Model/ContactRequest.cpp
index 3ad804f..28f1d17 100644
--- a/src/Model/ContactRequest.cpp
+++ b/src/Model/ContactRequest.cpp
@@ -93,4 +93,4 @@ void ContactRequest::clear()
ContactRequest::~ContactRequest()
{
clear();
-}
\ No newline at end of file
+}
diff --git a/src/Model/ContactRequest.h b/src/Model/ContactRequest.h
index 930ad56..5fe5fa3 100644
--- a/src/Model/ContactRequest.h
+++ b/src/Model/ContactRequest.h
@@ -37,4 +37,4 @@ class ContactRequest
~ContactRequest();
};
-#endif
\ No newline at end of file
+#endif
diff --git a/src/addressbook.cpp b/src/addressbook.cpp
index e2f481d..eb23258 100644
--- a/src/addressbook.cpp
+++ b/src/addressbook.cpp
@@ -250,6 +250,9 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target)
);
+ parent->ui->listChat->verticalScrollBar()->setValue(
+ parent->ui->listChat->verticalScrollBar()->maximum());
+
});
// AddressBook::getInstance()->addAddressLabel(newLabel, ab.addr->text(), cid);
@@ -386,25 +389,56 @@ AddressBook::AddressBook()
void AddressBook::readFromStorage()
{
- QFile file(AddressBook::writeableFile());
+ auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
+ QString target_decaddr_file = dir.filePath("addresslabels.dat");
+ QString target_encaddr_file = dir.filePath("addresslabels.dat.enc");
+ QFile file(target_encaddr_file);
+ QFile file1(target_decaddr_file);
if (file.exists())
{
+
+ // Decrypt first
+
+ QString passphraseHash = DataStore::getChatDataStore()->getPassword();
+ int length = passphraseHash.length();
+
+ char *sequence1 = NULL;
+ sequence1 = new char[length+1];
+ strncpy(sequence1, passphraseHash.toUtf8(), length+1);
+
+ #define PassphraseHashEnd ((const unsigned char *) sequence1)
+ #define MESSAGE_LEN length
+
+ #define PASSWORD sequence
+ #define KEY_LEN crypto_box_SEEDBYTES
+
+ const QByteArray ba = QByteArray::fromHex(passphraseHash.toLatin1());
+ const unsigned char *pwHash= reinterpret_cast(ba.constData());
+
+
+
+
+ FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, pwHash);
+
+
allLabels.clear();
- file.open(QIODevice::ReadOnly);
- QDataStream in(&file); // read the data serialized from the file
+ file1.open(QIODevice::ReadOnly);
+ QDataStream in(&file1); // read the data serialized from the file
QString version;
in >> version;
QList> stuff;
in >> stuff;
//////////////found old addrbook, and rename it to .bak
- if (version != "v2")
+ if (version == "v1")
{
auto filename = QStringLiteral("addresslabels.dat");
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
QFile address(dir.filePath(filename));
+ qDebug() << "is v1";
+
address.rename(dir.filePath("addresslabels.bak"));
}else{
@@ -419,21 +453,16 @@ void AddressBook::readFromStorage()
// qDebug() << "Read " << version << " Hush contacts from disk...";
- file.close();
+ file1.close();
+
+ FileEncryption::encrypt(target_encaddr_file, target_decaddr_file, pwHash);
+ file1.remove();
}
else
{
qDebug() << "No Hush contacts found on disk!";
}
- // Special.
- // Add the default silentdragon donation address if it isn't already present
- // QList allAddresses;
- // std::transform(allLabels.begin(), allLabels.end(),
- // std::back_inserter(allAddresses), [=] (auto i) { return i.getPartnerAddress(); });
- // if (!allAddresses.contains(Settings::getDonationAddr(true))) {
- // allLabels.append(QPair("silentdragon donation", Settings::getDonationAddr(true)));
- // }
}
@@ -442,12 +471,36 @@ void AddressBook::writeToStorage()
//FileSystem::getInstance()->writeContacts(AddressBook::writeableFile(), DataStore::getContactDataStore()->dump());
// FileSystem::getInstance()->writeContactsOldFormat(AddressBook::writeableFile(), allLabels);
+
+ QString passphraseHash = DataStore::getChatDataStore()->getPassword();
+ int length = passphraseHash.length();
+
+ char *sequence1 = NULL;
+ sequence1 = new char[length+1];
+ strncpy(sequence1, passphraseHash.toUtf8(), length+1);
+
+ #define PassphraseHashEnd ((const unsigned char *) sequence1)
+ #define MESSAGE_LEN length
+
+ #define PASSWORD sequence
+ #define KEY_LEN crypto_box_SEEDBYTES
+
+ const QByteArray ba = QByteArray::fromHex(passphraseHash.toLatin1());
+ const unsigned char *pwHash= reinterpret_cast(ba.constData());
+
+
-
- QFile file(AddressBook::writeableFile());
+ auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
+ QString target_encaddr_file = dir.filePath("addresslabels.dat.enc");
+ QString target_decaddr_file = dir.filePath("addresslabels.dat");
+
+ FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, pwHash);
+
+ QFile file(target_decaddr_file);
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
QDataStream out(&file); // we will serialize the data into the file
QList> contacts;
+
for(auto &item: allLabels)
{
QList c;
@@ -456,10 +509,20 @@ void AddressBook::writeToStorage()
c.push_back(item.getMyAddress());
c.push_back(item.getCid());
c.push_back(item.getAvatar());
- contacts.push_back(c);
+ contacts.push_back(c);
+
}
out << QString("v2") << contacts;
+ qDebug()<<"schreibe in Datei: ";
file.close();
+
+
+ FileEncryption::encrypt(target_encaddr_file, target_decaddr_file , pwHash);
+ QFile file1(target_decaddr_file);
+ file1.remove();
+
+ qDebug()<<"encrypt Addrbook writeToStorage";
+
}
QString AddressBook::writeableFile()
diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp
index f5bf1b6..63146fc 100644
--- a/src/chatmodel.cpp
+++ b/src/chatmodel.cpp
@@ -163,7 +163,7 @@ void MainWindow::renderContactRequest(){
- if ((c.second.isOutgoing() == false) && (label_contact == c.second.getRequestZaddr()))
+ if ((c.second.isOutgoing() == false) && (label_contact == c.second.getRequestZaddr() && (c.second.getMemo().startsWith("{") == false)))
{
@@ -194,12 +194,12 @@ void MainWindow::renderContactRequest(){
QString label_contactold = index.data(Qt::DisplayRole).toString();
QStandardItemModel* contactMemo = new QStandardItemModel();
- if ((c.second.isOutgoing() == false) && (label_contactold == c.second.getContact()))
+ if ((c.second.isOutgoing() == false) && (label_contactold == c.second.getContact()) && (c.second.getMemo().startsWith("{") == false))
{
QStandardItem* Items = new QStandardItem(c.second.getMemo());
- contactMemo->appendRow(Items);
+ contactMemo->appendRow(Items);
requestContact.requestMemo->setModel(contactMemo);
requestContact.requestMemo->show();
@@ -255,7 +255,7 @@ void MainWindow::renderContactRequest(){
ui->listContactWidget);
QMessageBox::information(this, "Added Contact","successfully added your new contact. You can now Chat with this contact");
-
+ dialog.close();
});
dialog.exec();
@@ -433,8 +433,6 @@ Tx MainWindow::createTxFromChatPage() {
QString myAddr = c.getMyAddress();
QString type = "Memo";
QString addr = c.getPartnerAddress();
-
-
/////////User input for chatmemos
QString memoplain = ui->memoTxtChat->toPlainText().trimmed();
@@ -443,43 +441,31 @@ Tx MainWindow::createTxFromChatPage() {
int lengthmemo = memoplain.length();
char *memoplainchar = NULL;
- memoplainchar = new char[lengthmemo+1];
- strncpy(memoplainchar, memoplain.toLocal8Bit(), lengthmemo +1);
-
- /////////We convert the CID from QString to unsigned char*, so we can encrypt it later
- int lengthcid = cid.length();
-
- char *cidchar = NULL;
- cidchar = new char[lengthcid+1];
- strncpy(cidchar, cid.toLocal8Bit(), lengthcid +1);
-
-
-
- QString pubkey = this->getPubkeyByAddress(addr);
- QString passphrase = DataStore::getChatDataStore()->getPassword();
- QString hashEncryptionKey = passphrase;
- int length = hashEncryptionKey.length();
+ memoplainchar = new char[lengthmemo+2];
+ strncpy(memoplainchar, memoplain.toUtf8(), lengthmemo +1);
+ QString pubkey = this->getPubkeyByAddress(addr);
+ QString passphraseHash = DataStore::getChatDataStore()->getPassword();
+ int length = passphraseHash.length();
////////////////Generate the secretkey for our message encryption
- char *hashEncryptionKeyraw = NULL;
- hashEncryptionKeyraw = new char[length+1];
- strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1);
+ char *hashEncryptionKeyraw = NULL;
+ hashEncryptionKeyraw = new char[length+1];
+ strncpy(hashEncryptionKeyraw, passphraseHash.toUtf8(), length+1);
#define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)
#define MESSAGEAS1_LEN length
- unsigned char hash[crypto_kx_SEEDBYTES];
-
- crypto_hash_sha256(hash,MESSAGEAS1, MESSAGEAS1_LEN);
-
+
unsigned char sk[crypto_kx_SECRETKEYBYTES];
unsigned char pk[crypto_kx_PUBLICKEYBYTES];
unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
if (crypto_kx_seed_keypair(pk,sk,
- hash) !=0) {
+ MESSAGEAS1) !=0) {
+
+ this->logger->write("Suspicious keypair, bail out ");
}
////////////////Get the pubkey from Bob, so we can create the share key
@@ -489,14 +475,21 @@ Tx MainWindow::createTxFromChatPage() {
if (crypto_kx_server_session_keys(server_rx, server_tx,
pk, sk, pubkeyBob) != 0) {
- /* Suspicious client public key, bail out */
+ this->logger->write("Suspicious client public send key, bail out ");
}
+ // Let's try to preserve Unicode characters
+ QByteArray ba_memo = memoplain.toUtf8();
+ int ba_memo_length = ba_memo.size();
+
+ #define MESSAGE (const unsigned char *) ba_memo.data()
+ #define MESSAGE_LEN ba_memo_length
+
////////////Now lets encrypt the message Alice send to Bob//////////////////////////////
- #define MESSAGE (const unsigned char *) memoplainchar
- #define MESSAGE_LEN lengthmemo
+ //#define MESSAGE (const unsigned char *) memoplainchar
+ //#define MESSAGE_LEN lengthmemo
#define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LEN)
unsigned char ciphertext[CIPHERTEXT_LEN];
unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
@@ -521,8 +514,7 @@ Tx MainWindow::createTxFromChatPage() {
/////Ciphertext Memo
QString memo = QByteArray(reinterpret_cast(ciphertext), CIPHERTEXT_LEN).toHex();
-
-
+
tx.toAddrs.push_back(ToFields{addr, amt, hmemo});
tx.toAddrs.push_back(ToFields{addr, amt, memo});
@@ -549,6 +541,7 @@ void MainWindow::sendChat() {
QMessageBox msg(QMessageBox::Critical, tr("You have to select a contact and insert a Memo"),
tr("You have selected no Contact from Contactlist,\n") + tr("\nor your Memo is empty"),
QMessageBox::Ok, this);
+ ui->memoTxtChat->setEnabled(true);
msg.exec();
return;
@@ -578,6 +571,7 @@ void MainWindow::sendChat() {
QMessageBox::Ok, this);
msg.exec();
+ ui->memoTxtChat->setEnabled(true);
// abort the Tx
return;
@@ -597,6 +591,7 @@ void MainWindow::sendChat() {
movie->start();
ui->sendChatButton->show();
ui->sendChatButton->setEnabled(false);
+ ui->memoTxtChat->setEnabled(true);
} else {
@@ -606,6 +601,8 @@ void MainWindow::sendChat() {
movie1->start();
ui->sendChatButton->show();
ui->sendChatButton->setEnabled(false);
+ ui->memoTxtChat->setEnabled(true);
+
}
ui->memoTxtChat->clear();
@@ -624,6 +621,8 @@ void MainWindow::sendChat() {
ui->sendChatButton->setIcon(sendIcon);
movie->stop();
ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
+
}else{
QPixmap send(":/icons/res/sendBlack.png");
@@ -631,6 +630,7 @@ void MainWindow::sendChat() {
ui->sendChatButton->setIcon(sendIcon);
movie1->stop();
ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
}
});
@@ -643,6 +643,7 @@ void MainWindow::sendChat() {
// Errored out
[=] (QString opid, QString errStr) {
ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000);
+ ui->memoTxtChat->setEnabled(true);
if (!opid.isEmpty())
errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
@@ -657,6 +658,7 @@ void MainWindow::sendChat() {
ui->sendChatButton->setIcon(sendIcon);
movie->stop();
ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
}else{
QPixmap send(":/icons/res/sendBlack.png");
@@ -664,6 +666,7 @@ void MainWindow::sendChat() {
ui->sendChatButton->setIcon(sendIcon);
movie1->stop();
ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
}
@@ -681,6 +684,7 @@ QString MainWindow::doSendChatTxValidations(Tx tx) {
if (!Settings::isValidAddress(toAddr.addr)) {
QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr);
return QString(tr("Recipient Address ")) % addr % tr(" is Invalid");
+ ui->memoTxtChat->setEnabled(true);
}
// This technically shouldn't be possible, but issue #62 seems to have discovered a bug
@@ -698,6 +702,7 @@ QString MainWindow::doSendChatTxValidations(Tx tx) {
if (available < total) {
return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent")
.arg(available.toDecimalhushString(), total.toDecimalhushString());
+ ui->memoTxtChat->setEnabled(true);
}
return "";
@@ -710,9 +715,11 @@ void::MainWindow::addContact()
request.setupUi(&dialog);
Settings::saveRestore(&dialog);
-QObject::connect(request.newZaddr, &QPushButton::clicked, [&] () {
- try
+ request.memorequest->setLenDisplayLabelChatRequest(request.memoSizeChatRequest);
+
+ try
{
+
bool sapling = true;
rpc->createNewZaddr(sapling, [=] (json reply) {
QString myAddr = QString::fromStdString(reply.get()[0]);
@@ -720,6 +727,10 @@ QObject::connect(request.newZaddr, &QPushButton::clicked, [&] () {
request.myzaddr->setText(myAddr);
ui->listReceiveAddresses->insertItem(0, myAddr);
ui->listReceiveAddresses->setCurrentIndex(0);
+ DataStore::getChatDataStore()->setSendZaddr(myAddr);
+
+
+ qDebug()<<"Zaddr: "<text();
@@ -748,78 +758,67 @@ QObject::connect(request.newZaddr, &QPushButton::clicked, [&] () {
contactRequest.setAvatar(avatar);
contactRequest.setLabel(label);
- });
-
- QObject::connect(request.sendRequestButton, &QPushButton::clicked, this, &MainWindow::saveandsendContact);
- // QObject::connect(request.onlyAdd, &QPushButton::clicked, this, &MainWindow::saveContact);
+ });
+
+
+ QObject::connect(request.sendRequestButton, &QPushButton::clicked, this, &MainWindow::saveandsendContact);
+
+ // QObject::connect(request.onlyAdd, &QPushButton::clicked, this, &MainWindow::saveContact);
dialog.exec();
-
rpc->refreshContacts(ui->listContactWidget);
-
}
void MainWindow::saveandsendContact()
{
- this->ContactRequest();
-
+ this->ContactRequest();
}
// Create a Tx for a contact Request
Tx MainWindow::createTxForSafeContactRequest()
{
Tx tx;
-{
- CAmount totalAmt;
- QString amtStr = "0";
- CAmount amt;
- QString headerbytes = "";
- amt = CAmount::fromDecimalString("0");
- totalAmt = totalAmt + amt;
+ {
+ CAmount totalAmt;
+ QString amtStr = "0";
+ CAmount amt;
+ QString headerbytes = "";
+ amt = CAmount::fromDecimalString("0");
+ totalAmt = totalAmt + amt;
- QString cid = contactRequest.getCid();
- QString myAddr = contactRequest.getSenderAddress();
- QString type = "Cont";
- QString addr = contactRequest.getReceiverAddress();
+ QString cid = contactRequest.getCid();
+ QString myAddr = DataStore::getChatDataStore()->getSendZaddr();
+ QString type = "Cont";
+ QString addr = contactRequest.getReceiverAddress();
-
- QString memo = contactRequest.getMemo();
- // QString privkey = rpc->fetchPrivKey(myAddr);
- QString passphrase = DataStore::getChatDataStore()->getPassword();
- QString hashEncryptionKey = passphrase;
- int length = hashEncryptionKey.length();
- ////////////////Generate the secretkey for our message encryption
- char *hashEncryptionKeyraw = NULL;
- hashEncryptionKeyraw = new char[length+1];
- strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1);
- #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)
- #define MESSAGEAS1_LEN length
+ QString memo = contactRequest.getMemo();
+ QString passphrase = DataStore::getChatDataStore()->getPassword();
+ int length = passphrase.length();
-
- unsigned char hash[crypto_kx_SEEDBYTES];
+////////////////Generate the secretkey for our message encryption
+ char *hashEncryptionKeyraw = NULL;
+ hashEncryptionKeyraw = new char[length+1];
+ strncpy(hashEncryptionKeyraw, passphrase.toUtf8(), length +1);
- crypto_hash_sha256(hash,MESSAGEAS1, MESSAGEAS1_LEN);
+ #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)
+ #define MESSAGEAS1_LEN length
+ unsigned char sk[crypto_kx_SECRETKEYBYTES];
+ unsigned char pk[crypto_kx_PUBLICKEYBYTES];
- unsigned char sk[crypto_kx_SECRETKEYBYTES];
- unsigned char pk[crypto_kx_PUBLICKEYBYTES];
-
- if (crypto_kx_seed_keypair(pk,sk,
- hash) !=0) {
- }
+ if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) {
+ this->logger->write("Suspicious client public contact request key, bail out ");
+ }
- QString publicKey = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex();
+ QString publicKey = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex();
+ QString hmemo= createHeaderMemo(type,cid,myAddr,"", publicKey);
- QString hmemo= createHeaderMemo(type,cid,myAddr,"", publicKey);
+ tx.toAddrs.push_back(ToFields{addr, amt, hmemo});
+ tx.toAddrs.push_back(ToFields{addr, amt, memo});
+ tx.fee = Settings::getMinerFee();
+ }
-
- tx.toAddrs.push_back(ToFields{addr, amt, hmemo});
- tx.toAddrs.push_back(ToFields{addr, amt, memo});
- tx.fee = Settings::getMinerFee();
-
-}
-
return tx;
}
@@ -835,26 +834,14 @@ void MainWindow::ContactRequest() {
return;
}
- if (contactRequest.getSenderAddress().size() > 80) {
-
- QMessageBox msg(QMessageBox::Critical, tr("Missing HushChat Address"),
- tr("You have to create your HushChat address to send a contact request,\n"),
- QMessageBox::Ok, this);
-
- msg.exec();
- return;
- }
-
- int max = 235;
+ int max = 512;
QString chattext = contactRequest.getMemo();;
int size = chattext.size();
if (size > max){
- // auto addr = "";
- // if (! Settings::isZAddress(AddressBook::addressFromAddressLabel(addr->text()))) {
QMessageBox msg(QMessageBox::Critical, tr("Your Message is too long"),
- tr("You can only write messages with 235 character maximum \n") + tr("\n Please reduce your message to 235 character."),
+ tr("You can only write messages with 512 character maximum \n") + tr("\n Please reduce your message to 235 character."),
QMessageBox::Ok, this);
msg.exec();
diff --git a/src/connection.cpp b/src/connection.cpp
index 569ebed..163be4b 100644
--- a/src/connection.cpp
+++ b/src/connection.cpp
@@ -10,6 +10,16 @@
using json = nlohmann::json;
+#ifdef Q_OS_WIN
+auto dirwalletconnection = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet.dat");
+#endif
+#ifdef Q_OS_MACOS
+auto dirwalletconnection = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet.dat");
+#endif
+#ifdef Q_OS_LINUX
+auto dirwalletconnection = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".silentdragonlite/silentdragonlite-wallet.dat");
+#endif
+
ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc)
{
this->main = main;
@@ -59,7 +69,6 @@ void ConnectionLoader::doAutoConnect()
{
qDebug() << "Doing autoconnect";
auto config = std::shared_ptr(new ConnectionConfig());
- config->dangerous = false;
config->server = Settings::getInstance()->getSettings().server;
// Initialize the library
@@ -70,7 +79,6 @@ void ConnectionLoader::doAutoConnect()
{
main->logger->write(QObject::tr("Using existing wallet."));
char* resp = litelib_initialize_existing(
- config->dangerous,
config->server.toStdString().c_str()
);
QString response = litelib_process_response(resp);
@@ -85,7 +93,7 @@ void ConnectionLoader::doAutoConnect()
else
{
main->logger->write(QObject::tr("Create/restore wallet."));
- createOrRestore(config->dangerous, config->server);
+ createOrRestore(config->server);
d->show();
}
@@ -97,13 +105,16 @@ void ConnectionLoader::doAutoConnect()
// If success, set the connection
main->logger->write("Connection is online.");
connection->setInfo(reply);
+ main->logger->write("getting Connection reply");
isSyncing = new QAtomicInteger();
- isSyncing->store(true);
+ isSyncing->storeRelaxed(true);
+ main->logger->write("isSyncing");
// Do a sync at startup
syncTimer = new QTimer(main);
+ main->logger->write("Beginning sync");
connection->doRPCWithDefaultErrorHandling("sync", "", [=](auto) {
- isSyncing->store(false);
+ isSyncing->storeRelaxed(false);
// Cancel the timer
syncTimer->deleteLater();
// When sync is done, set the connection
@@ -113,10 +124,13 @@ void ConnectionLoader::doAutoConnect()
// While it is syncing, we'll show the status updates while it is alive.
QObject::connect(syncTimer, &QTimer::timeout, [=]() {
// Check the sync status
- if (isSyncing != nullptr && isSyncing->load()) {
+ if (isSyncing != nullptr && isSyncing->loadRelaxed()) {
// Get the sync status
+
+ try {
connection->doRPC("syncstatus", "", [=](json reply) {
if (isSyncing != nullptr && reply.find("synced_blocks") != reply.end())
+
{
qint64 synced = reply["synced_blocks"].get();
qint64 total = reply["total_blocks"].get();
@@ -128,32 +142,56 @@ void ConnectionLoader::doAutoConnect()
[=](QString err) {
qDebug() << "Sync error" << err;
});
+ }catch (...)
+ {
+ main->logger->write("catch sync progress reply");
+
+ }
+
}
});
syncTimer->setInterval(1* 1000);
syncTimer->start();
+ main->logger->write("Start sync timer");
}, [=](QString err) {
showError(err);
});
}
-void ConnectionLoader::createOrRestore(bool dangerous, QString server)
+void ConnectionLoader::createOrRestore(QString server)
{
// Close the startup dialog, since we'll be showing the wizard
d->hide();
// Create a wizard
- FirstTimeWizard wizard(dangerous, server);
+ FirstTimeWizard wizard(server);
+ main->logger->write("Start new Wallet with FirstimeWizard");
wizard.exec();
}
void ConnectionLoader::doRPCSetConnection(Connection* conn)
{
qDebug() << "Connectionloader finished, setting connection";
+ main->logger->write("Connectionloader finished, setting connection");
rpc->setConnection(conn);
d->accept();
QTimer::singleShot(1, [=]() { delete this; });
+
+try
+{
+
+ QFile plaintextWallet(dirwalletconnection);
+ main->logger->write("Path to Wallet.dat : " );
+ plaintextWallet.remove();
+
+}catch (...)
+
+{
+
+ main->logger->write("no Plaintext wallet.dat");
+}
+
}
Connection* ConnectionLoader::makeConnection(std::shared_ptr config)
@@ -202,7 +240,6 @@ void Executor::run()
{
char* resp = litelib_execute(this->cmd.toStdString().c_str(), this->args.toStdString().c_str());
QString reply = litelib_process_response(resp);
- //qDebug() << "RPC Reply=" << reply;
auto parsed = json::parse(
reply.toStdString().c_str(),
nullptr,
@@ -212,7 +249,8 @@ void Executor::run()
emit handleError(reply);
else
- emit responseReady(parsed);
+
+ emit responseReady(parsed);
}
diff --git a/src/connection.h b/src/connection.h
index 7130710..715fd1d 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -5,14 +5,12 @@
#include "ui_connection.h"
#include "precompiled.h"
-
using json = nlohmann::json;
class Controller;
struct ConnectionConfig {
QString server;
- bool dangerous;
QString proxy;
};
@@ -34,7 +32,7 @@ private:
void doAutoConnect();
- void createOrRestore(bool dangerous, QString server);
+ void createOrRestore(QString server);
void showError(QString explanation);
void showInformation(QString info, QString detail = "");
@@ -64,7 +62,7 @@ public slots:
void processRPCCallback(json resp);
void processError(QString error);
-private:
+private:
std::function cb;
std::function errCb;
@@ -73,14 +71,14 @@ private:
/**
* A runnable that runs some lightclient Command in a non-UI thread.
* It emits the "responseReady" signal, which should be processed in a GUI thread.
- *
+ *
* Since the autoDelete flag is ON, the runnable should be destroyed automatically
- * by the threadpool.
+ * by the threadpool.
*/
class Executor : public QObject, public QRunnable {
Q_OBJECT
-public:
+public:
Executor(QString cmd, QString args) {
this->cmd = cmd;
this->args = args;
@@ -97,7 +95,7 @@ signals:
private:
QString cmd;
- QString args;
+ QString args;
};
/**
@@ -116,8 +114,8 @@ public:
void shutdown();
-
- void doRPC(const QString cmd, const QString args, const std::function& cb,
+
+ void doRPC(const QString cmd, const QString args, const std::function& cb,
const std::function& errCb);
void doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function& cb);
void doRPCIgnoreError(const QString cmd, const QString args, const std::function& cb) ;
diff --git a/src/contactrequest.ui b/src/contactrequest.ui
index d187eb1..62699d3 100644
--- a/src/contactrequest.ui
+++ b/src/contactrequest.ui
@@ -122,22 +122,6 @@
- -
-
-
-
- 0
- 0
-
-
-
- Create New Address
-
-
- false
-
-
-
-
@@ -394,7 +378,7 @@
-
-
+
0
@@ -407,7 +391,7 @@
-
-
+
Add a memo to your request
@@ -453,6 +437,13 @@
+
+
+ ChatMemoEditRequest
+ QTextEdit
+
+
+
diff --git a/src/controller.cpp b/src/controller.cpp
index 7ce4c2d..e14e32d 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -17,6 +17,7 @@ ContactModel *contactModel = new ContactModel();
using json = nlohmann::json;
+
Controller::Controller(MainWindow* main)
{
auto cl = new ConnectionLoader(main, this);
@@ -102,6 +103,9 @@ void Controller::setConnection(Connection* c)
ui->listContactWidget
);
+
+ ui->listChat->verticalScrollBar()->setValue(
+ ui->listChat->verticalScrollBar()->maximum());
}
std::string Controller::encryptDecrypt(std::string toEncrypt)
@@ -121,7 +125,7 @@ std::string Controller::encryptDecrypt(std::string toEncrypt)
}
// Build the RPC JSON Parameters for this tx
-void Controller::fillTxJsonParams(json& allRecepients, Tx tx)
+void Controller::fillTxJsonParams(json& allRecepients, Tx tx)
{
Q_ASSERT(allRecepients.is_array());
@@ -141,12 +145,11 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx)
DataStore::getSietchDataStore()->setData(QString("Sietch") + QString(i), zdust.toUtf8());
} );
}
-
// Set sietch zdust addr to json.
- // Using DataStore singelton, to store the data into the dusts, bing bada boom :D
+ // Using DataStore singelton, to store the data into the dust.
for(uint8_t i = 0; i < 6; i++)
{
- dust.at(i)["address"] = DataStore::getSietchDataStore()->getData(QString("Sietch" + QString(i))).toStdString();
+ dust.at(i)["address"] = DataStore::getSietchDataStore()->getData(QString("Sietch" + QString(i))).toStdString();
}
DataStore::getSietchDataStore()->clear(); // clears the datastore
@@ -157,42 +160,41 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx)
const int randomStringLength = sizerandomString;
QString randomString;
+ QRandomGenerator *gen = QRandomGenerator::system();
for(int i=0; ibounded(0, possibleCharacters.length() - 1);
QChar nextChar = possibleCharacters.at(index);
randomString.append(nextChar);
}
-
- for(uint8_t i = 0; i < 6; i++)
+
+ for(uint8_t i = 0; i < 6; i++)
{
int length = randomString.length();
int randomSize = rand() % 120 +10;
-
char *randomHash = NULL;
randomHash = new char[length+1];
strncpy(randomHash, randomString.toLocal8Bit(), length +1);
-
#define MESSAGE ((const unsigned char *) randomHash)
#define MESSAGE_LEN length
#define MESSAGE_LEN1 length + randomSize
+
+ unsigned char hash[crypto_secretstream_xchacha20poly1305_ABYTES];
-unsigned char hash[crypto_secretstream_xchacha20poly1305_ABYTES];
-
-crypto_generichash(hash, sizeof hash,
+ crypto_generichash(hash, sizeof hash,
MESSAGE, MESSAGE_LEN1,
NULL, 0);
-std::string decryptedMemo(reinterpret_cast(hash),MESSAGE_LEN1);
-std::string encrypt = this->encryptDecrypt(decryptedMemo);
-QString randomHashafter1 = QByteArray(reinterpret_cast(encrypt.c_str()),encrypt.size()).toHex();
-dust.at(i)["memo"] = randomHashafter1.toStdString();
-
- }
+ std::string decryptedMemo(reinterpret_cast(hash),MESSAGE_LEN1);
+ std::string encrypt = this->encryptDecrypt(decryptedMemo);
+ QString randomHashafter1 = QByteArray(reinterpret_cast(encrypt.c_str()),encrypt.size()).toHex();
+ dust.at(i)["memo"] = randomHashafter1.toStdString();
+ }
- for(uint8_t i = 0; i < 6; i++)
+ for(auto &it: dust)
{
- dust.at(i)["amount"] = 0;
+ it["amount"] = 0;
}
@@ -205,18 +207,20 @@ dust.at(i)["memo"] = randomHashafter1.toStdString();
if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.trimmed().isEmpty())
rec["memo"] = toAddr.memo.toStdString();
- allRecepients.push_back(rec) ;
+ allRecepients.push_back(rec);
}
- allRecepients.insert(std::begin(allRecepients), {
+ allRecepients.insert(std::begin(allRecepients), {
dust.at(0),
dust.at(1),
dust.at(2),
dust.at(3),
dust.at(4),
dust.at(5)
-
+
}) ;
+
+ qDebug()<<"ADDR DUST";
}
void Controller::noConnection()
@@ -257,11 +261,11 @@ void Controller::refresh(bool force)
getInfoThenRefresh(force);
}
-void Controller::processInfo(const json& info)
+void Controller::processInfo(const json& info)
{
// Testnet?
QString chainName;
- if (!info["chain_name"].is_null())
+ if (!info["chain_name"].is_null())
{
chainName = QString::fromStdString(info["chain_name"].get());
Settings::getInstance()->setTestnet(chainName == "test");
@@ -282,18 +286,16 @@ void Controller::getInfoThenRefresh(bool force)
static bool prevCallSucceeded = false;
- zrpc->fetchInfo([=] (const json& reply) {
+ zrpc->fetchInfo([=] (const json& reply) {
prevCallSucceeded = true;
int curBlock = reply["latest_block_height"].get();
bool doUpdate = force || (model->getLatestBlock() != curBlock);
int difficulty = reply["difficulty"].get();
int blocks_until_halving= 340000 - curBlock;
- int halving_days = (blocks_until_halving * 150) / (60*60*24) ;
+ int halving_days = (blocks_until_halving * 150) / (60 * 60 * 24) ;
int longestchain = reply["longestchain"].get();
int notarized = reply["notarized"].get();
-
-
model->setLatestBlock(curBlock);
if (
Settings::getInstance()->get_currency_name() == "EUR" ||
@@ -309,11 +311,7 @@ void Controller::getInfoThenRefresh(bool force)
);
ui->longestchain->setText(
"Block: " + QLocale(QLocale::German).toString(longestchain)
-
);
-
-
-
ui->difficulty->setText(
QLocale(QLocale::German).toString(difficulty)
);
@@ -342,12 +340,9 @@ void Controller::getInfoThenRefresh(bool force)
);
}
- ui->Version->setText(
- QString::fromStdString(reply["version"].get())
- );
- ui->Vendor->setText(
- QString::fromStdString(reply["vendor"].get())
- );
+ ui->Version->setText(QString::fromStdString(reply["version"].get()));
+ ui->Vendor->setText(QString::fromStdString(reply["vendor"].get()));
+
main->logger->write(
QString("Refresh. curblock ") % QString::number(curBlock) % ", update=" % (doUpdate ? "true" : "false")
);
@@ -359,7 +354,6 @@ void Controller::getInfoThenRefresh(bool force)
QString chainName = Settings::getInstance()->isTestnet() ? "test" : "main";
main->statusLabel->setText(chainName + "(" + QString::number(curBlock) + ")");
-
// use currency ComboBox as input
if (Settings::getInstance()->get_currency_name() == "USD")
@@ -377,8 +371,6 @@ void Controller::getInfoThenRefresh(bool force)
" $ " + (QLocale(QLocale::English).toString(cap,'f', 2))
);
-
-
}
else if (Settings::getInstance()->get_currency_name() == "EUR")
{
@@ -568,7 +560,7 @@ void Controller::getInfoThenRefresh(bool force)
zrpc->fetchSupply([=] (const json& reply) {
int supply = reply["supply"].get();
int zfunds = reply["zfunds"].get();
- int total = reply["total"].get();
+ int total = reply["total"].get();;
if (
Settings::getInstance()->get_currency_name() == "EUR" ||
Settings::getInstance()->get_currency_name() == "CHF" ||
@@ -595,7 +587,7 @@ void Controller::getInfoThenRefresh(bool force)
refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans()
refreshTransactions();
}
-
+ refreshBalances();
int lag = longestchain - notarized ;
this->setLag(lag);
}, [=](QString err) {
@@ -652,7 +644,7 @@ void Controller::refreshAddresses()
model->replaceZaddresses(newzaddresses);
auto taddrs = reply["t_addresses"].get();
- for (auto& it : taddrs)
+ for (auto& it : taddrs)
{
auto addr = QString::fromStdString(it.get());
if (Settings::isTAddress(addr))
@@ -690,7 +682,7 @@ void Controller::processUnspent(const json& reply, QMap* balan
CAmount amount = CAmount::fromqint64(it["value"].get());
bool spendable = it["unconfirmed_spent"].is_null() && it["spent"].is_null(); // TODO: Wait for 1 confirmations
- bool pending = !it["unconfirmed_spent"].is_null();
+ bool pending = !it["unconfirmed_spent"].is_null();;
unspentOutputs->push_back(
UnspentOutput{ qsAddr, txid, amount, block, spendable, pending }
@@ -878,7 +870,6 @@ void Controller::refreshBalances()
CAmount balAvailable = balT + balVerified;
model->setAvailableBalance(balAvailable);
updateUIBalances();
-
});
// 2. Get the UTXOs
@@ -916,7 +907,8 @@ void Controller::refreshTransactions() {
zrpc->fetchTransactions([=] (json reply) {
QList txdata;
- for (auto& it : reply.get()) {
+ for (auto& it : reply.get()) {
+ {
QString address;
CAmount total_amount;
QList items;
@@ -924,204 +916,195 @@ void Controller::refreshTransactions() {
long confirmations;
if (it.find("unconfirmed") != it.end() && it["unconfirmed"].get()) {
confirmations = 0;
- } else {
+ }else{
confirmations = model->getLatestBlock() - it["block_height"].get() + 1;
}
+
auto txid = QString::fromStdString(it["txid"]);
auto datetime = it["datetime"].get();
-
+
// First, check if there's outgoing metadata
if (!it["outgoing_metadata"].is_null()) {
for (auto o: it["outgoing_metadata"].get())
- {
- // if (chatModel->getCidByTx(txid) == QString("0xdeadbeef")){
- QString address;
+
+ {
+ // if (chatModel->getCidByTx(txid) == QString("0xdeadbeef")){
+ QString address;
address = QString::fromStdString(o["address"]);
-
+
// Sent items are -ve
- CAmount amount = CAmount::fromqint64(-1* o["value"].get());
+ CAmount amount = CAmount::fromqint64(-1* o["value"].get());
- // Check for Memos
-
- if (confirmations == 0) {
- chatModel->addconfirmations(txid, confirmations);
- }
-
- if ((confirmations == 1) && (chatModel->getConfirmationByTx(txid) != QString("0xdeadbeef"))){
- DataStore::getChatDataStore()->clear();
- chatModel->killConfirmationCache();
- chatModel->killMemoCache();
- this->refresh(true);
- }
+ // Check for Memos
+ if (confirmations == 0) {
+ chatModel->addconfirmations(txid, confirmations);
+ }
+
+ if ((confirmations > 0) && (chatModel->getConfirmationByTx(txid) != QString("0xdeadbeef"))) {
+ DataStore::getChatDataStore()->clear();
+ chatModel->killConfirmationCache();
+ chatModel->killMemoCache();
+ this->refresh(true);
+ }
+
QString memo;
QString cid;
QString headerbytes;
QString publickey;
if (!o["memo"].is_null()) {
- memo = QString::fromStdString(o["memo"].get());
+ memo = QString::fromStdString(o["memo"].get());
- if (memo.startsWith("{")) {
- try
- {
- QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8());
-
- cid = headermemo["cid"].toString();
- headerbytes = headermemo["e"].toString();
-
- chatModel->addCid(txid, cid);
- chatModel->addHeader(txid, headerbytes);
-
- } catch(...)
-
- {
-
- }
- }
+ if (memo.startsWith("{")) {
+ try
+ {
+ QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8());
+
+ cid = headermemo["cid"].toString();
+ headerbytes = headermemo["e"].toString();
+
+ chatModel->addCid(txid, cid);
+ chatModel->addHeader(txid, headerbytes);
+
+ }
+ catch (...)
+ {
+ // on any exception caught
+ }
+ }
bool isNotarized;
if (confirmations > getLag())
{
isNotarized = true;
- }else{
-
- isNotarized = false;
}
+ else
+ {
+ isNotarized = false;
+ }
- if (chatModel->getCidByTx(txid) != QString("0xdeadbeef")){
-
- cid = chatModel->getCidByTx(txid);
-
- }else{
- cid = "";
- }
-
-
- if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")){
-
- headerbytes = chatModel->getHeaderByTx(txid);
-
-
- }else{
- headerbytes = "";
- }
-
- if (main->getPubkeyByAddress(address) != QString("0xdeadbeef")){
+ if (chatModel->getCidByTx(txid) != QString("0xdeadbeef"))
+ {
+ cid = chatModel->getCidByTx(txid);
+ }
+ else
+ {
+ cid = "";
+ }
- publickey = main->getPubkeyByAddress(address);
-
+ if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef"))
+ {
+ headerbytes = chatModel->getHeaderByTx(txid);
+ }
+ else
+ {
+ headerbytes = "";
+ }
- }else{
- publickey = "";
- }
+ if (main->getPubkeyByAddress(address) != QString("0xdeadbeef"))
+ {
+ publickey = main->getPubkeyByAddress(address);
+ }
+ else
+ {
+ publickey = "";
+ }
- /////We need to filter out Memos smaller then the ciphertext size, or it will dump
-
- if ((memo.startsWith("{") == false) && (headerbytes.length() > 20))
- {
-
- QString passphrase = DataStore::getChatDataStore()->getPassword();
- QString hashEncryptionKey = passphrase;
- int length = hashEncryptionKey.length();
+ /////We need to filter out Memos smaller then the ciphertext size, or it will dump
+ if ((memo.startsWith("{") == false) && (headerbytes.length() > 20))
+ {
+ QString passphrase = DataStore::getChatDataStore()->getPassword();
+ int length = passphrase.length();
- ////////////////Generate the secretkey for our message encryption
+ ////////////////Generate the secretkey for our message encryption
+ char *hashEncryptionKeyraw = NULL;
+ hashEncryptionKeyraw = new char[length+1];
+ strncpy(hashEncryptionKeyraw, passphrase.toUtf8(), length +1);
- char *hashEncryptionKeyraw = NULL;
- hashEncryptionKeyraw = new char[length+1];
- strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1);
- const QByteArray pubkeyBobArray = QByteArray::fromHex(publickey.toLatin1());
- const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData());
+ const QByteArray pubkeyBobArray = QByteArray::fromHex(publickey.toLatin1());
+ const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData());
+ #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) ///////////
+ #define MESSAGEAS1_LEN length
-
-
- #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)///////////
- #define MESSAGEAS1_LEN length
-
-
- unsigned char hash1[crypto_kx_SEEDBYTES];
-
- crypto_hash_sha256(hash1,MESSAGEAS1, MESSAGEAS1_LEN);
- unsigned char sk[crypto_kx_SECRETKEYBYTES];
- unsigned char pk[crypto_kx_PUBLICKEYBYTES];
+ unsigned char sk[crypto_kx_SECRETKEYBYTES];
+ unsigned char pk[crypto_kx_PUBLICKEYBYTES];
- if (crypto_kx_seed_keypair(pk,sk,
- hash1) !=0) {
- }
-
- unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
+ if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0)
+ {
+ main->logger->write("Keypair outgoing error");
+ }
+
+ unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
- ////////////////Get the pubkey from Bob, so we can create the share key
-
-
- /////Create the shared key for sending the message
-
- if (crypto_kx_server_session_keys(server_rx, server_tx,
- pk, sk, pubkeyBob) != 0) {
- /* Suspicious client public key, bail out */
- }
-
-
- const QByteArray ba = QByteArray::fromHex(memo.toLatin1());
- const unsigned char *encryptedMemo = reinterpret_cast(ba.constData());
+ ////////////////Get the pubkey from Bob, so we can create the share key
- const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1());
- const unsigned char *header = reinterpret_cast(ba1.constData());
-
- int encryptedMemoSize1 = ba.length();
+ /////Create the shared key for sending the message
- QString memodecrypt;
+ if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0)
+ {
+ main->logger->write("Suspicious client public outgoing key, bail out ");
+ }
+
+ const QByteArray ba = QByteArray::fromHex(memo.toUtf8());
+ const unsigned char *encryptedMemo = reinterpret_cast(ba.constData());
- if (encryptedMemoSize1 > 15)
- {
- //////unsigned char* as message from QString
- #define MESSAGE2 (const unsigned char *) encryptedMemo
+ const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1());
+ const unsigned char *header = reinterpret_cast(ba1.constData());
- ///////// length of the encrypted message
- #define CIPHERTEXT1_LEN encryptedMemoSize1
+ int encryptedMemoSize1 = ba.length();
- ///////Message length is smaller then the encrypted message
- #define MESSAGE1_LEN encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES
+ QString memodecrypt;
- //////Set the length of the decrypted message
+ if ((encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES) > 0)
+ {
+ //////unsigned char* as message from QString
+ #define MESSAGE2 (const unsigned char *) encryptedMemo
- unsigned char decrypted[MESSAGE1_LEN];
- unsigned char tag[crypto_secretstream_xchacha20poly1305_TAG_FINAL];
- crypto_secretstream_xchacha20poly1305_state state;
+ ///////// length of the encrypted message
+ #define CIPHERTEXT1_LEN encryptedMemoSize1
- /////Our decrypted message is now in decrypted. We need it as QString to render it
- /////Only the QString gives weird data, so convert first to std::string
- // crypto_secretstream_xchacha20poly1305_keygen(client_rx);
- if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, server_tx) != 0) {
- /* Invalid header, no need to go any further */
- }
+ ///////Message length is smaller then the encrypted message
+ #define MESSAGE1_LEN encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES
- if (crypto_secretstream_xchacha20poly1305_pull
- (&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
- /* Invalid/incomplete/corrupted ciphertext - abort */
- }
+ //////Set the length of the decrypted message
- std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN);
-
- memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size());
+ unsigned char decrypted[MESSAGE1_LEN];
+ unsigned char tag[crypto_secretstream_xchacha20poly1305_TAG_FINAL];
+ crypto_secretstream_xchacha20poly1305_state state;
- }else{
- memodecrypt = "";
+ /////Our decrypted message is now in decrypted. We need it as QString to render it
+ /////Only the QString gives weird data, so convert first to std::string
+ // crypto_secretstream_xchacha20poly1305_keygen(client_rx);
+ if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, server_tx) != 0) {
+ /* Invalid header, no need to go any further */
+ }
+
+ if (crypto_secretstream_xchacha20poly1305_pull
+ (&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
+ /* Invalid/incomplete/corrupted ciphertext - abort */
+ }
- }
- /////Now we can convert it to QString
+ std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN);
-
-
- //////////////Give us the output of the decrypted message as debug to see if it was successfully
-
- ChatItem item = ChatItem(
+ memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size());
+ }
+ else
+ {
+
+ memodecrypt = "";
+ }
+
+ /////Now we can convert it to QString
+ //////////////Give us the output of the decrypted message as debug to see if it was successfully
+
+ ChatItem item = ChatItem(
datetime,
address,
QString(""),
@@ -1135,49 +1118,46 @@ void Controller::refreshTransactions() {
isNotarized,
false
);
- DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
- updateUIBalances();
-
+ DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
+ // updateUIBalances();
}
-
- }
+ }
items.push_back(TransactionItemDetail{address, amount, memo});
total_amount = total_amount + amount;
- }
+ }
{
- QList addresses;
+ QList addresses;
for (auto item : items) {
- // Concat all the addresses
-
-
- addresses.push_back(item.address);
- address = addresses.join(",");
+ // Concat all the addresses
+ addresses.push_back(item.address);
+ address = addresses.join(",");
}
-
- }
+ }
txdata.push_back(TransactionItem{
"send", datetime, address, txid,confirmations, items
});
- } else {
- // Incoming Transaction
+ }
+ else
+ {
+
+ { // Incoming Transaction
address = (it["address"].is_null() ? "" : QString::fromStdString(it["address"]));
model->markAddressUsed(address);
QString memo;
if (!it["memo"].is_null()) {
memo = QString::fromStdString(it["memo"]);
- }
items.push_back(TransactionItemDetail{
- address,
+ address,
CAmount::fromqint64(it["amount"].get()),
- memo
+ memo
});
TransactionItem tx{
@@ -1185,7 +1165,9 @@ void Controller::refreshTransactions() {
};
txdata.push_back(tx);
-
+ }
+
+
QString type;
QString publickey;
QString headerbytes;
@@ -1197,8 +1179,8 @@ void Controller::refreshTransactions() {
if (!it["memo"].is_null()) {
if (memo.startsWith("{")) {
- try
- {
+ try
+ {
QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8());
cid = headermemo["cid"].toString();
@@ -1210,225 +1192,220 @@ void Controller::refreshTransactions() {
chatModel->addCid(txid, cid);
chatModel->addrequestZaddr(txid, requestZaddr);
chatModel->addHeader(txid, headerbytes);
-
+
if (publickey.length() > 10){
main->addPubkey(requestZaddr, publickey);
}
- } catch(...)
- {
-
- }
- }
+ }
+ catch (...)
+ {
+ // on any exception
+ }
+ }
- if (chatModel->getCidByTx(txid) != QString("0xdeadbeef")){
-
+ if (chatModel->getCidByTx(txid) != QString("0xdeadbeef"))
+ {
cid = chatModel->getCidByTx(txid);
-
- }else{
- cid = "";
+ }
+ else
+ {
+ cid = "";
}
- if (chatModel->getrequestZaddrByTx(txid) != QString("0xdeadbeef")){
-
+ if (chatModel->getrequestZaddrByTx(txid) != QString("0xdeadbeef"))
+ {
requestZaddr = chatModel->getrequestZaddrByTx(txid);
- }else{
- requestZaddr = "";
- }
-
-
- if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")){
+ }
+ else
+ {
+ requestZaddr = "";
+ }
+ if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef"))
+ {
headerbytes = chatModel->getHeaderByTx(txid);
-
-
- }else{
- headerbytes = "";
- }
-
- if (main->getPubkeyByAddress(requestZaddr) != QString("0xdeadbeef")){
+ }
+ else
+ {
+ headerbytes = "";
+ }
+ if (main->getPubkeyByAddress(requestZaddr) != QString("0xdeadbeef"))
+ {
publickey = main->getPubkeyByAddress(requestZaddr);
-
-
- }else{
- publickey = "";
- }
-
- if (contactModel->getContactbyAddress(requestZaddr) != QString("0xdeadbeef")){
+ }
+ else
+ {
+ publickey = "";
+ }
- isContact = true;
- contactname = contactModel->getContactbyAddress(requestZaddr);
+ if (contactModel->getContactbyAddress(requestZaddr) != QString("0xdeadbeef"))
+ {
+ isContact = true;
+ contactname = contactModel->getContactbyAddress(requestZaddr);
+ }
+ else
+ {
+ isContact = false;
+ contactname = "";
+ }
- }else{
+ bool isNotarized;
- isContact = false;
- contactname = "";
+ if (confirmations > getLag())
+ {
+ isNotarized = true;
+ }
+ else
+ {
+ isNotarized = false;
+ }
- }
+ int position = it["position"].get();
- bool isNotarized;
+ int ciphercheck = memo.length() - crypto_secretstream_xchacha20poly1305_ABYTES;
- if (confirmations > getLag())
+ if ((memo.startsWith("{") == false) && (headerbytes > 0) && (ciphercheck > 0))
+ {
+ if (chatModel->getMemoByTx(txid) == QString("0xdeadbeef"))
{
- isNotarized = true;
- }else{
-
- isNotarized = false;
- }
-
- int position = it["position"].get();
-
- if ((memo.startsWith("{") == false) && (headerbytes > 0))
- {
-
- if (chatModel->getMemoByTx(txid) == QString("0xdeadbeef")){
-
-
- if (position == 1)
- {
-
- chatModel->addMemo(txid, headerbytes);
- }else{}
-
- QString passphrase = DataStore::getChatDataStore()->getPassword();
- QString hashEncryptionKey = passphrase;
- int length = hashEncryptionKey.length();
-
- char *hashEncryptionKeyraw = NULL;
- hashEncryptionKeyraw = new char[length+1];
- strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1);
-
- //const QByteArray ba2 = QByteArray::fromHex(hashEncryptionKey.toLatin1());
- // const unsigned char *hashEncryptionKeyraw = reinterpret_cast(ba2.constData());
-
- const QByteArray pubkeyBobArray = QByteArray::fromHex(publickey.toLatin1());
- const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData());
+ if (position == 1)
+ {
+ chatModel->addMemo(txid, headerbytes);
+ }
+ else
+ {
+ //
+ }
+ QString passphrase = DataStore::getChatDataStore()->getPassword();
+ int length = passphrase.length();
- #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)///////////
- #define MESSAGEAS1_LEN length
+ char *hashEncryptionKeyraw = NULL;
+ hashEncryptionKeyraw = new char[length+1];
+ strncpy(hashEncryptionKeyraw, passphrase.toUtf8(), length +1);
-
- unsigned char hash1[crypto_kx_SEEDBYTES];
+ const QByteArray pubkeyBobArray = QByteArray::fromHex(publickey.toLatin1());
+ const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData());
- crypto_hash_sha256(hash1,MESSAGEAS1, MESSAGEAS1_LEN);
- unsigned char sk[crypto_kx_SECRETKEYBYTES];
- unsigned char pk[crypto_kx_PUBLICKEYBYTES];
-
- if (crypto_kx_seed_keypair(pk,sk,
- hash1) !=0) {
+ #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)///////////
+ #define MESSAGEAS1_LEN length
+ unsigned char sk[crypto_kx_SECRETKEYBYTES];
+ unsigned char pk[crypto_kx_PUBLICKEYBYTES];
- }
- unsigned char client_rx[crypto_kx_SESSIONKEYBYTES], client_tx[crypto_kx_SESSIONKEYBYTES];
+ if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0)
+ {
+ main->logger->write("Suspicious outgoing key pair, bail out ");
+ }
-
- ////////////////Get the pubkey from Bob, so we can create the share key
+ unsigned char client_rx[crypto_kx_SESSIONKEYBYTES], client_tx[crypto_kx_SESSIONKEYBYTES];
-
- /////Create the shared key for sending the message
+ ////////////////Get the pubkey from Bob, so we can create the share key
- if (crypto_kx_client_session_keys(client_rx, client_tx,
- pk, sk, pubkeyBob) != 0) {
- /* Suspicious client public key, bail out */
- }
-
-
+ /////Create the shared key for sending the message
- const QByteArray ba = QByteArray::fromHex(memo.toLatin1());
- const unsigned char *encryptedMemo = reinterpret_cast(ba.constData());
+ if (crypto_kx_client_session_keys(client_rx, client_tx, pk, sk, pubkeyBob) != 0)
+ {
+ main->logger->write("Suspicious client public incoming key, bail out ");
+ }
- const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1());
- const unsigned char *header = reinterpret_cast(ba1.constData());
+ const QByteArray ba = QByteArray::fromHex(memo.toUtf8());
+ const unsigned char *encryptedMemo = reinterpret_cast(ba.constData());
- int encryptedMemoSize1 = ba.length();
- int headersize = ba1.length();
+ const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1());
+ const unsigned char *header = reinterpret_cast(ba1.constData());
- //////unsigned char* as message from QString
- #define MESSAGE2 (const unsigned char *) encryptedMemo
+ int encryptedMemoSize1 = ba.length();
+ int headersize = ba1.length();
- ///////// length of the encrypted message
- #define CIPHERTEXT1_LEN encryptedMemoSize1
+ //////unsigned char* as message from QString
+ #define MESSAGE2 (const unsigned char *) encryptedMemo
- ///////Message length is smaller then the encrypted message
- #define MESSAGE1_LEN encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES
+ ///////// length of the encrypted message
+ #define CIPHERTEXT1_LEN encryptedMemoSize1
- //////Set the length of the decrypted message
+ ///////Message length is smaller then the encrypted message
+ #define MESSAGE1_LEN encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES
- unsigned char decrypted[MESSAGE1_LEN];
- unsigned char tag[crypto_secretstream_xchacha20poly1305_TAG_FINAL];
- crypto_secretstream_xchacha20poly1305_state state;
+ //////Set the length of the decrypted message
- /////Our decrypted message is now in decrypted. We need it as QString to render it
- /////Only the QString gives weird data, so convert first to std::string
- // crypto_secretstream_xchacha20poly1305_keygen(client_rx);
- if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, client_rx) != 0) {
- /* Invalid header, no need to go any further */
- }
+ unsigned char decrypted[MESSAGE1_LEN+1];
+ unsigned char tag[crypto_secretstream_xchacha20poly1305_TAG_FINAL];
+ crypto_secretstream_xchacha20poly1305_state state;
- if (crypto_secretstream_xchacha20poly1305_pull
- (&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
- /* Invalid/incomplete/corrupted ciphertext - abort */
- }
+ /////Our decrypted message is now in decrypted. We need it as QString to render it
+ /////Only the QString gives weird data, so convert first to std::string
+ // crypto_secretstream_xchacha20poly1305_keygen(client_rx);
+ if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, client_rx) != 0) {
+ main->logger->write("Invalid header incoming, no need to go any further ");
+ }
- std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN);
+ if (crypto_secretstream_xchacha20poly1305_pull
+ (&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
+ main->logger->write("Invalid/incomplete/corrupted ciphertext - abort");
+ }
- /////Now we can convert it to QString
- QString memodecrypt;
-
- memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size());
-
+ std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN);
+ /////Now we can convert it to QString
+ QString memodecrypt;
- // }
- //////////////Give us the output of the decrypted message as debug to see if it was successfully
-
+ memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size());
+ // }
+ //////////////Give us the output of the decrypted message as debug to see if it was successfully
- ChatItem item = ChatItem(
+ ChatItem item = ChatItem(
datetime,
address,
contactname,
memodecrypt,
requestZaddr,
type,
- cid,
+ cid,
txid,
confirmations,
false,
isNotarized,
isContact
);
- DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
-
- }else{
-
- }
-
- }else{
- ChatItem item = ChatItem(
- datetime,
- address,
- contactname,
- memo,
- requestZaddr,
- type,
- cid,
- txid,
- confirmations,
- false,
- isNotarized,
- isContact
- );
- DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
+ DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
+
+ }
+ else
+ {
+ //
+ }
+
+ }
+ else
+ {
+ ChatItem item = ChatItem(
+ datetime,
+ address,
+ contactname,
+ memo,
+ requestZaddr,
+ type,
+ cid,
+ txid,
+ confirmations,
+ false,
+ isNotarized,
+ isContact
+ );
+ DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
}
}
+ }
+ }
}
- }
+ }
- // Calculate the total unspent amount that's pending. This will need to be
+ // Calculate the total unspent amount that's pending. This will need to be
// shown in the UI so the user can keep track of pending funds
CAmount totalPending;
for (auto txitem : txdata) {
@@ -1444,13 +1421,14 @@ void Controller::refreshTransactions() {
// Update UI Balance
updateUIBalances();
- // Update model data, which updates the table view
- transactionsTableModel->replaceData(txdata);
- chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat);
+ // Update model data, which updates the table view
+ transactionsTableModel->replaceData(txdata);
+ chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat);
ui->listChat->verticalScrollBar()->setValue(
ui->listChat->verticalScrollBar()->maximum());
-
- });
+
+ });
+
}
void Controller::refreshChat(QListView *listWidget, QLabel *label)
@@ -1464,6 +1442,8 @@ void Controller::refreshChat(QListView *listWidget, QLabel *label)
void Controller::refreshContacts(QListView *listWidget)
{
contactModel->renderContactList(listWidget);
+ ui->listChat->verticalScrollBar()->setValue(
+ ui->listChat->verticalScrollBar()->maximum());
}
// If the wallet is encrpyted and locked, we need to unlock it
@@ -1560,11 +1540,11 @@ void Controller::executeTransaction(Tx tx,
std::cout << std::setw(2) << params << std::endl;
zrpc->sendTransaction(QString::fromStdString(params.dump()), [=](const json& reply) {
- if (reply.find("txid") == reply.end())
+ if (reply.find("txid") == reply.end())
{
error("", "Couldn't understand Response: " + QString::fromStdString(reply.dump()));
- }
- else
+ }
+ else
{
QString txid = QString::fromStdString(reply["txid"].get());
submitted(txid);
@@ -1773,7 +1753,7 @@ void Controller::refreshZECPrice()
const json& item = parsed.get();
const json& hush = item["hush"].get();
- if (hush["usd"] >= 0)
+ if (hush["usd"] >= 0)
{
qDebug() << "Found hush key in price json";
qDebug() << "HUSH = $" << QString::number((double)hush["usd"]);
@@ -1804,7 +1784,7 @@ void Controller::refreshZECPrice()
Settings::getInstance()->setRUBPrice( hush["rub"]);
}
- if (hush["cad"] >= 0)
+ if (hush["cad"] >= 0)
{
qDebug() << "HUSH = CAD" << QString::number((double)hush["cad"]);
Settings::getInstance()->setCADPrice( hush["cad"]);
@@ -1858,7 +1838,7 @@ void Controller::refreshZECPrice()
Settings::getInstance()->setBTCVolume( hush["btc_24h_vol"]);
}
- if (hush["cny_24h_vol"] >= 0)
+ if (hush["cny_24h_vol"] >= 0)
{
qDebug() << "HUSH = cny_24h_vol" << QString::number((double)hush["cny_24h_vol"]);
Settings::getInstance()->setCNYVolume( hush["cny_24h_vol"]);
@@ -2049,7 +2029,7 @@ void Controller::shutdownhushd()
}
bool finished = false;
- zrpc->saveWallet([&] (json) {
+ zrpc->saveWallet([&] (json) {
if (!finished)
d.accept();
finished = true;
diff --git a/src/controller.h b/src/controller.h
index 195827c..bbf3cc7 100644
--- a/src/controller.h
+++ b/src/controller.h
@@ -19,6 +19,7 @@
#include "Model/ContactRequestChatItem.h"
#include "Model/ContactItem.h"
#include "contactmodel.h"
+
using json = nlohmann::json;
struct WatchedTx {
@@ -40,7 +41,7 @@ public:
Connection* getConnection() { return zrpc->getConnection(); }
void setConnection(Connection* c);
void refresh(bool force = false);
- void refreshAddresses();
+ void refreshAddresses();
int getLag();
void setLag(int lag);
int _lag;
@@ -99,35 +100,35 @@ public:
void noConnection();
bool isEmbedded() { return ehushd != nullptr; }
- void encryptWallet(QString password, const std::function& cb) {
+ void encryptWallet(QString password, const std::function& cb) {
zrpc->encryptWallet(password, cb);
}
- void removeWalletEncryption(QString password, const std::function& cb) {
+ void removeWalletEncryption(QString password, const std::function& cb) {
zrpc->removeWalletEncryption(password, cb); }
void saveWallet(const std::function& cb) { zrpc->saveWallet(cb); }
void clearWallet(const std::function& cb) { zrpc->clearWallet(cb); }
- void createNewZaddr(bool sapling, const std::function& cb) {
+ void createNewZaddr(bool sapling, const std::function& cb) {
unlockIfEncrypted([=] () {
zrpc->createNewZaddr(sapling, cb);
}, [=](){});
}
- void createNewTaddr(const std::function& cb) {
+ void createNewTaddr(const std::function& cb) {
unlockIfEncrypted([=] () {
zrpc->createNewTaddr(cb);
}, [=](){});
}
- void createNewSietchZaddr(const std::function& cb) {
+ void createNewSietchZaddr(const std::function& cb) {
unlockIfEncrypted([=] () {
zrpc->createNewSietchZaddr(cb);
}, [=](){});
}
- void fetchPrivKey(QString addr, const std::function& cb) {
+ void fetchPrivKey(QString addr, const std::function& cb) {
unlockIfEncrypted([=] () {
zrpc->fetchPrivKey(addr, cb);
},
@@ -136,7 +137,7 @@ public:
});
}
- void fetchAllPrivKeys(const std::function cb) {
+ void fetchAllPrivKeys(const std::function cb) {
unlockIfEncrypted([=] () {
zrpc->fetchAllPrivKeys(cb);
},
diff --git a/src/emoji.ui b/src/emoji.ui
new file mode 100644
index 0000000..8118466
--- /dev/null
+++ b/src/emoji.ui
@@ -0,0 +1,339 @@
+
+
+ emojiDialog
+
+
+
+ 0
+ 0
+ 261
+ 150
+
+
+
+ Emoji
+
+
+ -
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+
+
+
+
+ :/emoji/res/emoji/emoji1.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/laughing.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/sweet_smile.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/joy.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/innocent.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/partying_face.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/icons/res/money-mouth.png
+
+
+
+ true
+
+
+
+
+
+ -
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+
+
+
+
+ :/emoji/res/emoji/face-with-rolling-eyes.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/face-with-tongue.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/face_with_3hearts.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/heart_shaped_eyes.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/nauseated-face.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/pile-of-poo.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/serious-face-with-symbols-covering-mouth.png
+
+
+
+ true
+
+
+
+
+
+ -
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+
+
+
+
+ :/emoji/res/emoji/smiling-face-with-sunglasses.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/stuck-out.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/hush-money-white.png
+
+
+
+ true
+
+
+
+ -
+
+
+
+
+
+
+ :/emoji/res/emoji/SD.png
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
diff --git a/src/firsttimewizard.cpp b/src/firsttimewizard.cpp
index 5ef96bb..47941ea 100644
--- a/src/firsttimewizard.cpp
+++ b/src/firsttimewizard.cpp
@@ -8,14 +8,24 @@
#include "../lib/silentdragonlitelib.h"
-using json = nlohmann::json;
-FirstTimeWizard::FirstTimeWizard(bool dangerous, QString server)
+FirstTimeWizard::FirstTimeWizard(QString server)
{
setWindowTitle("New wallet wizard");
- this->dangerous = dangerous;
this->server = server;
+ ////backup addresslabels.dat if there is one, to restore it later
+
+ auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
+ QString addressbook = dir.filePath("addresslabels.dat.enc");
+ QFile file(addressbook);
+
+ if (file.exists())
+ {
+ file.rename(dir.filePath("addresslabels.dat.enc-backup"));
+
+ }
+
// Create the pages
setPage(Page_NewOrRestore, new NewOrRestorePage(this));
setPage(Page_New, new NewSeedPage(this));
@@ -40,34 +50,86 @@ int FirstTimeWizard::nextId() const {
NewOrRestorePage::NewOrRestorePage(FirstTimeWizard *parent) : QWizardPage(parent) {
setTitle("Create or Restore wallet.");
-
-
QWidget* pageWidget = new QWidget();
Ui_CreateWalletForm form;
form.setupUi(pageWidget);
-
+
+ QGraphicsScene* scene = new QGraphicsScene();
+ QGraphicsView* view = new QGraphicsView(scene);
+ form.Logo->setScene(scene);
+ QPixmap pixmap(":/icons/res/dark-01.png");
+ scene->addPixmap(pixmap);
+ form.Logo->show();
+
+
+ parent->button(QWizard::CommitButton)->setEnabled(false);
+ setButtonText(QWizard::CommitButton, "Next");
+ form.txtPassword->setEnabled(false);
+ form.txtConfirmPassword->setEnabled(false);
+
+ QObject::connect(form.TOS, &QRadioButton::clicked, [=](bool checked) {
+ if (checked) {
+
+ form.txtPassword->setEnabled(true);
+ form.txtConfirmPassword->setEnabled(true);
+
+ }
+ });
+
auto fnPasswordEdited = [=](const QString&) {
// Enable the Finish button if the passwords match.
- QString Password = form.txtPassword->text();
+ QString passphraseBlank = form.txtPassword->text();
+
+ QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL");
+
if (!form.txtPassword->text().isEmpty() &&
- form.txtPassword->text() == form.txtConfirmPassword->text() && Password.size() >= 16) {
+ form.txtPassword->text() == form.txtConfirmPassword->text() && passphraseBlank.size() >= 16 ){
form.lblPasswordMatch->setText("");
- parent->button(QWizard::CommitButton)->setEnabled(true);
- setButtonText(QWizard::CommitButton, "Next");
+
+
form.radioRestoreWallet->setEnabled(true);
form.radioNewWallet->setEnabled(true);
form.radioNewWallet->setChecked(true);
+ parent->button(QWizard::CommitButton)->setEnabled(true);
-
-DataStore::getChatDataStore()->setPassword(Password);
+ int length = passphrase.length();
+
+ char *sequence = NULL;
+ sequence = new char[length+1];
+ strncpy(sequence, passphrase.toUtf8(), length +1);
+
+ QString passphraseHash = blake3_PW(sequence);
+
+
+ char *sequence1 = NULL;
+ sequence1 = new char[length+1];
+ strncpy(sequence1, passphraseHash.toUtf8(), length+1);
+
+ #define MESSAGE ((const unsigned char *) sequence)
+ #define MESSAGE_LEN length
+ #define hash ((const unsigned char *) sequence1)
+
+ #define PASSWORD sequence
+ #define KEY_LEN crypto_box_SEEDBYTES
+
+ unsigned char key[KEY_LEN];
+
+ if (crypto_pwhash
+ (key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
+ crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
+ crypto_pwhash_ALG_DEFAULT) != 0) {
+ /* out of memory */
+}
+ QString passphraseHash1 = QByteArray(reinterpret_cast(key), KEY_LEN).toHex();
+ DataStore::getChatDataStore()->setPassword(passphraseHash1);
//main->setPassword(Password);
//qDebug()<<"Objekt gesetzt";
-
+
// Exclusive buttons
QObject::connect(form.radioNewWallet, &QRadioButton::clicked, [=](bool checked) {
if (checked) {
@@ -82,6 +144,8 @@ DataStore::getChatDataStore()->setPassword(Password);
}
});
+
+
@@ -106,6 +170,8 @@ DataStore::getChatDataStore()->setPassword(Password);
form.radioRestoreWallet->setEnabled(false);
form.radioNewWallet->setEnabled(false);
setCommitPage(true);
+
+
}
@@ -127,7 +193,7 @@ NewSeedPage::NewSeedPage(FirstTimeWizard *parent) : QWizardPage(parent) {
void NewSeedPage::initializePage() {
// Call the library to create a new wallet.
- char* resp = litelib_initialize_new(parent->dangerous, parent->server.toStdString().c_str());
+ char* resp = litelib_initialize_new(parent->server.toStdString().c_str());
QString reply = litelib_process_response(resp);
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false);
@@ -136,8 +202,6 @@ void NewSeedPage::initializePage() {
} else {
QString seed = QString::fromStdString(parsed["seed"].get());
form.txtSeed->setPlainText(seed);
-
-
}
@@ -151,6 +215,7 @@ bool NewSeedPage::validatePage() {
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false);
if (parsed.is_discarded() || parsed.is_null() || parsed.find("result") == parsed.end()) {
+
QMessageBox::warning(this, tr("Failed to save wallet"),
tr("Couldn't save the wallet") + "\n" + reply,
QMessageBox::Ok);
@@ -196,10 +261,14 @@ bool RestoreSeedPage::validatePage() {
return false;
}
+///Number
+
+QString number_str = form.number->text();
+qint64 number = number_str.toUInt();
// 3. Attempt to restore wallet with the seed phrase
{
- char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(),
- seed.toStdString().c_str(), birthday);
+ char* resp = litelib_initialize_new_from_phrase(parent->server.toStdString().c_str(),
+ seed.toStdString().c_str(), birthday, number);
QString reply = litelib_process_response(resp);
if (reply.toUpper().trimmed() != "OK") {
diff --git a/src/firsttimewizard.h b/src/firsttimewizard.h
index 8d84b61..8b6de40 100644
--- a/src/firsttimewizard.h
+++ b/src/firsttimewizard.h
@@ -5,6 +5,7 @@
#include "ui_newseed.h"
#include "ui_restoreseed.h"
+#include "ui_newwallet.h"
#include "mainwindow.h"
@@ -15,7 +16,7 @@ class FirstTimeWizard: public QWizard
public:
- FirstTimeWizard(bool dangerous, QString server);
+ FirstTimeWizard(QString server);
protected:
@@ -28,7 +29,6 @@ private:
Page_Restore
};
- bool dangerous;
QString server;
friend class NewOrRestorePage;
diff --git a/src/liteinterface.cpp b/src/liteinterface.cpp
index e17bb71..3d7a4a1 100644
--- a/src/liteinterface.cpp
+++ b/src/liteinterface.cpp
@@ -129,7 +129,7 @@ void LiteInterface::removeWalletEncryption(QString password, const std::function
}
-void LiteInterface::sendTransaction(QString params, const std::function& cb,
+void LiteInterface::sendTransaction(QString params, const std::function& cb,
const std::function& err) {
if (conn == nullptr)
return;
@@ -137,7 +137,7 @@ void LiteInterface::sendTransaction(QString params, const std::functiondoRPC("send", params, cb, err);
}
-void LiteInterface::fetchInfo(const std::function& cb,
+void LiteInterface::fetchInfo(const std::function& cb,
const std::function& err) {
if (conn == nullptr)
return;
@@ -153,7 +153,7 @@ void LiteInterface::fetchSupply(const std::function& cb) {
}
-void LiteInterface::fetchLatestBlock(const std::function& cb,
+void LiteInterface::fetchLatestBlock(const std::function& cb,
const std::function& err) {
if (conn == nullptr)
return;
diff --git a/src/liteinterface.h b/src/liteinterface.h
index 4f9c13c..b8309bd 100644
--- a/src/liteinterface.h
+++ b/src/liteinterface.h
@@ -42,12 +42,12 @@ public:
void fetchTransactions (const std::function& cb);
void fetchAddresses (const std::function& cb);
- void fetchInfo(const std::function& cb,
+ void fetchInfo(const std::function& cb,
const std::function& err);
- void fetchLatestBlock(const std::function& cb,
+ void fetchLatestBlock(const std::function& cb,
const std::function& err);
void fetchBalance(const std::function& cb);
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 338c8b2..64a3148 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -17,13 +17,16 @@
#include "settings.h"
#include "version.h"
#include "connection.h"
+#include "ui_sendHushTransactionChat.h"
#include "ui_contactrequest.h"
#include "ui_deposithush.h"
+#include "ui_emoji.h"
#include "ui_requestContactDialog.h"
#include "chatmodel.h"
#include "requestdialog.h"
#include "ui_startupencryption.h"
#include "ui_removeencryption.h"
+#include "ui_seedrestore.h"
#include "websockets.h"
#include "sodium.h"
#include "sodium/crypto_generichash_blake2b.h"
@@ -33,11 +36,14 @@
#include "Crypto/FileEncryption.h"
#include "DataStore/DataStore.h"
#include "firsttimewizard.h"
+#include "../lib/silentdragonlitelib.h"
+#include
+#include
+#include
using json = nlohmann::json;
-
#ifdef Q_OS_WIN
auto dirwallet = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet.dat");
auto dirwalletenc = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet-enc.dat");
@@ -159,17 +165,124 @@ MainWindow::MainWindow(QWidget *parent) :
// Rescan
QObject::connect(ui->actionRescan, &QAction::triggered, [=]() {
- // To rescan, we clear the wallet state, and then reload the connection
+
+ QFile file(dirwalletenc);
+ QFile file1(dirwallet);
+
+ if(fileExists(dirwalletenc))
+
+ {
+ file.remove();
+ file1.remove();
+ }
+
+
+ Ui_Restore restoreSeed;
+ QDialog dialog(this);
+ restoreSeed.setupUi(&dialog);
+ Settings::saveRestore(&dialog);
+
+
+ rpc->fetchSeed([=](json reply) {
+ if (isJsonError(reply)) {
+ return;
+ }
+
+ restoreSeed.seed->setReadOnly(true);
+ restoreSeed.seed->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap);
+ QString seedJson = QString::fromStdString(reply.get());
+ int startPos = seedJson.indexOf("seed") +7;
+ int endPos = seedJson.indexOf("}") -1;
+ int length = endPos - startPos;
+ QString seed = seedJson.mid(startPos, length);
+ restoreSeed.seed->setPlainText(seed);
+
+ int startPosB = seedJson.indexOf("birthday") +10;
+ int endPosB = seedJson.indexOf("seed") -2;
+ int lengthB = endPosB - startPosB;
+ QString birthday = seedJson.mid(startPosB, lengthB);
+ restoreSeed.birthday->setPlainText(birthday);
+ });
+
+ QObject::connect(restoreSeed.restore, &QPushButton::clicked, [&](){
+
+ QString seed = restoreSeed.seed->toPlainText();
+ if (seed.trimmed().split(" ").length() != 24) {
+ QMessageBox::warning(this, tr("Failed to restore wallet"),
+ tr("SilentDragonLite needs 24 words to restore wallet"),
+ QMessageBox::Ok);
+ return false;
+ }
+
+
+ // 2. Validate birthday
+ QString birthday_str = restoreSeed.birthday->toPlainText();
+ bool ok;
+ qint64 birthday = birthday_str.toUInt(&ok);
+ if (!ok) {
+ QMessageBox::warning(this, tr("Failed to parse wallet birthday"),
+ tr("Couldn't understand wallet birthday. This should be a block height from where to rescan the wallet. You can leave it as '0' if you don't know what it should be."),
+ QMessageBox::Ok);
+ return false;
+ }
+
+
+ QString number_str = restoreSeed.quantity->text();
+ qint64 number = number_str.toUInt();
+
+ auto config = std::shared_ptr(new ConnectionConfig());
+ config->server = Settings::getInstance()->getSettings().server;
+ // 3. Attempt to restore wallet with the seed phrase
+ {
+ char* resp = litelib_initialize_new_from_phrase(config->server.toStdString().c_str(),
+ seed.toStdString().c_str(), birthday, number);
+ QString reply = litelib_process_response(resp);
+
+ if (reply.toUpper().trimmed() != "OK") {
+ QMessageBox::warning(this, tr("Failed to restore wallet"),
+ tr("Couldn't restore the wallet") + "\n" + reply,
+ QMessageBox::Ok);
+
+ }
+ }
+
+ // 4. Finally attempt to save the wallet
+ {
+ char* resp = litelib_execute("save", "");
+ QString reply = litelib_process_response(resp);
+
+ QByteArray ba_reply = reply.toUtf8();
+ QJsonDocument jd_reply = QJsonDocument::fromJson(ba_reply);
+ QJsonObject parsed = jd_reply.object();
+
+ if (parsed.isEmpty() || parsed["result"].isNull()) {
+ QMessageBox::warning(this, tr("Failed to save wallet"),
+ tr("Couldn't save the wallet") + "\n" + reply,
+ QMessageBox::Ok);
+
+ } else {}
+
+ dialog.close();
+ // To rescan, we clear the wallet state, and then reload the connection
// This will start a sync, and show the scanning status.
this->getRPC()->clearWallet([=] (auto) {
// Save the wallet
this->getRPC()->saveWallet([=] (auto) {
// Then reload the connection. The ConnectionLoader deletes itself.
- auto cl = new ConnectionLoader(this, rpc);
+ auto cl = new ConnectionLoader(this, rpc);
cl->loadConnection();
- });
- });
- });
+ });
+ });
+
+
+ }
+
+ });
+
+ // });
+
+ dialog.exec();
+});
// Address Book
QObject::connect(ui->action_Address_Book, &QAction::triggered, this, &MainWindow::addressBook);
@@ -305,53 +418,31 @@ void MainWindow::closeEvent(QCloseEvent* event) {
fileoldencryption.remove();
// Encrypt our wallet.dat
- QString str = DataStore::getChatDataStore()->getPassword();
- // QString str = ed.txtPassword->text(); // data comes from user inputs
- int length = str.length();
-
- char *sequence = NULL;
- sequence = new char[length+1];
- strncpy(sequence, str.toLocal8Bit(), length +1);
+ QString passphraseHash = DataStore::getChatDataStore()->getPassword();
+ int length = passphraseHash.length();
- #define MESSAGE ((const unsigned char *) sequence)
- #define MESSAGE_LEN length
-
- unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES];
-
- crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN);
-
- #define PASSWORD sequence
- #define KEY_LEN crypto_box_SEEDBYTES
-
-
+ char *sequence1 = NULL;
+ sequence1 = new char[length+1];
+ strncpy(sequence1, passphraseHash.toUtf8(), length+1);
- /////////we use the Hash of the Password as Salt, not perfect but still a good solution.
+ #define PassphraseHashEnd ((const unsigned char *) sequence1)
+ #define MESSAGE_LEN length
- unsigned char key[KEY_LEN];
+ #define PASSWORD sequence
+ #define KEY_LEN crypto_box_SEEDBYTES
- if (crypto_pwhash
- (key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
- crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
- crypto_pwhash_ALG_DEFAULT) != 0) {
- /* out of memory */
-}
-
+ const QByteArray ba = QByteArray::fromHex(passphraseHash.toLatin1());
+ const unsigned char *encryptedMemo1 = reinterpret_cast(ba.constData());
+
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
- // auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
- QString source_file = dir.filePath("addresslabels.dat");
- QString target_enc_file = dir.filePath("addresslabels.dat.enc");
QString sourceWallet_file = dirwallet;
QString target_encWallet_file = dirwalletenc;
- FileEncryption::encrypt(target_enc_file, source_file, key);
- FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, key);
-
- ///////////////// we rename the plaintext wallet.dat to Backup, for testing.
+ // FileEncryption::encrypt(target_enc_file, source_file, key);
+ FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, encryptedMemo1);
QFile wallet(dirwallet);
- QFile address(dir.filePath("addresslabels.dat"));
wallet.remove();
- address.remove();
}
@@ -399,51 +490,49 @@ void MainWindow::encryptWallet() {
if (d.exec() == QDialog::Accepted)
{
- QString passphrase = 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");
int length = passphrase.length();
- DataStore::getChatDataStore()->setPassword(passphrase);
-
- char *sequence = NULL;
- sequence = new char[length+1];
- strncpy(sequence, passphrase.toLocal8Bit(), length +1);
-
- #define MESSAGE ((const unsigned char *) sequence)
- #define MESSAGE_LEN length
-
- unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES];
+
- crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN);
+ char *sequence = NULL;
+ sequence = new char[length+1];
+ strncpy(sequence, passphrase.toUtf8(), length +1);
+
+ QString passphraseHash = blake3_PW(sequence);
+ DataStore::getChatDataStore()->setPassword(passphraseHash);
- #define PASSWORD sequence
- #define KEY_LEN crypto_box_SEEDBYTES
+ char *sequence1 = NULL;
+ sequence1 = new char[length+1];
+ strncpy(sequence1, passphraseHash.toUtf8(), length+1);
-
+ #define MESSAGE ((const unsigned char *) sequence)
+ #define MESSAGE_LEN length
+ #define hash ((const unsigned char *) sequence1)
- /////////we use the Hash of the Password as Salt, not perfect but still a good solution.
+ #define PASSWORD sequence
+ #define KEY_LEN crypto_box_SEEDBYTES
- unsigned char key[KEY_LEN];
+ unsigned char key[KEY_LEN];
- if (crypto_pwhash
- (key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
- crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
- crypto_pwhash_ALG_DEFAULT) != 0) {
- /* out of memory */
+ if (crypto_pwhash
+ (key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
+ crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
+ crypto_pwhash_ALG_DEFAULT) != 0) {
+ /* out of memory */
}
+ QString passphraseHash1 = QByteArray(reinterpret_cast(key), KEY_LEN).toHex();
+ DataStore::getChatDataStore()->setPassword(passphraseHash1);
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
- QString source_file = dir.filePath("addresslabels.dat");
- QString target_enc_file = dir.filePath("addresslabels.dat.enc");
QString sourceWallet_file = dirwallet;
QString target_encWallet_file = dirwalletenc;
-
- FileEncryption::encrypt(target_enc_file, source_file, key);
+
FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, key);
QFile wallet(dirwallet);
- QFile address(dir.filePath("addresslabels.dat"));
wallet.rename(dirwalletbackup);
- address.rename(dir.filePath("addresslabels.datBackup"));
QMessageBox::information(this, tr("Wallet Encryption Success"),
QString("Successfully encrypted your wallet"),
@@ -484,27 +573,28 @@ void MainWindow::removeWalletEncryption() {
if (d.exec() == QDialog::Accepted)
{
- QString str = ed.txtPassword->text(); // data comes from user inputs
- int length = str.length();
+ QString passphraseBlank = ed.txtPassword->text(); // data comes from user inputs
+
+ QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL");
+
+ int length = passphrase.length();
char *sequence = NULL;
sequence = new char[length+1];
- strncpy(sequence, str.toLocal8Bit(), length +1);
+ strncpy(sequence, passphrase.toUtf8(), length +1);
- #define MESSAGE ((const unsigned char *) sequence)
- #define MESSAGE_LEN length
+ QString passphraseHash = blake3_PW(sequence);
- unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES];
+ char *sequence1 = NULL;
+ sequence1 = new char[length+1];
+ strncpy(sequence1, passphraseHash.toUtf8(), length+1);
- crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN);
+
+ #define hash ((const unsigned char *) sequence1)
#define PASSWORD sequence
#define KEY_LEN crypto_box_SEEDBYTES
-
-
- /////////we use the Hash of the Password as Salt, not perfect but still a good solution.
-
unsigned char key[KEY_LEN];
if (crypto_pwhash
@@ -513,18 +603,14 @@ void MainWindow::removeWalletEncryption() {
crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */
}
-
-
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QString target_encwallet_file = dirwalletenc;
QString target_decwallet_file = dirwallet;
- QString target_encaddr_file = dir.filePath("addresslabels.dat.enc");
- QString target_decaddr_file = dir.filePath("addresslabels.dat");
FileEncryption::decrypt(target_decwallet_file, target_encwallet_file, key);
- FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, key);
+
QFile filencrypted(dirwalletenc);
QFile wallet(dirwallet);
@@ -556,85 +642,64 @@ void MainWindow::removeWalletEncryptionStartUp() {
QDialog d(this);
Ui_startup ed;
ed.setupUi(&d);
-
+
if (d.exec() == QDialog::Accepted)
{
- QString password = ed.txtPassword->text(); // data comes from user inputs
- int length = password.length();
- DataStore::getChatDataStore()->setPassword(password);
+ QString passphraseBlank = ed.txtPassword->text(); // data comes from user inputs
+
+ QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL");
+ int length = passphrase.length();
+
char *sequence = NULL;
sequence = new char[length+1];
- strncpy(sequence, password.toLocal8Bit(), length +1);
+ strncpy(sequence, passphrase.toUtf8(), length +1);
+
+ QString passphraseHash = blake3_PW(sequence);
+
+
+ char *sequence1 = NULL;
+ sequence1 = new char[length+1];
+ strncpy(sequence1, passphraseHash.toUtf8(), length+1);
#define MESSAGE ((const unsigned char *) sequence)
#define MESSAGE_LEN length
-
- unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES];
-
- crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN);
+ #define hash ((const unsigned char *) sequence1)
#define PASSWORD sequence
- #define KEY_LEN crypto_box_SEEDBYTES
+ #define KEY_LEN crypto_box_SEEDBYTES
-
-
- /////////we use the Hash of the Password as Salt, not perfect but still a good solution.
-
- unsigned char key[KEY_LEN];
+ unsigned char key[KEY_LEN];
- if (crypto_pwhash
- (key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
- crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
- crypto_pwhash_ALG_DEFAULT) != 0) {
+ if (crypto_pwhash
+ (key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
+ crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
+ crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */
- }
+}
+ QString passphraseHash1 = QByteArray(reinterpret_cast(key), KEY_LEN).toHex();
+ DataStore::getChatDataStore()->setPassword(passphraseHash1);
-
- {
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
- auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
+
QString target_encwallet_file = dirwalletenc;
QString target_decwallet_file = dirwallet;
- QString target_encaddr_file = dir.filePath("addresslabels.dat.enc");
- QString target_decaddr_file = dir.filePath("addresslabels.dat");
FileEncryption::decrypt(target_decwallet_file, target_encwallet_file, key);
- FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, key);
- }
+
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QFile wallet(dirwallet);
- //QFile backup(dirHome.filePath(".silentdragonlite/silentdragonlite-wallet.datBACKUP"));*/
- if (wallet.size() > 0)
+ if (wallet.size() == 0)
{
- if (fileExists(dirwalletbackup))
-
- {
-
- QMessageBox::information(this, tr("You still have plaintext data on your disk!"),
- QString("WARNING: Delete it only if you have a backup of your Wallet Seed."),
- QMessageBox::Ok
- );
- // backup.remove();
-
- }
-
- QMessageBox::information(this, tr("Wallet Encryption Success"),
- QString("SDL is ready to Rock"),
- QMessageBox::Ok
- );
-
-
- }else{
-
+
QMessageBox::critical(this, tr("Wallet Encryption Failed"),
QString("false password please try again"),
QMessageBox::Ok
);
this->removeWalletEncryptionStartUp();
- }
+ }else{}
}else{
@@ -655,6 +720,30 @@ void MainWindow::setPassword(QString password)
_password = password;
}
+QString MainWindow::getAmt()
+{
+
+ return _amt;
+}
+
+void MainWindow::setAmt(QString amt)
+{
+
+ _amt = amt;
+}
+
+QString MainWindow::getMoneyMemo()
+{
+
+ return _moneymemo;
+}
+
+void MainWindow::setMoneyMemo(QString moneymemo)
+{
+
+ _moneymemo = moneymemo;
+}
+
void MainWindow::setupStatusBar() {
// Status Bar
loadingLabel = new QLabel();
@@ -731,8 +820,6 @@ void MainWindow::setupSettingsModal() {
QObject::connect(settings.comboBoxTheme, &QComboBox::currentTextChanged, [=] (QString theme_name) {
this->slot_change_theme(theme_name);
- // Tell the user to restart
- QMessageBox::information(this, tr("Restart"), tr("Please restart Silentdragonlite to have the theme apply"), QMessageBox::Ok);
});
// Get Currency Data
@@ -756,7 +843,7 @@ void MainWindow::setupSettingsModal() {
// List of default servers
settings.cmbServer->addItem("https://lite.myhush.org");
- settings.cmbServer->addItem("rnhk4pwlsbaqzx7wcqfy47lijf2opklstaukq35reiz5rn76crfqpjqd.onion:9067");
+ settings.cmbServer->addItem("6onaaujm4ozaokzu.onion:80");
// Load current values into the dialog
@@ -1169,7 +1256,7 @@ void MainWindow::setupBalancesTab() {
QList allAddresses;
allAddresses = getRPC()->getModel()->getAllZAddresses();
- QString depositzaddr = allAddresses[1];
+ QString depositzaddr = allAddresses[0];
deposithush.qrcodeDisplayDeposit->setQrcodeString(depositzaddr);
deposithush.zaddr->setText(depositzaddr);
@@ -1245,9 +1332,9 @@ void MainWindow::setupTransactionsTab() {
// Set up context menu on transactions tab
auto theme = Settings::getInstance()->get_theme_name();
if (theme == "Dark" || theme == "Midnight") {
- ui->listChat->setStyleSheet("background-image: url(:/icons/res/sdlogo.png) ;background-attachment: fixed ;background-position: center center ;background-repeat: no-repeat;background-size: cover");
+ ui->listChat->setStyleSheet("background-image: url(:/icons/res/SDLogo.png) ;background-attachment: fixed ;background-position: center center ;background-repeat: no-repeat");
}
- if (theme == "Default") {ui->listChat->setStyleSheet("background-image: url(:/icons/res/sdlogo2.png) ;background-attachment: fixed ;background-position: center center ;background-repeat: no-repeat;background-size: cover");}
+ if (theme == "Default") {ui->listChat->setStyleSheet("background-image: url(:/icons/res/sdlogo2.png) ;background-attachment: fixed ;background-position: center center ;background-repeat: no-repeat");}
ui->listChat->setResizeMode(QListView::Adjust);
ui->listChat->setWordWrap(true);
@@ -1344,6 +1431,8 @@ void MainWindow::setupTransactionsTab() {
void MainWindow::setupchatTab() {
+ ui->memoTxtChat->setEnabled(false);
+
/////////////Setting Icons for Chattab and different themes
auto theme = Settings::getInstance()->get_theme_name();
@@ -1388,6 +1477,11 @@ void MainWindow::setupchatTab() {
}
QObject::connect(ui->sendChatButton, &QPushButton::clicked, this, &MainWindow::sendChat);
+ QObject::connect(ui->sendChatButton, &QPushButton::clicked, [&] () {
+
+ ui->memoTxtChat->setEnabled(false);
+
+ });
QObject::connect(ui->safeContactRequest, &QPushButton::clicked, this, &MainWindow::addContact);
QObject::connect(ui->pushContact, &QPushButton::clicked, this , &MainWindow::renderContactRequest);
@@ -1411,6 +1505,8 @@ void MainWindow::setupchatTab() {
ui->listChat->addAction(viewexplorer);
ui->listChat->addAction(copytxid);
+ });
+
QObject::connect(copymessage, &QAction::triggered, [=] {
@@ -1503,7 +1599,7 @@ void MainWindow::setupchatTab() {
}
});
-});
+
///////// Add contextmenu
QMenu* contextMenu;
@@ -1513,10 +1609,8 @@ void MainWindow::setupchatTab() {
QAction* requestHushAction;
QAction* subatomicAction;
contextMenu = new QMenu(ui->listContactWidget);
- requestAction = new QAction("Send a contact request - coming soon",contextMenu);
+ HushAction = new QAction("Send or Request Hush ",contextMenu);
editAction = new QAction("Delete this contact",contextMenu);
- HushAction = new QAction("Send a friend some Hush - coming soon",contextMenu);
- requestHushAction = new QAction("Request some Hush - coming soon",contextMenu);
subatomicAction = new QAction("Make a subatomic swap with a friend- coming soon",contextMenu);
@@ -1525,25 +1619,86 @@ void MainWindow::setupchatTab() {
QObject::connect(ui->listContactWidget, &QTableView::clicked, [=] () {
ui->listContactWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
- ui->listContactWidget->addAction(requestAction);
- ui->listContactWidget->addAction(editAction);
ui->listContactWidget->addAction(HushAction);
- ui->listContactWidget->addAction(requestHushAction);
+ ui->listContactWidget->addAction(editAction);
ui->listContactWidget->addAction(subatomicAction);
+ ui->memoTxtChat->setEnabled(true);
- /*QObject::connect(requestHushAction, &QAction::triggered, [=]() {
QModelIndex index = ui->listContactWidget->currentIndex();
- QString label_contact = index.data(Qt::DisplayRole).toString();
+ QString label_contact = index.data(Qt::DisplayRole).toString();
for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
if (label_contact == p.getName()) {
ui->contactNameMemo->setText(p.getName());
rpc->refresh(true);
+
+ }
+ });
+
+ QObject::connect(HushAction, &QAction::triggered, [=]() {
+
+ QModelIndex index = ui->listContactWidget->currentIndex();
+ QString label_contact = index.data(Qt::DisplayRole).toString();
+
+ Ui_transactionHush transaction;
+ QDialog transactionDialog(this);
+ transaction.setupUi(&transactionDialog);
+ Settings::saveRestore(&transactionDialog);
+ // transaction.requestHush->setEnabled(false);
+ // transaction.requestHush->setVisible(false);
+ transaction.amountChat->setValidator(this->getAmountValidator());
+ QString icon = ":icons/res/hush-money-white.png";
+ QPixmap hush(icon);
+ transaction.label_3->setPixmap(hush);
+
+
+
+ for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
+ if (label_contact == p.getName()) {
+
+ QStandardItemModel* contact = new QStandardItemModel();
+ QString avatar = p.getAvatar();
+ QStandardItem* Items1 = new QStandardItem(p.getName());
+ Items1->setData(QIcon(avatar),Qt::DecorationRole);
+ contact->appendRow(Items1);
+ transaction.contactName->setModel(contact);
+ transaction.contactName->setIconSize(QSize(60,70));
+ transaction.contactName->setUniformItemSizes(true);
+ transaction.contactName->setDragDropMode(QAbstractItemView::DropOnly);
+ transaction.contactName->show();
+
}
- MainWindow::showRequesthush();
-
- }); */
+
+ QObject::connect(transaction.sendHush, &QPushButton::clicked, [&] (){
+
+ QString amt = transaction.amountChat->text();
+ QString memo = transaction.MemoMoney->text();
+ this->setAmt(amt);
+ this->setMoneyMemo(memo);
+ transactionDialog.close();
+ });
+
+ QObject::connect(transaction.sendHush, &QPushButton::clicked, this , &MainWindow::sendMoneyChat);
+
+
+
+ QObject::connect(transaction.requestHush, &QPushButton::clicked, [&] (){
+
+ QString amt = transaction.amountChat->text();
+ QString memo = transaction.MemoMoney->text();
+ this->setAmt(amt);
+ this->setMoneyMemo(memo);
+ transactionDialog.close();
+ });
+
+ QObject::connect(transaction.requestHush, &QPushButton::clicked, this , &MainWindow::sendMoneyRequestChat);
+
+
+
+ transactionDialog.exec();
+
+ });
QObject::connect(editAction, &QAction::triggered, [=]() {
QModelIndex index = ui->listContactWidget->currentIndex();
@@ -1566,20 +1721,579 @@ void MainWindow::setupchatTab() {
}
});
+
+
+ui->memoTxtChat->setLenDisplayLabelChat(ui->memoSizeChat);
+
+}
+
+// Create a Tx from the current state of the Chat page.
+Tx MainWindow::createTxFromSendChatPage() {
+ Tx tx;
+ CAmount totalAmt;
+ // For each addr/amt in the Chat tab
+ {
+
+ QString amtStr = this->getAmt();
+ CAmount amt;
+ CAmount amtHm;
+
+ amt = CAmount::fromDecimalString(amtStr);
+ amtHm = CAmount::fromDecimalString("0");
+ totalAmt = totalAmt + amt;
+
QModelIndex index = ui->listContactWidget->currentIndex();
QString label_contact = index.data(Qt::DisplayRole).toString();
-
- for(auto &p : AddressBook::getInstance()->getAllAddressLabels())
- if (label_contact == p.getName()) {
- ui->contactNameMemo->setText(p.getName());
- rpc->refresh(true);
+
+ for(auto &c : AddressBook::getInstance()->getAllAddressLabels())
+
+ if (label_contact == c.getName()) {
+
+ QString cid = c.getCid();
+ QString myAddr = c.getMyAddress();
+ QString type = "Money";
+ QString addr = c.getPartnerAddress();
+ QString moneymemo = this->getMoneyMemo();
+
+ /////////User input for chatmemos
+ QString memoplain = QString("Money transaction of : ") + amtStr + QString(" HUSH") + QString("\n") + QString("\n") + moneymemo;
+
+ /////////We convert the user input from QString to unsigned char*, so we can encrypt it later
+ int lengthmemo = memoplain.length();
+
+ char *memoplainchar = NULL;
+ memoplainchar = new char[lengthmemo+2];
+ strncpy(memoplainchar, memoplain.toUtf8(), lengthmemo +1);
+
+ QString pubkey = this->getPubkeyByAddress(addr);
+ QString passphraseHash = DataStore::getChatDataStore()->getPassword();
+ int length = passphraseHash.length();
+
+ ////////////////Generate the secretkey for our message encryption
+
+ char *hashEncryptionKeyraw = NULL;
+ hashEncryptionKeyraw = new char[length+1];
+ strncpy(hashEncryptionKeyraw, passphraseHash.toUtf8(), length+1);
+
+ #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)
+ #define MESSAGEAS1_LEN length
+
+ unsigned char sk[crypto_kx_SECRETKEYBYTES];
+ unsigned char pk[crypto_kx_PUBLICKEYBYTES];
+ unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
+
+ if (crypto_kx_seed_keypair(pk,sk,
+ MESSAGEAS1) !=0) {
+
+ this->logger->write("Suspicious keypair, bail out ");
+ }
+ ////////////////Get the pubkey from Bob, so we can create the share key
+
+ const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1());
+ const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData());
+ /////Create the shared key for sending the message
+
+ if (crypto_kx_server_session_keys(server_rx, server_tx,
+ pk, sk, pubkeyBob) != 0) {
+ this->logger->write("Suspicious client public send key, bail out ");
+ }
+
+
+ // Let's try to preserve Unicode characters
+ QByteArray ba_memo = memoplain.toUtf8();
+ int ba_memo_length = ba_memo.size();
+
+ #define MESSAGEMoney (const unsigned char *) ba_memo.data()
+ #define MESSAGE_LENMoney ba_memo_length
+
+
+ ////////////Now lets encrypt the message Alice send to Bob//////////////////////////////
+ //#define MESSAGE (const unsigned char *) memoplainchar
+ //#define MESSAGE_LEN lengthmemo
+ #define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LENMoney)
+ unsigned char ciphertext[CIPHERTEXT_LEN];
+ unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
+
+ crypto_secretstream_xchacha20poly1305_state state;
+
+ /* Set up a new stream: initialize the state and create the header */
+ crypto_secretstream_xchacha20poly1305_init_push(&state, header, server_tx);
+
+
+ /* Now, encrypt the first chunk. `c1` will contain an encrypted,
+ * authenticated representation of `MESSAGE_PART1`. */
+ crypto_secretstream_xchacha20poly1305_push
+ (&state, ciphertext, NULL, MESSAGEMoney, MESSAGE_LENMoney, NULL, 0, crypto_secretstream_xchacha20poly1305_TAG_FINAL);
+
+ ////Create the HM for this message
+ QString headerbytes = QByteArray(reinterpret_cast(header), crypto_secretstream_xchacha20poly1305_HEADERBYTES).toHex();
+ QString publickeyAlice = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex();
+
+
+ QString hmemo= createHeaderMemo(type,cid,myAddr,headerbytes,publickeyAlice,1,0);
+
+ /////Ciphertext Memo
+ QString memo = QByteArray(reinterpret_cast(ciphertext), CIPHERTEXT_LEN).toHex();
+
+
+ tx.toAddrs.push_back(ToFields{addr, amtHm, hmemo});
+ tx.toAddrs.push_back(ToFields{addr, amt, memo});
+
+ }
+ }
+
+ tx.fee = Settings::getMinerFee();
+
+ return tx;
+
+}
+
+void MainWindow::sendMoneyChat() {
+
+////////////////////////////Todo: Check if a Contact is selected//////////
+
+ // Create a Tx from the values on the send tab. Note that this Tx object
+ // might not be valid yet.
+
+ /* QString Name = ui->contactNameMemo->text();
+
+ if ((ui->contactNameMemo->text().isEmpty()) || (ui->memoTxtChat->toPlainText().trimmed().isEmpty())) {
+
+ QMessageBox msg(QMessageBox::Critical, tr("You have to select a contact and insert a Memo"),
+ tr("You have selected no Contact from Contactlist,\n") + tr("\nor your Memo is empty"),
+ QMessageBox::Ok, this);
+
+ msg.exec();
+ return;
+ }*/
+
+
+ Tx tx = createTxFromSendChatPage();
+
+ QString error = doSendChatMoneyTxValidations(tx);
+
+ if (!error.isEmpty()) {
+ // Something went wrong, so show an error and exit
+ QMessageBox msg(QMessageBox::Critical, tr("Message Error"), error,
+ QMessageBox::Ok, this);
+
+ msg.exec();
+ ui->memoTxtChat->setEnabled(true);
+
+ // abort the Tx
+ return;
+ }
+
+ auto movie = new QMovie(this);
+ auto movie1 = new QMovie(this);
+ movie->setFileName(":/img/res/loaderblack.gif");
+ movie1->setFileName(":/img/res/loaderwhite.gif");
+
+ auto theme = Settings::getInstance()->get_theme_name();
+ if (theme == "Dark" || theme == "Midnight") {
+
+ connect(movie, &QMovie::frameChanged, [=]{
+ ui->sendChatButton->setIcon(movie->currentPixmap());
+ });
+ movie->start();
+ ui->sendChatButton->show();
+ ui->sendChatButton->setEnabled(false);
+
+ } else {
+
+ connect(movie1, &QMovie::frameChanged, [=]{
+ ui->sendChatButton->setIcon(movie1->currentPixmap());
+ });
+ movie1->start();
+ ui->sendChatButton->show();
+ ui->sendChatButton->setEnabled(false);
+ ui->memoTxtChat->setEnabled(false);
}
- });
+
+ ui->memoTxtChat->clear();
+
+ // And send the Tx
+ rpc->executeTransaction(tx,
+ [=] (QString txid) {
+ ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
+
+
+ QTimer::singleShot(1000, [=]() {
+
+ if (theme == "Dark" || theme == "Midnight") {
+ QPixmap send(":/icons/res/send-white.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie->stop();
+ ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
+ }else{
+
+ QPixmap send(":/icons/res/sendBlack.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie1->stop();
+ ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
+ }
+
+ });
+
+ // Force a UI update so we get the unconfirmed Tx
+ rpc->refresh(true);
+ ui->memoTxtChat->clear();
+ // ui->memoTxtChat->setEnabled(true);
+
+ },
+ // Errored out
+ [=] (QString opid, QString errStr) {
+ ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000);
+ ui->memoTxtChat->setEnabled(true);
+
+ if (!opid.isEmpty())
+ errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
+
+ QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
+ movie->stop();
+ ui->memoTxtChat->setEnabled(true);
+
+
+ if (theme == "Dark" || theme == "Midnight") {
+ QPixmap send(":/icons/res/send-white.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie->stop();
+ ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
+ }else{
+
+ QPixmap send(":/icons/res/sendBlack.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie1->stop();
+ ui->sendChatButton->setEnabled(true);
+ ui->memoTxtChat->setEnabled(true);
+ }
+
+
+ }
+ );
+
+ }
+
+QString MainWindow::doSendChatMoneyTxValidations(Tx tx) {
+ // Check to see if we have enough verified funds to send the Tx.
+
+ CAmount total;
+ for (auto toAddr : tx.toAddrs) {
+ if (!Settings::isValidAddress(toAddr.addr)) {
+ QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr);
+ return QString(tr("Recipient Address ")) % addr % tr(" is Invalid");
+ ui->memoTxtChat->setEnabled(true);
+ }
+
+ // This technically shouldn't be possible, but issue #62 seems to have discovered a bug
+ // somewhere, so just add a check to make sure.
+ if (toAddr.amount.toqint64() < 0) {
+ return QString(tr("Amount for address '%1' is invalid!").arg(toAddr.addr));
+ ui->memoTxtChat->setEnabled(true);
+ }
+
+ total = total + toAddr.amount;
+ }
+ total = total + tx.fee;
+
+ auto available = rpc->getModel()->getAvailableBalance();
+
+ if (available < total) {
+ return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent")
+ .arg(available.toDecimalhushString(), total.toDecimalhushString());
+ ui->memoTxtChat->setEnabled(true);
+
+ }
+
+ return "";
+}
+
+// Create a Tx from the current state of the Chat page.
+Tx MainWindow::createTxFromSendRequestChatPage() {
+ Tx tx;
+ CAmount totalAmt;
+ // For each addr/amt in the Chat tab
+ {
+
+ QString amtStr = this->getAmt();
+ CAmount amt;
+ CAmount amtHm;
+
+ amt = CAmount::fromDecimalString("0");
+ amtHm = CAmount::fromDecimalString("0");
+ totalAmt = totalAmt + amt;
+
+ QModelIndex index = ui->listContactWidget->currentIndex();
+ QString label_contact = index.data(Qt::DisplayRole).toString();
+
+ for(auto &c : AddressBook::getInstance()->getAllAddressLabels())
+
+ if (label_contact == c.getName()) {
+
+ QString cid = c.getCid();
+ QString myAddr = c.getMyAddress();
+ QString type = "Money";
+ QString addr = c.getPartnerAddress();
+ QString moneymemo = this->getMoneyMemo();
+
+ /////////User input for chatmemos
+ QString memoplain = QString("Request of : ") + amtStr + QString(" HUSH ") + QString("\n") + QString("\n") + moneymemo;
+
+ /////////We convert the user input from QString to unsigned char*, so we can encrypt it later
+ int lengthmemo = memoplain.length();
+
+ char *memoplainchar = NULL;
+ memoplainchar = new char[lengthmemo+2];
+ strncpy(memoplainchar, memoplain.toUtf8(), lengthmemo +1);
+
+ QString pubkey = this->getPubkeyByAddress(addr);
+ QString passphraseHash = DataStore::getChatDataStore()->getPassword();
+ int length = passphraseHash.length();
+
+ ////////////////Generate the secretkey for our message encryption
+
+ char *hashEncryptionKeyraw = NULL;
+ hashEncryptionKeyraw = new char[length+1];
+ strncpy(hashEncryptionKeyraw, passphraseHash.toUtf8(), length+1);
+
+ #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)
+ #define MESSAGEAS1_LEN length
+
+
+ unsigned char sk[crypto_kx_SECRETKEYBYTES];
+ unsigned char pk[crypto_kx_PUBLICKEYBYTES];
+ unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
+
+ if (crypto_kx_seed_keypair(pk,sk,
+ MESSAGEAS1) !=0) {
+
+ this->logger->write("Suspicious keypair, bail out ");
+ }
+ ////////////////Get the pubkey from Bob, so we can create the share key
+
+ const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1());
+ const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData());
+ /////Create the shared key for sending the message
+
+ if (crypto_kx_server_session_keys(server_rx, server_tx,
+ pk, sk, pubkeyBob) != 0) {
+ this->logger->write("Suspicious client public send key, bail out ");
+ }
+
+
+ // Let's try to preserve Unicode characters
+ QByteArray ba_memo = memoplain.toUtf8();
+ int ba_memo_length = ba_memo.size();
+
+ #define MESSAGEMoney (const unsigned char *) ba_memo.data()
+ #define MESSAGE_LENMoney ba_memo_length
+
+
+ ////////////Now lets encrypt the message Alice send to Bob//////////////////////////////
+ //#define MESSAGE (const unsigned char *) memoplainchar
+ //#define MESSAGE_LEN lengthmemo
+ #define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LENMoney)
+ unsigned char ciphertext[CIPHERTEXT_LEN];
+ unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
+
+ crypto_secretstream_xchacha20poly1305_state state;
+
+ /* Set up a new stream: initialize the state and create the header */
+ crypto_secretstream_xchacha20poly1305_init_push(&state, header, server_tx);
+
+
+ /* Now, encrypt the first chunk. `c1` will contain an encrypted,
+ * authenticated representation of `MESSAGE_PART1`. */
+ crypto_secretstream_xchacha20poly1305_push
+ (&state, ciphertext, NULL, MESSAGEMoney, MESSAGE_LENMoney, NULL, 0, crypto_secretstream_xchacha20poly1305_TAG_FINAL);
+
+ ////Create the HM for this message
+ QString headerbytes = QByteArray(reinterpret_cast(header), crypto_secretstream_xchacha20poly1305_HEADERBYTES).toHex();
+ QString publickeyAlice = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex();
+
+
+ QString hmemo= createHeaderMemo(type,cid,myAddr,headerbytes,publickeyAlice,1,0);
+
+ /////Ciphertext Memo
+ QString memo = QByteArray(reinterpret_cast(ciphertext), CIPHERTEXT_LEN).toHex();
+
-ui->memoTxtChat->setLenDisplayLabelChat(ui->memoSizeChat);
+ tx.toAddrs.push_back(ToFields{addr, amtHm, hmemo});
+ tx.toAddrs.push_back(ToFields{addr, amt, memo});
+
+ }
+ }
+
+ tx.fee = Settings::getMinerFee();
+
+ return tx;
+
+}
+
+void MainWindow::sendMoneyRequestChat() {
+
+////////////////////////////Todo: Check if a Contact is selected//////////
+
+ // Create a Tx from the values on the send tab. Note that this Tx object
+ // might not be valid yet.
+
+ /* QString Name = ui->contactNameMemo->text();
+
+ if ((ui->contactNameMemo->text().isEmpty()) || (ui->memoTxtChat->toPlainText().trimmed().isEmpty())) {
+
+ QMessageBox msg(QMessageBox::Critical, tr("You have to select a contact and insert a Memo"),
+ tr("You have selected no Contact from Contactlist,\n") + tr("\nor your Memo is empty"),
+ QMessageBox::Ok, this);
+
+ msg.exec();
+ return;
+ }*/
+
+
+ Tx tx = createTxFromSendRequestChatPage();
+
+ QString error = doSendChatMoneyRequestTxValidations(tx);
+
+ if (!error.isEmpty()) {
+ // Something went wrong, so show an error and exit
+ QMessageBox msg(QMessageBox::Critical, tr("Message Error"), error,
+ QMessageBox::Ok, this);
+
+ msg.exec();
+
+ // abort the Tx
+ return;
+ }
+
+ auto movie = new QMovie(this);
+ auto movie1 = new QMovie(this);
+ movie->setFileName(":/img/res/loaderblack.gif");
+ movie1->setFileName(":/img/res/loaderwhite.gif");
+
+ auto theme = Settings::getInstance()->get_theme_name();
+ if (theme == "Dark" || theme == "Midnight") {
+
+ connect(movie, &QMovie::frameChanged, [=]{
+ ui->sendChatButton->setIcon(movie->currentPixmap());
+ });
+ movie->start();
+ ui->sendChatButton->show();
+ ui->sendChatButton->setEnabled(false);
+
+ } else {
+
+ connect(movie1, &QMovie::frameChanged, [=]{
+ ui->sendChatButton->setIcon(movie1->currentPixmap());
+ });
+ movie1->start();
+ ui->sendChatButton->show();
+ ui->sendChatButton->setEnabled(false);
+ }
+
+ ui->memoTxtChat->clear();
+
+ // And send the Tx
+ rpc->executeTransaction(tx,
+ [=] (QString txid) {
+ ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
+
+
+ QTimer::singleShot(1000, [=]() {
+
+ if (theme == "Dark" || theme == "Midnight") {
+ QPixmap send(":/icons/res/send-white.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie->stop();
+ ui->sendChatButton->setEnabled(true);
+ }else{
+
+ QPixmap send(":/icons/res/sendBlack.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie1->stop();
+ ui->sendChatButton->setEnabled(true);
+ }
+
+ });
+
+ // Force a UI update so we get the unconfirmed Tx
+ rpc->refresh(true);
+ ui->memoTxtChat->clear();
+
+ },
+ // Errored out
+ [=] (QString opid, QString errStr) {
+ ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000);
+
+ if (!opid.isEmpty())
+ errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
+
+ QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
+ movie->stop();
+
+
+ if (theme == "Dark" || theme == "Midnight") {
+ QPixmap send(":/icons/res/send-white.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie->stop();
+ ui->sendChatButton->setEnabled(true);
+ }else{
+
+ QPixmap send(":/icons/res/sendBlack.png");
+ QIcon sendIcon(send);
+ ui->sendChatButton->setIcon(sendIcon);
+ movie1->stop();
+ ui->sendChatButton->setEnabled(true);
+ }
+
+
+
+ }
+ );
+
+ }
+
+QString MainWindow::doSendChatMoneyRequestTxValidations(Tx tx) {
+ // Check to see if we have enough verified funds to send the Tx.
+
+ CAmount total;
+ for (auto toAddr : tx.toAddrs) {
+ if (!Settings::isValidAddress(toAddr.addr)) {
+ QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr);
+ return QString(tr("Recipient Address ")) % addr % tr(" is Invalid");
+ }
+
+ // This technically shouldn't be possible, but issue #62 seems to have discovered a bug
+ // somewhere, so just add a check to make sure.
+ if (toAddr.amount.toqint64() < 0) {
+ return QString(tr("Amount for address '%1' is invalid!").arg(toAddr.addr));
+ }
+
+ total = total + toAddr.amount;
+ }
+ total = total + tx.fee;
+
+ auto available = rpc->getModel()->getAvailableBalance();
+
+ if (available < total) {
+ return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent")
+ .arg(available.toDecimalhushString(), total.toDecimalhushString());
+ }
+
+ return "";
}
+
void MainWindow::updateChat()
{
rpc->refreshChat(ui->listChat,ui->memoSizeChat);
@@ -1993,7 +2707,7 @@ void MainWindow::slot_change_theme(const QString& theme_name)
if (qFile.open(QFile::ReadOnly))
{
QString styleSheet = QLatin1String(qFile.readAll());
- this->setStyleSheet(""); // reset styles
+ this->setStyleSheet(""); // resets styles, makes app restart unnecessary
this->setStyleSheet(styleSheet);
}
@@ -2029,3 +2743,125 @@ void MainWindow::on_givemeZaddr_clicked()
});
}
+
+void MainWindow::on_emojiButton_clicked()
+{
+
+ QDialog emojiDialog(this);
+ Ui_emojiDialog emoji;
+ emoji.setupUi(&emojiDialog);
+ Settings::saveRestore(&emojiDialog);
+
+QObject::connect(emoji.smiley, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":smiley:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.money, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":money_mouth:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.laughing, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":laughing:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.sweet_smile, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":sweet_smile:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.joy, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":joy:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.innocent, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":innocent:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.partying_face, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":partying_face:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.rolling_eyes, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":rolling_eyes:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.tongue, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":stuck_out_tongue:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.hearts3, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":face_with_3hearts:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.heart_eyes, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":heart_eyes:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.nauseated, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":nauseated:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.poop, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":poop:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.symbols_mouth, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":symbols_mouth:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.sunglass, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":sunglass:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.stuck_out, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":stuck_out:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.hush_white, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":hush_white:");
+
+ emojiDialog.close();
+});
+
+QObject::connect(emoji.sd, &QPushButton::clicked, [&] () {
+ ui->memoTxtChat->insertHtml(":sd:");
+
+ emojiDialog.close();
+});
+
+
+
+ emojiDialog.exec();
+}
+
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 62ff3f3..09edc6e 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -7,6 +7,8 @@
#include "recurring.h"
#include "firsttimewizard.h"
+using json = nlohmann::json;
+
// Forward declare to break circular dependency.
class Controller;
class Settings;
@@ -14,7 +16,6 @@ class WSServer;
class WormholeClient;
class ChatModel;
-using json = nlohmann::json;
// Struct used to hold destination info when sending a Tx.
struct ToFields {
@@ -50,12 +51,18 @@ public:
QString doSendTxValidations(Tx tx);
QString doSendChatTxValidations(Tx tx);
+ QString doSendChatMoneyTxValidations(Tx tx);
QString doSendRequestTxValidations(Tx tx);
+ QString doSendChatMoneyRequestTxValidations(Tx tx);
QString getCid();
+ QString getAmt();
+ QString getMoneyMemo();
QString getPassword();
std::map pubkeyMap;
QString getPubkeyByAddress(QString requestZaddr);
void setPassword(QString Password);
+ void setAmt(QString Amt);
+ void setMoneyMemo(QString MoneyMemo);
void addPubkey(QString requestZaddr, QString pubkey);
@@ -106,12 +113,15 @@ private slots:
void on_givemeZaddr_clicked();
+ void on_emojiButton_clicked();
private:
bool fileExists(QString path);
void closeEvent(QCloseEvent* event);
void closeEventpw(QCloseEvent* event);
QString _password;
+ QString _amt;
+ QString _moneymemo;
void setupSendTab();
@@ -136,7 +146,8 @@ private:
Tx createTxFromChatPage();
Tx createTxForSafeContactRequest();
-
+ Tx createTxFromSendChatPage();
+ Tx createTxFromSendRequestChatPage();
void encryptWallet();
void removeWalletEncryption();
@@ -145,6 +156,8 @@ private:
void cancelButton();
void sendButton();
void sendChat();
+ void sendMoneyChat();
+ void sendMoneyRequestChat();
void addContact();
void ContactRequest();
@@ -215,5 +228,21 @@ private:
QPushButton* sendChatButton = nullptr;
};
+class ChatMemoEditRequest : public QTextEdit
+{
+public:
+ ChatMemoEditRequest(QWidget* parent);
+
+ void setMaxLenChatRequest(int len);
+ void setLenDisplayLabelChatRequest(QLabel* label);
+ void SetSendRequestButton(QPushButton* button);
+ void updateDisplayChatRequest();
+
+private:
+ int maxlenchatrequest = 512;
+ QLabel* lenDisplayLabelchatRequest = nullptr;
+ QPushButton* sendRequestButton = nullptr;
+};
+
#endif // MAINWINDOW_H
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index 8471227..4e62995 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -6,7 +6,7 @@
0
0
- 1274
+ 1308
779
@@ -59,7 +59,7 @@
-
- 2
+ 0
@@ -428,8 +428,8 @@
0
0
- 1226
- 493
+ 1260
+ 509
@@ -1341,8 +1341,8 @@
HushChat
-
-
-
+
+
-
-
@@ -1546,7 +1546,7 @@
- -
+
-
QLayout::SetDefaultConstraint
@@ -1683,6 +1683,12 @@
0
+
+
+ 850
+ 0
+
+
false
@@ -1706,9 +1712,48 @@
+ -
+
+
+
+ 20
+ 0
+
+
+
+
+
+
+
+ :/emoji/res/emoji/emoji1.png
+
+
+
+
+ 17
+ 17
+
+
+
+ true
+
+
+
-
-
-
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
@@ -1716,6 +1761,12 @@
0
+
+
+ 16777215
+ 50
+
+
100
@@ -1747,7 +1798,7 @@
- -
+
-
@@ -1783,7 +1834,7 @@
0
0
- 1274
+ 1308
22
diff --git a/src/newwallet.ui b/src/newwallet.ui
index 9f1e76c..a307069 100644
--- a/src/newwallet.ui
+++ b/src/newwallet.ui
@@ -6,114 +6,129 @@
0
0
- 437
- 381
+ 950
+ 717
+
+
+ 0
+ 0
+
+
+
+
+ 950
+ 734
+
+
Create New SDL Wallet
-
-
-
-
- Confirm Passphrase:
-
-
-
- -
-
-
- QLineEdit::Password
-
-
-
- -
-
+
-
+
-
+
0
0
-
-
-
-
-
-
-
-
- Restore wallet from seed
-
-
-
- -
-
-
- Restore an existing wallet, using the 24-word seed.
-
-
- true
-
-
-
-
-
-
- -
-
-
- QLineEdit::Password
+
+
+ 931
+ 192
+
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ QAbstractScrollArea::AdjustToContentsOnFirstShow
- -
-
-
-
- 0
- 0
-
+
-
+
+
+ Qt::Vertical
-
-
-
-
-
-
-
-
- Create a new wallet
-
-
-
- -
-
-
- Create a new wallet with a randomly generated seed.
-
-
- true
-
-
-
-
-
+
+
+ 20
+ 50
+
+
+
-
-
-
- Qt::Horizontal
+
+
+
+ 931
+ 150
+
+
+
+
+ 949
+ 16777215
+
+
+
+ false
+
+
+
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
+<h1 align="center" style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:600;">Hush + HushChat Terms of Service</span></h1>
+<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All users of this platform agree to not use it for initiating or threatening any forceful interference or violence on an individual or their property, aka, the <a href="https://en.wikipedia.org/wiki/Non-aggression_principle"><span style=" text-decoration: underline; color:#0000ff;">Non-Aggression Principle</span></a>.</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">THE SERVICE IS PROVIDED “AS IS” AND The Hush Developers DO NOT MAKE ANY SPECIFIC COMMITMENTS OR WARRANTIES ABOUT THE SERVICE.</p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">By clicking OK, you agree to use Hush, the SilentDragon family of wallets, HushChat, and any software developed by The Hush Developers in accordance with your local laws, that all liabilities related to using this service are your own, and The Hush Developers WILL NOT BE RESPONSIBLE FOR any losses related to using this software.</p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html>
+
+
+ true
- -
-
+
-
+
+
+
+ 251
+ 16777215
+
+
- Encryption Passphrase:
+ I accept the Terms of Service
- -
+
-
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 49
+
+
+
+
+ -
@@ -121,6 +136,12 @@
0
+
+
+ 711
+ 0
+
+
color: red;
@@ -132,7 +153,7 @@
- -
+
-
@@ -145,6 +166,125 @@
+ -
+
+
+ Encryption Passphrase:
+
+
+
+ -
+
+
+
+ 611
+ 0
+
+
+
+ QLineEdit::Password
+
+
+
+ -
+
+
+ Confirm Passphrase:
+
+
+
+ -
+
+
+
+ 611
+ 0
+
+
+
+ QLineEdit::Password
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 431
+ 90
+
+
+
+
+ 431
+ 90
+
+
+
+
+
+
+
-
+
+
+ Restore wallet from seed
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 431
+ 0
+
+
+
+
+ 431
+ 90
+
+
+
+
+
+
+
-
+
+
+ Create a new wallet
+
+
+
+
+
+
+
+
diff --git a/src/precompiled.h b/src/precompiled.h
index 1826cda..80905dc 100644
--- a/src/precompiled.h
+++ b/src/precompiled.h
@@ -71,9 +71,10 @@
#include
#include
#include
+#include
-#include "3rdparty/json/json.hpp"
#include "3rdparty/qrcode/QrCode.hpp"
+#include "3rdparty/json/json.hpp"
#define SODIUM_STATIC
#include "3rdparty/sodium.h"
diff --git a/src/recurring.cpp b/src/recurring.cpp
index 471cd90..dd10f70 100644
--- a/src/recurring.cpp
+++ b/src/recurring.cpp
@@ -319,7 +319,7 @@ QString Recurring::writeableFile() {
auto filename = QStringLiteral("recurringpayments.json");
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
- if (!dir.exists())
+ if (dir.exists())
QDir().mkpath(dir.absolutePath());
if (Settings::getInstance()->isTestnet()) {
@@ -353,6 +353,9 @@ void Recurring::removeRecurringInfo(QString hash) {
void Recurring::readFromStorage() {
+
+ if (writeableFile().isEmpty())
+ {
QFile file(writeableFile());
file.open(QIODevice::ReadOnly);
@@ -365,10 +368,14 @@ void Recurring::readFromStorage() {
auto p = RecurringPaymentInfo::fromJson(k.toObject());
payments.insert(p.getHash(), p);
}
+ }else{}
}
void Recurring::writeToStorage() {
+
+ if (writeableFile().isEmpty())
+ {
QFile file(writeableFile());
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
@@ -381,6 +388,7 @@ void Recurring::writeToStorage() {
out << QJsonDocument(arr).toJson();
file.close();
+}else{}
}
/**
diff --git a/src/restoreSeed.ui b/src/restoreSeed.ui
new file mode 100644
index 0000000..fb923db
--- /dev/null
+++ b/src/restoreSeed.ui
@@ -0,0 +1,72 @@
+
+
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ Dialog
+
+
+
+
+ 30
+ 240
+ 341
+ 32
+
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ Dialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ Dialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
+
diff --git a/src/restoreseed.ui b/src/restoreseed.ui
index 64bd43f..fb549dc 100644
--- a/src/restoreseed.ui
+++ b/src/restoreseed.ui
@@ -6,24 +6,14 @@
0
0
- 400
- 300
+ 498
+ 575
Restore Wallet Seed
- -
-
-
- Please enter your 24-word seed below
-
-
- true
-
-
-
-
@@ -35,36 +25,36 @@
-
-
-
+
+
-
Wallet Seed
- -
+
-
false
- -
+
-
Wallet Birthday
- -
+
-
0
- -
+
-
@@ -79,9 +69,48 @@
+ -
+
+
+ Quantity
+
+
+
+ -
+
+
+ 10
+
+
+
+ -
+
+
+
+ 9
+
+
+
+ The quantity of shielded addresses that gets recreated during the restore process
+
+
+ true
+
+
+
+ -
+
+
+ Please enter your 24-word seed below
+
+
+ true
+
+
+
diff --git a/src/scripts/mkrelease.sh b/src/scripts/mkrelease.sh
index 15e22ac..1a965df 100755
--- a/src/scripts/mkrelease.sh
+++ b/src/scripts/mkrelease.sh
@@ -35,6 +35,15 @@ rm -rf bin/SilentDragonLite* > /dev/null
# Build the lib first
cd lib && make release && cd ..
make -j$(nproc) > /dev/null
+make install INSTALL_ROOT=AppDir
+
+# now, build AppImage using linuxdeploy and linuxdeploy-plugin-qt
+# download linuxdeploy and its Qt plugin
+wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
+wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
+
+# make them executable
+chmod +x linuxdeploy*.AppImage
echo "[OK]"
diff --git a/src/seedrestore.ui b/src/seedrestore.ui
new file mode 100644
index 0000000..697c2c2
--- /dev/null
+++ b/src/seedrestore.ui
@@ -0,0 +1,114 @@
+
+
+ Restore
+
+
+
+ 0
+ 0
+ 637
+ 429
+
+
+
+ Restore your Wallet
+
+
+ -
+
+
+
+ 0
+ 284
+
+
+
+
+ -
+
+
-
+
+
+ Birthday :
+
+
+
+ -
+
+
+ Quantity :
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 529
+ 0
+
+
+
+
+ 16777215
+ 25
+
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+
+ -
+
+
+
+ 529
+ 0
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 521
+ 20
+
+
+
+
+ -
+
+
+
+ 89
+ 16777215
+
+
+
+ Restore
+
+
+
+
+
+
+
+
diff --git a/src/sendHushTransactionChat.ui b/src/sendHushTransactionChat.ui
new file mode 100644
index 0000000..94bc851
--- /dev/null
+++ b/src/sendHushTransactionChat.ui
@@ -0,0 +1,276 @@
+
+
+ transactionHush
+
+
+
+ 0
+ 0
+ 212
+ 405
+
+
+
+ Send or Request Hush
+
+
+ -
+
+
+ To :
+
+
+
+ -
+
+
+ QLayout::SetFixedSize
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+
+ 16777215
+ 70
+
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ false
+
+
+
+
+
+ -
+
+
+ QLayout::SetFixedSize
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+
+ 80
+ 16777215
+
+
+
+ Amount:
+
+
+
+ -
+
+
+
+ 80
+ 16777215
+
+
+
+
+ 200
+ 0
+
+
+
+ 9
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ Amount
+
+
+
+ -
+
+
+
+ 35
+ 16777215
+
+
+
+ Hush
+
+
+
+
+
+ -
+
+
+ Memo :
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+ 0
+ 41
+
+
+
+
+ 16777215
+ 41
+
+
+
+ 100
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 39
+
+
+
+
+ -
+
+
+ QLayout::SetFixedSize
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+ Request Hush
+
+
+
+ -
+
+
+
+ 16777215
+ 25
+
+
+
+ Send Hush
+
+
+
+
+
+ -
+
+
+ QLayout::SetFixedSize
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
-
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ rejected()
+ transactionHush
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/src/sendtab.cpp b/src/sendtab.cpp
index 7e21261..4d125dd 100644
--- a/src/sendtab.cpp
+++ b/src/sendtab.cpp
@@ -8,9 +8,9 @@
#include "controller.h"
#include "recurring.h"
-
using json = nlohmann::json;
+
void MainWindow::setupSendTab() {
// Create the validator for send to/amount fields
amtValidator = new QRegExpValidator(QRegExp("[0-9]{0,8}\\.?[0-9]{0,8}"));
diff --git a/src/settings.h b/src/settings.h
index c598369..a917d67 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -67,8 +67,6 @@ public:
void set_currency_name(QString currency_name);
-
-
bool isSaplingActive();
void setZECPrice(double p) { ZECPrice = p; }
diff --git a/src/settings.ui b/src/settings.ui
index 57620e5..e9b5c22 100644
--- a/src/settings.ui
+++ b/src/settings.ui
@@ -138,6 +138,11 @@
Default
+ -
+
+ test
+
+
diff --git a/src/version.h b/src/version.h
index 927bb5b..06e80b4 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define APP_VERSION "1.3.3"
+#define APP_VERSION "1.3.8"
diff --git a/src/websockets.cpp b/src/websockets.cpp
index 852a553..3f75e59 100644
--- a/src/websockets.cpp
+++ b/src/websockets.cpp
@@ -923,7 +923,7 @@ void AppDataServer::processGetTransactions(MainWindow* mainWindow, std::shared_p
{"amount", model->getAmt(i)},
{"txid", model->getTxId(i)},
{"address", model->getAddr(i)},
- {"memo", model->getMemo(i)},
+ // {"memo", model->getMemo(i)},
{"confirmations", model->getConfirmations(i)}
});
}