diff --git a/lib/Cargo.lock b/lib/Cargo.lock index 1bd2058..26c09ac 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -1051,7 +1051,7 @@ version = "0.1.0" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=4d9c09433007e71e259b10f15c28ba1c6ac3efae)", + "silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=11d5d15e8b03c0a5b6eae1af00ac17fb7660a004)", ] [[package]] @@ -1467,7 +1467,7 @@ dependencies = [ [[package]] name = "silentdragonlitelib" version = "0.1.0" -source = "git+https://github.com/DenioD/silentdragonlite-cli?rev=4d9c09433007e71e259b10f15c28ba1c6ac3efae#4d9c09433007e71e259b10f15c28ba1c6ac3efae" +source = "git+https://github.com/DenioD/silentdragonlite-cli?rev=11d5d15e8b03c0a5b6eae1af00ac17fb7660a004#11d5d15e8b03c0a5b6eae1af00ac17fb7660a004" dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bellman 0.1.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)", @@ -2481,7 +2481,7 @@ dependencies = [ "checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=4d9c09433007e71e259b10f15c28ba1c6ac3efae)" = "" +"checksum silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=11d5d15e8b03c0a5b6eae1af00ac17fb7660a004)" = "" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585232e78a4fc18133eef9946d3080befdf68b906c51b621531c37e91787fa2b" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index fba4348..3ee29ec 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -11,4 +11,4 @@ crate-type = ["staticlib"] [dependencies] libc = "0.2.58" lazy_static = "1.4.0" -silentdragonlitelib = { git = "https://github.com/DenioD/silentdragonlite-cli", rev = "4d9c09433007e71e259b10f15c28ba1c6ac3efae" } +silentdragonlitelib = { git = "https://github.com/DenioD/silentdragonlite-cli", rev = "11d5d15e8b03c0a5b6eae1af00ac17fb7660a004" } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index a3df75c..d6f5a1f 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -4,7 +4,7 @@ extern crate lazy_static; use libc::{c_char}; use std::ffi::{CStr, CString}; -use std::sync::{Mutex}; +use std::sync::{Mutex, Arc}; use std::cell::RefCell; use silentdragonlitelib::{commands, lightclient::{LightClient, LightClientConfig}}; @@ -13,7 +13,7 @@ use silentdragonlitelib::{commands, lightclient::{LightClient, LightClientConfig // so we don't have to keep creating it. We need to store it here, in rust // because we can't return such a complex structure back to C++ lazy_static! { - static ref LIGHTCLIENT: Mutex>> = Mutex::new(RefCell::new(None)); + static ref LIGHTCLIENT: Mutex>>> = Mutex::new(RefCell::new(None)); } // Check if there is an existing wallet @@ -39,15 +39,14 @@ pub extern fn litelib_initialize_new(dangerous: bool, server: *const c_char) -> CStr::from_ptr(server).to_string_lossy().into_owned() }; - + 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), Err(e) => { let e_str = CString::new(format!("Error: {}", e)).unwrap(); return e_str.into_raw(); - } - + } }; let lightclient = match LightClient::new(&config, latest_block_height) { @@ -66,7 +65,7 @@ pub extern fn litelib_initialize_new(dangerous: bool, server: *const c_char) -> } }; - LIGHTCLIENT.lock().unwrap().replace(Some(lightclient)); + LIGHTCLIENT.lock().unwrap().replace(Some(Arc::new(lightclient))); // Return the wallet's seed let s_str = CString::new(seed).unwrap(); @@ -114,7 +113,7 @@ pub extern fn litelib_initialize_new_from_phrase(dangerous: bool, server: *const } }; - LIGHTCLIENT.lock().unwrap().replace(Some(lightclient)); + LIGHTCLIENT.lock().unwrap().replace(Some(Arc::new(lightclient))); let c_str = CString::new("OK").unwrap(); return c_str.into_raw(); @@ -146,7 +145,7 @@ pub extern fn litelib_initialize_existing(dangerous: bool, server: *const c_char } }; - LIGHTCLIENT.lock().unwrap().replace(Some(lightclient)); + LIGHTCLIENT.lock().unwrap().replace(Some(Arc::new(lightclient))); let c_str = CString::new("OK").unwrap(); return c_str.into_raw(); @@ -168,16 +167,21 @@ pub extern fn litelib_execute(cmd: *const c_char, args: *const c_char) -> *mut c let resp: String; { - let lc = LIGHTCLIENT.lock().unwrap(); + let lightclient: Arc; + { + let lc = LIGHTCLIENT.lock().unwrap(); - if lc.borrow().is_none() { - let e_str = CString::new("Error: Light Client is not initialized").unwrap(); - return e_str.into_raw(); - } + if lc.borrow().is_none() { + let e_str = CString::new("Error: Light Client is not initialized").unwrap(); + return e_str.into_raw(); + } + + lightclient = lc.borrow().as_ref().unwrap().clone(); + }; let args = if arg_str.is_empty() { vec![] } else { vec![arg_str.as_ref()] }; - resp = commands::do_user_command(&cmd_str, &args, lc.borrow().as_ref().unwrap()).clone(); + resp = commands::do_user_command(&cmd_str, &args, lightclient.as_ref()).clone(); }; let c_str = CString::new(resp.as_bytes()).unwrap(); diff --git a/silentdragonlite b/silentdragonlite new file mode 100755 index 0000000..80f0fce Binary files /dev/null and b/silentdragonlite differ diff --git a/src/connection.cpp b/src/connection.cpp index 22ddc1a..01d7330 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -22,9 +22,12 @@ ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc) { connD->setupUi(d); QPixmap logo(":/img/res/logobig.gif"); connD->topIcon->setBasePixmap(logo.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + + isSyncing = new QAtomicInteger(); } -ConnectionLoader::~ConnectionLoader() { +ConnectionLoader::~ConnectionLoader() { + delete isSyncing; delete connD; delete d; } @@ -52,16 +55,55 @@ void ConnectionLoader::doAutoConnect() { } else { main->logger->write(QObject::tr("Create/restore wallet.")); litelib_initialize_existing(config->dangerous, config->server.toStdString().c_str()); + d->show(); } auto connection = makeConnection(config); // After the lib is initialized, try to do get info connection->doRPC("info", "", [=](auto reply) { - // If success, set the connection + // If success, set the connection main->logger->write("Connection is online."); - this->doRPCSetConnection(connection); - }, [=](auto err) {}); + + isSyncing = new QAtomicInteger(); + isSyncing->store(true); + + // Do a sync at startup + syncTimer = new QTimer(main); + connection->doRPCWithDefaultErrorHandling("sync", "", [=](auto) { + isSyncing->store(false); + + // Cancel the timer + syncTimer->deleteLater(); + + // When sync is done, set the connection + this->doRPCSetConnection(connection); + }); + + // 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()) { + // Get the sync status + 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(); + showInformation("Synced " + QString::number(synced) + " / " + QString::number(total)); + } + }, + [=](QString err) { + qDebug() << "Sync error" << err; + }); + } + }); + + syncTimer->setInterval(1* 1000); + syncTimer->start(); + + }, [=](QString err) { + showError(err); + }); } void ConnectionLoader::createOrRestore(bool dangerous, QString server) { @@ -75,6 +117,7 @@ void ConnectionLoader::createOrRestore(bool dangerous, QString server) { } void ConnectionLoader::doRPCSetConnection(Connection* conn) { + qDebug() << "Connectionloader finished, setting connection"; rpc->setConnection(conn); d->accept(); @@ -88,20 +131,9 @@ Connection* ConnectionLoader::makeConnection(std::shared_ptr c // Update the UI with the status void ConnectionLoader::showInformation(QString info, QString detail) { - static int rescanCount = 0; - if (detail.toLower().startsWith("rescan")) { - rescanCount++; - } - - if (rescanCount > 10) { - detail = detail + "\n" + QObject::tr("This may take several hours"); - } - + qDebug() << "Showing info " << info << ":" << detail; connD->status->setText(info); connD->statusDetail->setText(detail); - - if (rescanCount < 10) - main->logger->write(info + ":" + detail); } /** diff --git a/src/connection.h b/src/connection.h index 97c8562..043a858 100644 --- a/src/connection.h +++ b/src/connection.h @@ -40,11 +40,14 @@ private: void doRPCSetConnection(Connection* conn); - QDialog* d; - Ui_ConnectionDialog* connD; + QTimer* syncTimer = nullptr; + QAtomicInteger* isSyncing = nullptr; - MainWindow* main; - Controller* rpc; + QDialog* d = nullptr; + Ui_ConnectionDialog* connD = nullptr; + + MainWindow* main = nullptr; + Controller* rpc = nullptr; }; /** diff --git a/src/controller.cpp b/src/controller.cpp index 95918e4..0b360b6 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -161,21 +161,25 @@ void Controller::getInfoThenRefresh(bool force) { prevCallSucceeded = true; // Testnet? + QString chainName; if (!reply["chain_name"].is_null()) { - Settings::getInstance()->setTestnet(reply["chain_name"].get() == "test"); + chainName = QString::fromStdString(reply["chain_name"].get()); + Settings::getInstance()->setTestnet(chainName == "test"); }; // Recurring pamynets are testnet only if (!Settings::getInstance()->isTestnet()) main->disableRecurring(); - // Connected, so display checkmark. - QIcon i(":/icons/res/connected.gif"); - main->statusIcon->setPixmap(i.pixmap(16, 16)); - static int lastBlock = 0; int curBlock = reply["latest_block_height"].get(); model->setLatestBlock(curBlock); + + // Connected, so display checkmark. + QIcon i(":/icons/res/connected.gif"); + main->statusLabel->setText(chainName + "(" + QString::number(curBlock) + ")"); + main->statusIcon->setPixmap(i.pixmap(16, 16)); + //int version = reply["version"].get(); int version = 1; Settings::getInstance()->sethushdVersion(version); diff --git a/src/firsttimewizard.cpp b/src/firsttimewizard.cpp index 20bae10..438f737 100644 --- a/src/firsttimewizard.cpp +++ b/src/firsttimewizard.cpp @@ -127,7 +127,7 @@ RestoreSeedPage::RestoreSeedPage(FirstTimeWizard *parent) : QWizardPage(parent) bool RestoreSeedPage::validatePage() { // 1. Validate that we do have 24 words - QString seed = form.txtSeed->toPlainText().replace(QRegExp("[ \n\r]+"), " "); + QString seed = form.txtSeed->toPlainText().replace(QRegExp("[ \n\r\t]+"), " "); if (seed.trimmed().split(" ").length() != 24) { QMessageBox::warning(this, tr("Failed to restore wallet"), tr("SilentDragonLite needs 24 words to restore wallet"),