Merge remote-tracking branch 'lucretius/dev' into dev
This commit is contained in:
2
lib/Cargo.lock
generated
2
lib/Cargo.lock
generated
@@ -1849,7 +1849,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "silentdragonlitelib"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.hush.is/hush/silentdragonlite-cli?rev=4ec78a01b4f35b08eff42b10e3be85de87ba2b02#4ec78a01b4f35b08eff42b10e3be85de87ba2b02"
|
||||
source = "git+https://git.hush.is/hush/silentdragonlite-cli?rev=568d7b7860ec0b848cb84474f38b25bed890de09#568d7b7860ec0b848cb84474f38b25bed890de09"
|
||||
dependencies = [
|
||||
"base58",
|
||||
"bellman",
|
||||
|
||||
@@ -12,4 +12,4 @@ crate-type = ["staticlib"]
|
||||
libc = "0.2.58"
|
||||
lazy_static = "1.4.0"
|
||||
blake3 = "0.3.4"
|
||||
silentdragonlitelib = { git = "https://git.hush.is/hush/silentdragonlite-cli", rev = "4ec78a01b4f35b08eff42b10e3be85de87ba2b02" }
|
||||
silentdragonlitelib = { git = "https://git.hush.is/hush/silentdragonlite-cli", rev = "568d7b7860ec0b848cb84474f38b25bed890de09" }
|
||||
|
||||
@@ -6,6 +6,7 @@ use libc::{c_char};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::sync::{Mutex, Arc};
|
||||
use std::cell::RefCell;
|
||||
use std::ptr;
|
||||
|
||||
use silentdragonlitelib::{commands, lightclient::{LightClient, LightClientConfig}};
|
||||
|
||||
@@ -108,33 +109,43 @@ pub extern fn litelib_initialize_new(dangerous: bool,server: *const c_char) -> *
|
||||
|
||||
/// Restore a wallet from the seed phrase
|
||||
#[no_mangle]
|
||||
pub extern fn litelib_initialize_new_from_phrase(dangerous: bool,server: *const c_char,
|
||||
pub extern "C" fn litelib_initialize_new_from_phrase(dangerous: bool, server: *const c_char,
|
||||
seed: *const c_char, birthday: u64, number: u64, overwrite: bool) -> *mut c_char {
|
||||
let server_str = unsafe {
|
||||
assert!(!server.is_null());
|
||||
if server.is_null() || seed.is_null() {
|
||||
println!("Server or seed is null");
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
let server_str = unsafe {
|
||||
CStr::from_ptr(server).to_string_lossy().into_owned()
|
||||
};
|
||||
|
||||
let seed_str = unsafe {
|
||||
assert!(!seed.is_null());
|
||||
|
||||
CStr::from_ptr(seed).to_string_lossy().into_owned()
|
||||
};
|
||||
|
||||
println!("Initializing with server: {}, seed: {}", server_str, seed_str);
|
||||
|
||||
let server = LightClientConfig::get_server_or_default(Some(server_str));
|
||||
let (config, _latest_block_height) = match LightClientConfig::create(server,dangerous) {
|
||||
Ok((c, h)) => (c, h),
|
||||
let (config, _latest_block_height) = match LightClientConfig::create(server, dangerous) {
|
||||
Ok((c, h)) => {
|
||||
println!("Config created successfully");
|
||||
(c, h)
|
||||
},
|
||||
Err(e) => {
|
||||
let e_str = CString::new(format!("Error: {}", e)).unwrap();
|
||||
println!("Error creating config: {}", e);
|
||||
let e_str = CString::new(format!("Error: {}", e)).unwrap_or_else(|_| CString::new("Error creating CString").unwrap());
|
||||
return e_str.into_raw();
|
||||
}
|
||||
};
|
||||
|
||||
let lightclient = match LightClient::new_from_phrase(seed_str, &config, birthday, number, overwrite) {
|
||||
Ok(l) => l,
|
||||
Ok(l) => {
|
||||
println!("LightClient created successfully");
|
||||
l
|
||||
},
|
||||
Err(e) => {
|
||||
let e_str = CString::new(format!("Error: {}", e)).unwrap();
|
||||
println!("Error creating LightClient: {}", e);
|
||||
let e_str = CString::new(format!("Error: {}", e)).unwrap_or_else(|_| CString::new("Error creating CString").unwrap());
|
||||
return e_str.into_raw();
|
||||
}
|
||||
};
|
||||
@@ -144,15 +155,13 @@ pub extern fn litelib_initialize_new_from_phrase(dangerous: bool,server: *const
|
||||
|
||||
let lc = Arc::new(lightclient);
|
||||
match LightClient::start_mempool_monitor(lc.clone()) {
|
||||
Ok(_) => {println!("Starting Mempool")},
|
||||
Err(e) => {
|
||||
println!("Couldnt start mempool {}",e)
|
||||
}
|
||||
Ok(_) => println!("Starting Mempool"),
|
||||
Err(e) => println!("Could not start mempool: {}", e)
|
||||
}
|
||||
|
||||
LIGHTCLIENT.lock().unwrap().replace(Some(lc));
|
||||
|
||||
let c_str = CString::new("OK").unwrap();
|
||||
|
||||
let c_str = CString::new("OK").unwrap_or_else(|_| CString::new("CString creation failed").unwrap());
|
||||
return c_str.into_raw();
|
||||
}
|
||||
|
||||
@@ -185,7 +194,6 @@ pub extern fn litelib_initialize_existing(dangerous: bool, server: *const c_char
|
||||
// Initialize logging
|
||||
let _ = lightclient.init_logging();
|
||||
|
||||
|
||||
let lc = Arc::new(lightclient);
|
||||
match LightClient::start_mempool_monitor(lc.clone()) {
|
||||
Ok(_) => {println!("Starting Mempool")},
|
||||
|
||||
@@ -73,6 +73,7 @@ SOURCES += \
|
||||
src/DataStore/DataStore.cpp \
|
||||
src/DataStore/ChatDataStore.cpp \
|
||||
src/DataStore/SietchDataStore.cpp \
|
||||
src/DataStore/NoteCountDataStore.cpp \
|
||||
src/DataStore/ContactDataStore.cpp \
|
||||
src/Model/ChatItem.cpp \
|
||||
src/Model/ContactRequestChatItem.cpp \
|
||||
|
||||
@@ -93,7 +93,7 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label)
|
||||
DataStore::getChatDataStore()->dump(); // test to see if the chat items in datastore are correctly dumped to json
|
||||
std::map<QString,int> seenTxids;
|
||||
|
||||
qDebug() << __func__ << ": looking at memos...";
|
||||
//qDebug() << __func__ << ": looking at memos...";
|
||||
for (auto &contact : AddressBook::getInstance()->getAllAddressLabels())
|
||||
{
|
||||
for (auto &memo : DataStore::getChatDataStore()->getAllMemos()) {
|
||||
@@ -104,7 +104,7 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label)
|
||||
QStandardItem *Items = new QStandardItem(memo.second.toChatLine());
|
||||
|
||||
Items->setData(OUTGOING, Qt::UserRole + 1);
|
||||
qDebug() << __func__ << ": appending row to OUTGOING chatitems to contact " << contact.getName() << " with item " << Items;
|
||||
// qDebug() << __func__ << ": appending row to OUTGOING chatitems to contact " << contact.getName() << " with item " << Items;
|
||||
chat->appendRow(Items);
|
||||
ui->listChat->setModel(chat);
|
||||
|
||||
@@ -112,7 +112,7 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label)
|
||||
ui->listChat->setModel(chat);
|
||||
}
|
||||
|
||||
qDebug() << __func__ << ": memo.first=" << memo.first;
|
||||
// qDebug() << __func__ << ": memo.first=" << memo.first;
|
||||
if ( (contact.getName() == ui->contactNameMemo->text().trimmed()) &&
|
||||
(contact.getMyAddress() == memo.second.getAddress()) &&
|
||||
(memo.second.isOutgoing() == false) &&
|
||||
@@ -120,19 +120,19 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label)
|
||||
) {
|
||||
QStandardItem *Items1 = new QStandardItem(memo.second.toChatLine());
|
||||
Items1->setData(INCOMING, Qt::UserRole + 1);
|
||||
qDebug() << __func__ << ": appending row to INCOMING chatitems to contact " << contact.getName() << "with txid=" << memo.second.getTxid() << " cid=" << contact.getCid() << " item " << Items1 << " memo=" << memo.second.getMemo();
|
||||
// qDebug() << __func__ << ": appending row to INCOMING chatitems to contact " << contact.getName() << "with txid=" << memo.second.getTxid() << " cid=" << contact.getCid() << " item " << Items1 << " memo=" << memo.second.getMemo();
|
||||
|
||||
|
||||
if(seenTxids.count( memo.second.getTxid() ) > 0) {
|
||||
// Do not render the same chat multiple times
|
||||
// TODO: this should also look at outputindex to allow for multi-part memos, when that is supported
|
||||
qDebug() << __func__ << ": INCOMING ignoring txid=" << memo.second.getTxid();
|
||||
// qDebug() << __func__ << ": INCOMING ignoring txid=" << memo.second.getTxid();
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: better header memo detection
|
||||
if (memo.second.getMemo().startsWith("{")) {
|
||||
qDebug() << __func__ << ": ignoring header memo=" << memo.second.getMemo();
|
||||
// qDebug() << __func__ << ": ignoring header memo=" << memo.second.getMemo();
|
||||
} else {
|
||||
chat->appendRow(Items1);
|
||||
ui->listChat->setModel(chat);
|
||||
|
||||
@@ -7,6 +7,11 @@ SietchDataStore* DataStore::getSietchDataStore()
|
||||
return SietchDataStore::getInstance();
|
||||
}
|
||||
|
||||
NoteCountDataStore* DataStore::getNoteCountDataStore()
|
||||
{
|
||||
return NoteCountDataStore::getInstance();
|
||||
}
|
||||
|
||||
ChatDataStore* DataStore::getChatDataStore()
|
||||
{
|
||||
return ChatDataStore::getInstance();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define DATASTORE_H
|
||||
|
||||
#include "SietchDataStore.h"
|
||||
#include "NoteCountDataStore.h"
|
||||
#include "ChatDataStore.h"
|
||||
#include "ContactDataStore.h"
|
||||
|
||||
@@ -11,6 +12,7 @@ class DataStore
|
||||
{
|
||||
public:
|
||||
static SietchDataStore* getSietchDataStore();
|
||||
static NoteCountDataStore* getNoteCountDataStore();
|
||||
static ChatDataStore* getChatDataStore();
|
||||
static ContactDataStore* getContactDataStore();
|
||||
};
|
||||
|
||||
51
src/DataStore/NoteCountDataStore.cpp
Normal file
51
src/DataStore/NoteCountDataStore.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#include "NoteCountDataStore.h"
|
||||
|
||||
NoteCountDataStore* NoteCountDataStore::instance = nullptr;
|
||||
bool NoteCountDataStore::instanced = false;
|
||||
|
||||
NoteCountDataStore* NoteCountDataStore::getInstance() {
|
||||
if (!instanced) {
|
||||
instanced = true;
|
||||
instance = new NoteCountDataStore();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
void NoteCountDataStore::clear() {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void NoteCountDataStore::setData(const QString& key, const QString& value) {
|
||||
data[key] = value;
|
||||
}
|
||||
|
||||
QString NoteCountDataStore::getData(const QString& key) {
|
||||
return data.value(key);
|
||||
}
|
||||
|
||||
QString NoteCountDataStore::dump() {
|
||||
QString result;
|
||||
for (const auto& key : data.keys()) {
|
||||
result += key + ": " + data[key] + "\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void NoteCountDataStore::setSpendableNotesCount(int count) {
|
||||
spendableNotesCount = count;
|
||||
}
|
||||
|
||||
int NoteCountDataStore::getSpendableNotesCount() const {
|
||||
return spendableNotesCount;
|
||||
}
|
||||
|
||||
void NoteCountDataStore::setAddressWithMaxValue(const QString& address, int value) {
|
||||
if (value > maxValue) {
|
||||
maxValue = value;
|
||||
addressWithMaxValue = address;
|
||||
}
|
||||
}
|
||||
|
||||
QString NoteCountDataStore::getAddressWithMaxValue() const {
|
||||
return addressWithMaxValue;
|
||||
}
|
||||
36
src/DataStore/NoteCountDataStore.h
Normal file
36
src/DataStore/NoteCountDataStore.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef NOTECOUNTDATASTORE_H
|
||||
#define NOTECOUNTDATASTORE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
|
||||
class NoteCountDataStore {
|
||||
private:
|
||||
static NoteCountDataStore* instance;
|
||||
static bool instanced;
|
||||
QMap<QString, QString> data;
|
||||
int spendableNotesCount;
|
||||
QString addressWithMaxValue;
|
||||
int maxValue; // Hinzugefügt, um den maximalen Wert zu speichern
|
||||
|
||||
NoteCountDataStore() : spendableNotesCount(0), maxValue(0) {} // Initialisiere maxValue
|
||||
|
||||
public:
|
||||
static NoteCountDataStore* getInstance();
|
||||
void clear();
|
||||
void setData(const QString& key, const QString& value);
|
||||
QString getData(const QString& key);
|
||||
QString dump();
|
||||
|
||||
void setSpendableNotesCount(int count);
|
||||
int getSpendableNotesCount() const;
|
||||
void setAddressWithMaxValue(const QString& address, int value);
|
||||
QString getAddressWithMaxValue() const;
|
||||
|
||||
~NoteCountDataStore() {
|
||||
instanced = false;
|
||||
instance = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // NOTECOUNTDATASTORE_H
|
||||
@@ -304,7 +304,7 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target)
|
||||
});
|
||||
|
||||
auto fnSetTargetLabelAddr = [=] (QLineEdit* target, QString label, QString addr, QString myAddr, QString cid, QString avatar) {
|
||||
qDebug() << __func__ << ": label=" << label << " cid=" << cid << " avatar=" << avatar;
|
||||
// qDebug() << __func__ << ": label=" << label << " cid=" << cid << " avatar=" << avatar;
|
||||
target->setText(label % "/" % addr % myAddr);
|
||||
};
|
||||
|
||||
|
||||
@@ -449,7 +449,7 @@ Tx MainWindow::createTxFromChatPage() {
|
||||
|
||||
if (crypto_kx_seed_keypair(pk,sk, MESSAGEAS1) !=0) {
|
||||
this->logger->write("Suspicious keypair, bail out ");
|
||||
qDebug() << __func__<< ": Suspicious client public outgoing key from crypto_kx_seed_keypair, aborting!";
|
||||
// qDebug() << __func__<< ": Suspicious client public outgoing key from crypto_kx_seed_keypair, aborting!";
|
||||
return tx;
|
||||
}
|
||||
|
||||
@@ -462,7 +462,7 @@ Tx MainWindow::createTxFromChatPage() {
|
||||
|
||||
if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0) {
|
||||
this->logger->write("Suspicious client public send key, bail out ");
|
||||
qDebug() << __func__ << ": Suspicious client public send key from crypto_kx_server_session_keys, aborting!";
|
||||
// << __func__ << ": Suspicious client public send key from crypto_kx_server_session_keys, aborting!";
|
||||
return tx;
|
||||
}
|
||||
|
||||
@@ -794,7 +794,7 @@ Tx MainWindow::createTxForSafeContactRequest()
|
||||
|
||||
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) {
|
||||
this->logger->write("Suspicious client public contact request key, bail out ");
|
||||
qDebug() << __func__ << ": Suspicious client public send key from crypto_kx_seed_keypair, aborting!";
|
||||
// qDebug() << __func__ << ": Suspicious client public send key from crypto_kx_seed_keypair, aborting!";
|
||||
return tx;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc)
|
||||
connD->setupUi(d);
|
||||
|
||||
auto theme = Settings::getInstance()->get_theme_name();
|
||||
DEBUG("theme " << theme << " has loaded");
|
||||
//DEBUG("theme " << theme << " has loaded");
|
||||
auto size = QSize(512,512);
|
||||
|
||||
if (theme == "Dark" || theme == "Midnight") {
|
||||
@@ -57,7 +57,7 @@ ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc)
|
||||
|
||||
ConnectionLoader::~ConnectionLoader()
|
||||
{
|
||||
DEBUG("destroying ConnectionLoader");
|
||||
// DEBUG("destroying ConnectionLoader");
|
||||
delete isSyncing;
|
||||
delete connD;
|
||||
delete d;
|
||||
@@ -100,64 +100,62 @@ void ConnectionLoader::ShowProgress()
|
||||
config->dangerous = false;
|
||||
config->server = Settings::getInstance()->getSettings().server;
|
||||
|
||||
DEBUG("Creating connection with server=" << config->server);
|
||||
auto connection = makeConnection(config);
|
||||
auto me = this;
|
||||
DEBUG("server=" << config->server << " connection=" << connection << " me=" << me);
|
||||
if (!connection) {
|
||||
DEBUG("Failed to create connection");
|
||||
return;
|
||||
}
|
||||
|
||||
isSyncing = new QAtomicInteger<bool>();
|
||||
isSyncing->store(true);
|
||||
DEBUG("isSyncing");
|
||||
auto me = this;
|
||||
isSyncing = new QAtomicInteger<bool>(true);
|
||||
DEBUG("isSyncing set to true");
|
||||
|
||||
// Do a sync after import
|
||||
syncTimer = new QTimer(main);
|
||||
DEBUG("Beginning sync after import wif");
|
||||
DEBUG("Created syncTimer");
|
||||
connection->doRPC("sync", "", [=](auto) {
|
||||
DEBUG("finished syncing");
|
||||
isSyncing->store(false);
|
||||
// Cancel the timer
|
||||
qDebug()<< "Finished syncing";
|
||||
isSyncing->storeRelaxed(false);
|
||||
syncTimer->deleteLater();
|
||||
// When sync is done, set the connection
|
||||
this->doRPCSetConnectionShield(connection);
|
||||
}, [=](auto) {
|
||||
DEBUG("sync rpc error! server=" << config->server);
|
||||
});
|
||||
|
||||
// While it is syncing, we'll show the status updates while it is alive.
|
||||
QObject::connect(syncTimer, &QTimer::timeout, [=]() {
|
||||
DEBUG("Check the sync status");
|
||||
if (isSyncing != nullptr && isSyncing->load()) {
|
||||
DEBUG("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<json::number_unsigned_t>();
|
||||
qint64 total = reply["total_blocks"].get<json::number_unsigned_t>();
|
||||
me->showInformation(
|
||||
"Syncing... " + QString::number(synced) + " / " + QString::number(total)
|
||||
);
|
||||
}
|
||||
}, [=](QString err) {
|
||||
DEBUG("Sync error " << err);
|
||||
// We may have gotten "Unexpected compression flag: 60"
|
||||
// or some other error, so let's try another server
|
||||
config->server = Settings::getRandomServer();
|
||||
DEBUG("Changed server to " << config->server );
|
||||
});
|
||||
} catch (const std::exception& e) {
|
||||
DEBUG("syncstatus exception: " << e.what() );
|
||||
main->logger->write("catch sync progress reply");
|
||||
if (!isSyncing || !isSyncing->loadRelaxed()) {
|
||||
DEBUG("Syncing complete or isSyncing is null, stopping timer");
|
||||
syncTimer->stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// rethrow exception so loadProgress can catch
|
||||
// it and retry the entire ShowProgress() function again
|
||||
throw new std::runtime_error(std::string("syncstatus failed"));
|
||||
}
|
||||
DEBUG("Checking sync status");
|
||||
try {
|
||||
connection->doRPC("syncstatus", "", [=](json reply) {
|
||||
if (isSyncing && reply.find("synced_blocks") != reply.end()) {
|
||||
qint64 synced = reply["synced_blocks"].get<json::number_unsigned_t>();
|
||||
qint64 total = reply["total_blocks"].get<json::number_unsigned_t>();
|
||||
DEBUG("Sync status: " << synced << " / " << total);
|
||||
me->showInformation(
|
||||
"Syncing... " + QString::number(synced) + " / " + QString::number(total)
|
||||
);
|
||||
}
|
||||
}, [=](QString err) {
|
||||
DEBUG("Sync status error: " << err);
|
||||
config->server = Settings::getRandomServer();
|
||||
DEBUG("Changed server to " << config->server);
|
||||
});
|
||||
} catch (const std::exception& e) {
|
||||
DEBUG("Exception caught in syncstatus: " << e.what());
|
||||
throw;
|
||||
}
|
||||
});
|
||||
|
||||
int interval = 1*1000;
|
||||
int interval = 1 * 1000;
|
||||
syncTimer->setInterval(interval);
|
||||
syncTimer->start();
|
||||
DEBUG("Start sync timer with interval=" << interval);
|
||||
DEBUG("Sync timer started with interval=" << interval);
|
||||
}
|
||||
|
||||
void ConnectionLoader::doAutoConnect()
|
||||
@@ -165,10 +163,10 @@ void ConnectionLoader::doAutoConnect()
|
||||
auto config = std::shared_ptr<ConnectionConfig>(new ConnectionConfig());
|
||||
config->dangerous = false;
|
||||
config->server = Settings::getInstance()->getSettings().server;
|
||||
DEBUG(" server=" << config->server);
|
||||
DEBUG("Creating connection with server=" << config->server);
|
||||
|
||||
// Initialize the library
|
||||
DEBUG("Attempting to initialize library with "<< config->server);
|
||||
DEBUG("Attempting to initialize library with " << config->server);
|
||||
|
||||
// Check to see if there's an existing wallet
|
||||
if (litelib_wallet_exists(Settings::getDefaultChainName().toStdString().c_str())) {
|
||||
@@ -219,56 +217,49 @@ void ConnectionLoader::doAutoConnect()
|
||||
|
||||
auto connection = makeConnection(config);
|
||||
auto me = this;
|
||||
qDebug() << __func__ << ": server=" << config->server
|
||||
<< " connection=" << connection << " me=" << me << endl;
|
||||
qDebug() << __func__ << ": server=" << config->server
|
||||
<< " connection=" << connection << " me=" << me << Qt::endl;
|
||||
|
||||
// After the lib is initialized, try to do get info
|
||||
connection->doRPC("info", "", [=](auto reply) {
|
||||
// If success, set the connection
|
||||
DEBUG("Connection is online.");
|
||||
connection->setInfo(reply);
|
||||
DEBUG("getting Connection reply");
|
||||
isSyncing = new QAtomicInteger<bool>();
|
||||
isSyncing->store(true);
|
||||
DEBUG("isSyncing");
|
||||
isSyncing->storeRelaxed(true);
|
||||
DEBUG("isSyncing set to true");
|
||||
|
||||
// Do a sync at startup
|
||||
syncTimer = new QTimer(main);
|
||||
DEBUG("Beginning sync");
|
||||
DEBUG("Beginning sync at startup");
|
||||
connection->doRPC("sync", "", [=](auto) {
|
||||
DEBUG("finished syncing");
|
||||
isSyncing->store(false);
|
||||
qDebug()<<"finished syncing startup";
|
||||
isSyncing->storeRelaxed(false);
|
||||
// Cancel the timer
|
||||
syncTimer->deleteLater();
|
||||
// When sync is done, set the connection
|
||||
this->doRPCSetConnection(connection);
|
||||
}, [=](auto) mutable {
|
||||
DEBUG("sync rpc error! server=" << config->server);
|
||||
// continually retry sync RPC until it succeeds
|
||||
// don't change server each time it fails
|
||||
bool failed = true;
|
||||
do {
|
||||
// config->server = Settings::getRandomServer();
|
||||
// auto connection = makeConnection(config);
|
||||
// DEBUG("changed server to " << config->server);
|
||||
// Attempt to retry sync RPC with a delay
|
||||
QTimer::singleShot(5000, [=]() { // 5-second delay
|
||||
connection->doRPC("sync", "", [=](auto) mutable {
|
||||
DEBUG("sync success with server=" << config->server);
|
||||
failed = false;
|
||||
isSyncing->store(false);
|
||||
qDebug()<<"sync success with server=" << config->server;
|
||||
isSyncing->storeRelaxed(false);
|
||||
// Cancel the timer
|
||||
syncTimer->deleteLater();
|
||||
// When sync is done, set the connection
|
||||
this->doRPCSetConnection(connection);
|
||||
}, [=](auto) {
|
||||
DEBUG("sync failed with server=" << config->server << " . continuing sync loop" );
|
||||
DEBUG("sync failed with server=" << config->server << " . retrying after delay");
|
||||
});
|
||||
} while (failed);
|
||||
});
|
||||
});
|
||||
|
||||
// While it is syncing, we'll show the status updates while it is alive.
|
||||
QObject::connect(syncTimer, &QTimer::timeout, [=]() {
|
||||
DEBUG("Check the sync status");
|
||||
if (isSyncing != nullptr && isSyncing->load()) {
|
||||
if (isSyncing != nullptr && isSyncing->loadRelaxed()) {
|
||||
DEBUG("Getting the sync status");
|
||||
try {
|
||||
connection->doRPC("syncstatus", "", [=](json reply) {
|
||||
@@ -380,7 +371,7 @@ void ConnectionLoader::showError(QString explanation)
|
||||
|
||||
QString litelib_process_response(char* resp)
|
||||
{
|
||||
qDebug() << __func__ << ": " << resp;
|
||||
//qDebug() << __func__ << ": " << resp;
|
||||
|
||||
char* resp_copy = new char[strlen(resp) + 1];
|
||||
//a safer version of strcpy
|
||||
@@ -398,7 +389,7 @@ QString litelib_process_response(char* resp)
|
||||
void Executor::run()
|
||||
{
|
||||
auto config = std::shared_ptr<ConnectionConfig>(new ConnectionConfig());
|
||||
DEBUG("cmd=" << cmd << " args=" << args << " server=" << config->server);
|
||||
//DEBUG("cmd=" << cmd << " args=" << args << " server=" << config->server);
|
||||
QString response = "";
|
||||
try {
|
||||
char* resp = litelib_execute(this->cmd.toStdString().c_str(), this->args.toStdString().c_str());
|
||||
@@ -461,7 +452,7 @@ Connection::Connection(MainWindow* m, std::shared_ptr<ConnectionConfig> conf)
|
||||
{
|
||||
this->config = conf;
|
||||
this->main = m;
|
||||
qDebug() << __func__;
|
||||
// qDebug() << __func__;
|
||||
// Register the JSON type as a type that can be passed between signals and slots.
|
||||
qRegisterMetaType<json>("json");
|
||||
}
|
||||
@@ -473,7 +464,7 @@ void Connection::doRPC(const QString cmd, const QString args, const std::functio
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG("cmd=" << cmd << " args=" << args);
|
||||
//DEBUG("cmd=" << cmd << " args=" << args);
|
||||
|
||||
// Create a runner.
|
||||
auto runner = new Executor(cmd, args);
|
||||
@@ -488,7 +479,7 @@ void Connection::doRPC(const QString cmd, const QString args, const std::functio
|
||||
|
||||
void Connection::doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function<void(json)>& cb)
|
||||
{
|
||||
DEBUG("cmd=" << cmd << " args=" << args);
|
||||
//DEBUG("cmd=" << cmd << " args=" << args);
|
||||
doRPC(cmd, args, cb, [=] (QString err) {
|
||||
this->showTxError(err);
|
||||
});
|
||||
@@ -496,7 +487,7 @@ void Connection::doRPCWithDefaultErrorHandling(const QString cmd, const QString
|
||||
|
||||
void Connection::doRPCIgnoreError(const QString cmd, const QString args, const std::function<void(json)>& cb)
|
||||
{
|
||||
DEBUG("cmd=" << cmd << " args=" << args);
|
||||
// DEBUG("cmd=" << cmd << " args=" << args);
|
||||
doRPC(cmd, args, cb, [=] (auto) {
|
||||
// Ignored error handling
|
||||
});
|
||||
@@ -504,7 +495,7 @@ void Connection::doRPCIgnoreError(const QString cmd, const QString args, const s
|
||||
|
||||
void Connection::showTxError(const QString& error)
|
||||
{
|
||||
qDebug() << __func__ << ": " << error;
|
||||
// qDebug() << __func__ << ": " << error;
|
||||
if (error.isNull())
|
||||
return;
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#include "camount.h"
|
||||
#include "Model/ChatItem.h"
|
||||
#include "DataStore/DataStore.h"
|
||||
#include <future>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
|
||||
ChatModel *chatModel = new ChatModel();
|
||||
Chat *chat = new Chat();
|
||||
@@ -19,12 +22,12 @@ using json = nlohmann::json;
|
||||
Controller::Controller(MainWindow* main)
|
||||
{
|
||||
auto cl = new ConnectionLoader(main, this);
|
||||
qDebug() << __func__ << ": cl=" << cl << endl;
|
||||
//qDebug() << __func__ << ": cl=" << cl << endl;
|
||||
|
||||
// Execute the load connection async, so we can set up the rest of RPC properly.
|
||||
QTimer::singleShot(1, [=]() { cl->loadConnection(); });
|
||||
|
||||
qDebug() << __func__ << "after loadConnection" << endl;
|
||||
// qDebug() << __func__ << "after loadConnection" << endl;
|
||||
|
||||
this->main = main;
|
||||
this->ui = main->ui;
|
||||
@@ -122,6 +125,10 @@ void Controller::setConnection(Connection* c)
|
||||
|
||||
ui->listChat->verticalScrollBar()->setValue(
|
||||
ui->listChat->verticalScrollBar()->maximum());
|
||||
|
||||
//fetch amounts of notes at startup
|
||||
fetchAndProcessUnspentNotes();
|
||||
|
||||
}
|
||||
|
||||
// Build the RPC JSON Parameters for this tx
|
||||
@@ -133,8 +140,10 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx)
|
||||
json rec = json::object();
|
||||
|
||||
//creating the JSON dust parameters in a std::vector to iterate over there during tx
|
||||
std::vector<json> dust(8);
|
||||
dust.resize(8, json::object());
|
||||
std::vector<json> dustTransactions(8);
|
||||
for (auto& dust : dustTransactions) {
|
||||
dust = json::object();
|
||||
}
|
||||
|
||||
// Create Sietch zdust addr again to not use it twice.
|
||||
// Using DataStore singelton, to store the data outside of lambda, bing bada boom :D
|
||||
@@ -149,11 +158,20 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx)
|
||||
// Using DataStore singelton, to store the data into the dust.
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
dust.at(i)["address"] = DataStore::getSietchDataStore()->getData(QString("Sietch" + QString(i))).toStdString();
|
||||
dustTransactions.at(i)["address"] = DataStore::getSietchDataStore()->getData(QString("Sietch" + QString(i))).toStdString();
|
||||
}
|
||||
|
||||
DataStore::getSietchDataStore()->clear(); // clears the datastore
|
||||
|
||||
// Only for Debugging/Testing: How many free Notes are available?
|
||||
int spendableNotesCount = NoteCountDataStore::getInstance()->getSpendableNotesCount();
|
||||
QString addressWithMaxValue = NoteCountDataStore::getInstance()->getAddressWithMaxValue();
|
||||
|
||||
qDebug() << "Available notes over fee:" << spendableNotesCount;
|
||||
|
||||
// Clear NoteCountDataStore
|
||||
DataStore::getNoteCountDataStore()->clear();
|
||||
|
||||
const QString possibleCharacters("0123456789abcdef");
|
||||
int sizerandomString = 512;
|
||||
const int randomStringLength = sizerandomString;
|
||||
@@ -168,19 +186,36 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx)
|
||||
randomString.append(nextChar);
|
||||
}
|
||||
|
||||
dust.at(i)["memo"] = randomString.toStdString();
|
||||
dustTransactions.at(i)["memo"] = randomString.toStdString();
|
||||
|
||||
}
|
||||
CAmount balanceAvailable = getModel()->getBalVerified();
|
||||
|
||||
for(auto &it: dust)
|
||||
{
|
||||
it["amount"] = 0;
|
||||
}
|
||||
// Create more Notes if spendableNotesCount < 30 and enough funds are available
|
||||
if (spendableNotesCount < 30 && balanceAvailable.toDecimalString().toDouble() > (dustTransactions.size() * 0.0001)) {
|
||||
// Create extra transaction
|
||||
for (size_t i = 0; i < dustTransactions.size(); ++i) {
|
||||
// Generate random memo
|
||||
QString randomMemo;
|
||||
for (int j = 0; j < randomStringLength; ++j) {
|
||||
int index = QRandomGenerator::system()->bounded(0, possibleCharacters.length());
|
||||
randomMemo.append(possibleCharacters.at(index));
|
||||
}
|
||||
|
||||
dustTransactions.at(i)["address"] = addressWithMaxValue.toStdString();
|
||||
dustTransactions.at(i)["amount"] = 10000;
|
||||
dustTransactions.at(i)["memo"] = randomMemo.toStdString();
|
||||
}
|
||||
} else {
|
||||
// Set amount for real Sietch transaction to 0
|
||||
for (auto &it : dustTransactions) {
|
||||
it["amount"] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// For each addr/amt/memo, construct the JSON and also build the confirm dialog box
|
||||
for (int i=0; i < tx.toAddrs.size(); i++)
|
||||
{
|
||||
auto toAddr = tx.toAddrs[i];
|
||||
for (const auto& toAddr : tx.toAddrs) {
|
||||
json rec = json::object();
|
||||
rec["address"] = toAddr.addr.toStdString();
|
||||
rec["amount"] = toAddr.amount.toqint64();
|
||||
if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.trimmed().isEmpty())
|
||||
@@ -189,59 +224,21 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx)
|
||||
allRecepients.push_back(rec);
|
||||
}
|
||||
|
||||
int decider = rand() % 100 + 1 ; ; // random int between 1 and 100
|
||||
int decider = rand() % 100 + 1;
|
||||
|
||||
int dustCount = (decider % 4 == 3) ? 5 : 6;
|
||||
if (tx.toAddrs.size() < 2) {
|
||||
|
||||
if(decider % 4 == 3) {
|
||||
allRecepients.insert(std::begin(allRecepients), {
|
||||
dust.at(0),
|
||||
dust.at(1),
|
||||
dust.at(2),
|
||||
dust.at(3),
|
||||
dust.at(4),
|
||||
dust.at(5)
|
||||
}) ;
|
||||
|
||||
} else {
|
||||
allRecepients.insert(std::begin(allRecepients), {
|
||||
dust.at(0),
|
||||
dust.at(1),
|
||||
dust.at(2),
|
||||
dust.at(3),
|
||||
dust.at(4),
|
||||
dust.at(5),
|
||||
dust.at(6)
|
||||
}) ;
|
||||
}
|
||||
} else {
|
||||
|
||||
if(decider % 4 == 3) {
|
||||
allRecepients.insert(std::begin(allRecepients), {
|
||||
dust.at(0),
|
||||
dust.at(1),
|
||||
dust.at(2),
|
||||
dust.at(3),
|
||||
dust.at(4)
|
||||
}) ;
|
||||
} else {
|
||||
allRecepients.insert(std::begin(allRecepients), {
|
||||
dust.at(0),
|
||||
dust.at(1),
|
||||
dust.at(2),
|
||||
dust.at(3),
|
||||
dust.at(4),
|
||||
dust.at(5)
|
||||
}) ;
|
||||
}
|
||||
dustCount++;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < dustCount; ++i) {
|
||||
allRecepients.insert(allRecepients.begin(), dustTransactions.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
void Controller::noConnection()
|
||||
{
|
||||
qDebug()<< __func__;
|
||||
//qDebug()<< __func__;
|
||||
QIcon i = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
|
||||
main->statusIcon->setPixmap(i.pixmap(16, 16));
|
||||
main->statusIcon->setToolTip("");
|
||||
@@ -274,7 +271,7 @@ void Controller::noConnection()
|
||||
/// This will refresh all the balance data from hushd
|
||||
void Controller::refresh(bool force)
|
||||
{
|
||||
qDebug()<< __func__;
|
||||
//qDebug()<< __func__;
|
||||
if (!zrpc->haveConnection())
|
||||
return;
|
||||
|
||||
@@ -301,7 +298,7 @@ void Controller::processInfo(const json& info)
|
||||
|
||||
void Controller::getInfoThenRefresh(bool force)
|
||||
{
|
||||
qDebug()<< __func__;
|
||||
//qDebug()<< __func__;
|
||||
if (!zrpc->haveConnection())
|
||||
return noConnection();
|
||||
|
||||
@@ -635,7 +632,7 @@ void Controller::setLag(int lag)
|
||||
|
||||
void Controller::refreshAddresses()
|
||||
{
|
||||
qDebug()<< __func__;
|
||||
//qDebug()<< __func__;
|
||||
if (!zrpc->haveConnection())
|
||||
return noConnection();
|
||||
|
||||
@@ -680,7 +677,7 @@ void Controller::updateUI(bool anyUnconfirmed)
|
||||
|
||||
void Controller::supplyUpdate() {
|
||||
|
||||
qDebug()<< __func__ << ": updating supply";
|
||||
// qDebug()<< __func__ << ": updating supply";
|
||||
|
||||
// Get the total supply and render it with thousand decimal
|
||||
zrpc->fetchSupply([=] (const json& reply) {
|
||||
@@ -701,7 +698,7 @@ void Controller::supplyUpdate() {
|
||||
ui->supply_zaddr->setText("HUSH " +(QLocale(QLocale::English).toString(zfunds)));
|
||||
ui->supply_total->setText("HUSH " +(QLocale(QLocale::English).toString(total)));
|
||||
}
|
||||
qDebug() << __func__ << ": supply=" << supply;
|
||||
//qDebug() << __func__ << ": supply=" << supply;
|
||||
});
|
||||
|
||||
}
|
||||
@@ -890,7 +887,7 @@ void Controller::updateUIBalances()
|
||||
|
||||
void Controller::refreshBalances()
|
||||
{
|
||||
qDebug()<< __func__;
|
||||
//qDebug()<< __func__;
|
||||
if (!zrpc->haveConnection())
|
||||
return noConnection();
|
||||
|
||||
@@ -963,11 +960,11 @@ void printJsonValue(QTextStream& out, const nlohmann::json& j, int depth = 0) {
|
||||
|
||||
|
||||
void Controller::refreshTransactions() {
|
||||
qDebug()<< __func__;
|
||||
//qDebug()<< __func__;
|
||||
if (!zrpc->haveConnection())
|
||||
return noConnection();
|
||||
|
||||
qDebug() << __func__ << ": fetchTransactions";
|
||||
// qDebug() << __func__ << ": fetchTransactions";
|
||||
zrpc->fetchTransactions([=] (json reply) {
|
||||
QList<TransactionItem> txdata;
|
||||
|
||||
@@ -1079,7 +1076,7 @@ void Controller::refreshTransactions() {
|
||||
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0)
|
||||
{
|
||||
main->logger->write("Keypair outgoing error");
|
||||
qDebug() << "refreshTransactions: crypto_kx_seed_keypair error";
|
||||
// qDebug() << "refreshTransactions: crypto_kx_seed_keypair error";
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1090,7 +1087,7 @@ void Controller::refreshTransactions() {
|
||||
if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0)
|
||||
{
|
||||
main->logger->write("Suspicious client public outgoing key, bail out ");
|
||||
qDebug() << "refreshTransactions: Suspicious client public outgoing key, aborting!";
|
||||
// qDebug() << "refreshTransactions: Suspicious client public outgoing key, aborting!";
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1119,13 +1116,13 @@ void Controller::refreshTransactions() {
|
||||
|
||||
if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, server_tx) != 0) {
|
||||
/* Invalid header, no need to go any further */
|
||||
qDebug() << "refreshTransactions: crypto_secretstream_xchacha20poly1305_init_pull error! Invalid header";
|
||||
// qDebug() << "refreshTransactions: crypto_secretstream_xchacha20poly1305_init_pull error! Invalid header";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (crypto_secretstream_xchacha20poly1305_pull(&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
|
||||
/* Invalid/incomplete/corrupted ciphertext - abort */
|
||||
qDebug() << "refreshTransactions: crypto_secretstream_xchacha20poly1305_pull error! Invalid ciphertext";
|
||||
// qDebug() << "refreshTransactions: crypto_secretstream_xchacha20poly1305_pull error! Invalid ciphertext";
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1155,7 +1152,7 @@ void Controller::refreshTransactions() {
|
||||
false
|
||||
);
|
||||
|
||||
qDebug() << "refreshTransactions: adding chatItem with memodecrypt=" << memodecrypt;
|
||||
// qDebug() << "refreshTransactions: adding chatItem with memodecrypt=" << memodecrypt;
|
||||
DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item);
|
||||
// updateUIBalances();
|
||||
}
|
||||
@@ -1269,8 +1266,8 @@ void Controller::refreshTransactions() {
|
||||
|
||||
int position = it["position"].get<json::number_integer_t>();
|
||||
int ciphercheck = memo.length() - crypto_secretstream_xchacha20poly1305_ABYTES;
|
||||
qDebug() << __func__ << ": position=" << position << " headerbytes=" << headerbytes
|
||||
<< " ciphercheck=" << ciphercheck << " for memo=" << memo;
|
||||
// qDebug() << __func__ << ": position=" << position << " headerbytes=" << headerbytes
|
||||
// << " ciphercheck=" << ciphercheck << " for memo=" << memo;
|
||||
|
||||
if ((memo.startsWith("{") == false) && (headerbytes > 0) && (ciphercheck > 0))
|
||||
{
|
||||
@@ -1301,7 +1298,7 @@ void Controller::refreshTransactions() {
|
||||
if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0)
|
||||
{
|
||||
main->logger->write("Suspicious outgoing key pair, bail out ");
|
||||
qDebug() << "refreshTransactions: (incoming) crypto_kx_seed_keypair error!";
|
||||
// qDebug() << "refreshTransactions: (incoming) crypto_kx_seed_keypair error!";
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1312,7 +1309,7 @@ void Controller::refreshTransactions() {
|
||||
if (crypto_kx_client_session_keys(client_rx, client_tx, pk, sk, pubkeyBob) != 0)
|
||||
{
|
||||
main->logger->write("Suspicious client public incoming key, bail out ");
|
||||
qDebug() << "refreshTransactions: (incoming) crypto_kx_client_session_keys error!";
|
||||
// qDebug() << "refreshTransactions: (incoming) crypto_kx_client_session_keys error!";
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1340,13 +1337,13 @@ void Controller::refreshTransactions() {
|
||||
// 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 ");
|
||||
qDebug() <<"refreshTransactions: (incoming) crypto_secretstream_xchacha20poly1305_init_pull error! memo=" << memo;
|
||||
//qDebug() <<"refreshTransactions: (incoming) crypto_secretstream_xchacha20poly1305_init_pull error! memo=" << memo;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (crypto_secretstream_xchacha20poly1305_pull(&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) {
|
||||
main->logger->write("Invalid/incomplete/corrupted ciphertext - abort");
|
||||
qDebug() << "refreshTransactions: (incoming) crypto_secretstream_xchacha20poly1305_pull error! memo=" << memo;
|
||||
// qDebug() << "refreshTransactions: (incoming) crypto_secretstream_xchacha20poly1305_pull error! memo=" << memo;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1374,11 +1371,11 @@ void Controller::refreshTransactions() {
|
||||
);
|
||||
|
||||
auto iid = ChatIDGenerator::getInstance()->generateID(item);
|
||||
qDebug() << "refreshTransactions: adding chatItem with item id=" << iid << " memodecrypt=" << memodecrypt;
|
||||
// qDebug() << "refreshTransactions: adding chatItem with item id=" << iid << " memodecrypt=" << memodecrypt;
|
||||
DataStore::getChatDataStore()->setData(iid, item);
|
||||
|
||||
} else {
|
||||
qDebug() << __func__ << ": ignoring txid="<< txid;
|
||||
// qDebug() << __func__ << ": ignoring txid="<< txid;
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -1398,7 +1395,7 @@ void Controller::refreshTransactions() {
|
||||
isContact
|
||||
);
|
||||
auto iid = ChatIDGenerator::getInstance()->generateID(item);
|
||||
qDebug() << "refreshTransactions: adding chatItem for initial CR with item id="<< iid << " memo='" << memo << "'";
|
||||
// qDebug() << "refreshTransactions: adding chatItem for initial CR with item id="<< iid << " memo='" << memo << "'";
|
||||
DataStore::getChatDataStore()->setData(iid, item);
|
||||
}
|
||||
}
|
||||
@@ -1425,7 +1422,7 @@ void Controller::refreshTransactions() {
|
||||
|
||||
// Update model data, which updates the table view
|
||||
transactionsTableModel->replaceData(txdata);
|
||||
qDebug() << __func__ << ": calling renderChatBox";
|
||||
// qDebug() << __func__ << ": calling renderChatBox";
|
||||
chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat);
|
||||
ui->listChat->verticalScrollBar()->setValue(ui->listChat->verticalScrollBar()->maximum());
|
||||
|
||||
@@ -1435,7 +1432,7 @@ void Controller::refreshTransactions() {
|
||||
|
||||
void Controller::refreshChat(QListView *listWidget, QLabel *label)
|
||||
{
|
||||
qDebug() << __func__ << ": calling renderChatBox";
|
||||
// qDebug() << __func__ << ": calling renderChatBox";
|
||||
chat->renderChatBox(ui, listWidget, label);
|
||||
ui->listChat->verticalScrollBar()->setValue(ui->listChat->verticalScrollBar()->maximum());
|
||||
|
||||
@@ -1528,12 +1525,14 @@ void Controller::executeStandardUITransaction(Tx tx)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Execute a transaction!
|
||||
void Controller::executeTransaction(Tx tx,
|
||||
const std::function<void(QString txid)> submitted,
|
||||
const std::function<void(QString txid, QString errStr)> error)
|
||||
const std::function<void(QString txid, QString errStr)> error)
|
||||
{
|
||||
// Refresh the available unspent notes
|
||||
fetchAndProcessUnspentNotes();
|
||||
|
||||
unlockIfEncrypted([=] () {
|
||||
// First, create the json params
|
||||
json params = json::array();
|
||||
@@ -1559,10 +1558,9 @@ void Controller::executeTransaction(Tx tx,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Controller::checkForUpdate(bool silent)
|
||||
{
|
||||
qDebug()<< __func__;
|
||||
// qDebug()<< __func__;
|
||||
// No checking for updates, needs testing with Gitea
|
||||
return;
|
||||
if (!zrpc->haveConnection())
|
||||
@@ -1653,7 +1651,7 @@ void Controller::checkForUpdate(bool silent)
|
||||
// Get the hush->USD price from coinmarketcap using their API
|
||||
void Controller::refreshHUSHPrice()
|
||||
{
|
||||
qDebug()<< __func__;
|
||||
// qDebug()<< __func__;
|
||||
if (!zrpc->haveConnection())
|
||||
return;
|
||||
|
||||
@@ -2009,7 +2007,7 @@ void Controller::shutdownhushd()
|
||||
// Save the wallet and exit the lightclient library cleanly.
|
||||
if (!zrpc) {
|
||||
zrpc = new LiteInterface();
|
||||
qDebug() << __func__ << ": created new rpc connection zrpc=" << zrpc;
|
||||
// qDebug() << __func__ << ": created new rpc connection zrpc=" << zrpc;
|
||||
}
|
||||
|
||||
if (zrpc && zrpc->haveConnection())
|
||||
@@ -2076,3 +2074,42 @@ QString Controller::getDefaultTAddress()
|
||||
return QString();
|
||||
|
||||
}
|
||||
|
||||
void Controller::fetchAndProcessUnspentNotes() {
|
||||
zrpc->fetchUnspent([=] (json reply) {
|
||||
|
||||
if (reply.find("unspent_notes") == reply.end() || !reply["unspent_notes"].is_array()) {
|
||||
qDebug() << "Fehler: 'unspent_notes' fehlt oder ist kein Array";
|
||||
return;
|
||||
}
|
||||
|
||||
int spendableNotesCount = 0;
|
||||
std::map<std::string, int> addressValues;
|
||||
std::string addressWithMaxValue;
|
||||
int maxValue = 0;
|
||||
|
||||
for (const auto& note : reply["unspent_notes"]) {
|
||||
if (note.find("spendable") != note.end() && note.find("value") != note.end() &&
|
||||
note["spendable"].is_boolean() && note["value"].is_number_integer()) {
|
||||
|
||||
if (note["spendable"] && note["value"] >= 10000) {
|
||||
spendableNotesCount++;
|
||||
}
|
||||
|
||||
std::string address = note["address"];
|
||||
int value = note["value"];
|
||||
addressValues[address] += value;
|
||||
if (addressValues[address] > maxValue) {
|
||||
maxValue = addressValues[address];
|
||||
addressWithMaxValue = address;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NoteCountDataStore::getInstance()->setSpendableNotesCount(spendableNotesCount);
|
||||
|
||||
if (!addressWithMaxValue.empty()) {
|
||||
NoteCountDataStore::getInstance()->setAddressWithMaxValue(QString::fromStdString(addressWithMaxValue), maxValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -98,6 +98,8 @@ public:
|
||||
void noConnection();
|
||||
bool isEmbedded() { return ehushd != nullptr; }
|
||||
|
||||
void fetchAndProcessUnspentNotes();
|
||||
|
||||
void encryptWallet(QString password, const std::function<void(json)>& cb) {
|
||||
zrpc->encryptWallet(password, cb);
|
||||
}
|
||||
|
||||
@@ -725,42 +725,40 @@ 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
|
||||
{
|
||||
QString reply = "";
|
||||
try {
|
||||
char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(),
|
||||
seed.toStdString().c_str(), birthday, number);
|
||||
reply = litelib_process_response(resp);
|
||||
} catch (const std::exception& e) {
|
||||
qDebug() << __func__ << ": caught an exception, ignoring: " << e.what();
|
||||
}
|
||||
// 3. Initialize wallet with number
|
||||
QString number_str = form.number->text();
|
||||
qint64 number = number_str.toUInt();
|
||||
qDebug() << __func__ << ": Initializing wallet with number: " << number;
|
||||
|
||||
qDebug() << __func__ << ": reply=" << reply;
|
||||
QString reply = "";
|
||||
try {
|
||||
char *resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(),
|
||||
seed.toStdString().c_str(), birthday, number);
|
||||
|
||||
if (reply.toUpper().trimmed() != "OK") {
|
||||
qDebug() << "Lite server " << parent->server << " is down, getting a random one";
|
||||
parent->server = Settings::getRandomServer();
|
||||
qDebug() << __func__ << ": new server is " << parent->server;
|
||||
|
||||
// retry with the new server
|
||||
char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(),
|
||||
seed.toStdString().c_str(), birthday, number);
|
||||
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" + "server=" + parent->server + "\n" + reply,
|
||||
QMessageBox::Ok);
|
||||
return false;
|
||||
}
|
||||
if (resp != nullptr) {
|
||||
reply = litelib_process_response(resp);
|
||||
} else {
|
||||
qDebug() << __func__ << ": Null response from litelib_initialize_new_from_phrase";
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
qDebug() << __func__ << ": caught an exception, ignoring: " << e.what();
|
||||
}
|
||||
|
||||
qDebug() << __func__ << ": reply=" << reply;
|
||||
|
||||
if (reply.toUpper().trimmed() != "OK") {
|
||||
qDebug() << "Lite server " << parent->server << " is down, getting a random one";
|
||||
parent->server = Settings::getRandomServer();
|
||||
qDebug() << __func__ << ": new server is " << parent->server;
|
||||
|
||||
char *resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(),
|
||||
seed.toStdString().c_str(), birthday, number);
|
||||
if (resp != nullptr) {
|
||||
reply = litelib_process_response(resp);
|
||||
} else {
|
||||
qDebug() << __func__ << ": Null response on retry from litelib_initialize_new_from_phrase";
|
||||
}
|
||||
}
|
||||
// 4. Finally attempt to save the wallet
|
||||
{
|
||||
QString reply = "";
|
||||
|
||||
@@ -45,12 +45,15 @@ void LiteInterface::importTPrivKey(QString addr,const std::function<void(json)>&
|
||||
|
||||
|
||||
void LiteInterface::fetchUnspent(const std::function<void(json)>& cb) {
|
||||
if (conn == nullptr)
|
||||
if (conn == nullptr) {
|
||||
qDebug() << "fetchUnspent: conn ist nullptr, breche ab";
|
||||
return;
|
||||
}
|
||||
|
||||
conn->doRPCWithDefaultErrorHandling("notes", "", cb);
|
||||
}
|
||||
|
||||
|
||||
void LiteInterface::createNewZaddr(bool, const std::function<void(json)>& cb) {
|
||||
if (conn == nullptr)
|
||||
return;
|
||||
|
||||
@@ -61,7 +61,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
qDebug() << __func__ << endl;
|
||||
// qDebug() << __func__ << endl;
|
||||
|
||||
// Include css
|
||||
QString theme_name;
|
||||
@@ -427,7 +427,7 @@ void MainWindow::closeEvent(QCloseEvent* event) {
|
||||
|
||||
void MainWindow::closeEventpw(QCloseEvent* event) {
|
||||
// Let the RPC know to shut down any running service.
|
||||
qDebug() << __func__ << ": event=" << event << " this=" << this;
|
||||
// qDebug() << __func__ << ": event=" << event << " this=" << this;
|
||||
if (rpc) {
|
||||
rpc->shutdownhushd();
|
||||
} else {
|
||||
@@ -742,7 +742,7 @@ void MainWindow::setMoneyMemo(QString moneymemo)
|
||||
}
|
||||
|
||||
void MainWindow::setupStatusBar() {
|
||||
qDebug() << __func__ << endl;
|
||||
// qDebug() << __func__ << endl;
|
||||
// Status Bar
|
||||
loadingLabel = new QLabel();
|
||||
loadingMovie = new QMovie(":/icons/res/loading.gif");
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
// Copyright 2019-2024 The Hush developers
|
||||
// Released under the GPLv3
|
||||
#define APP_VERSION "2.0.1"
|
||||
|
||||
Reference in New Issue
Block a user