Compare commits

..

11 Commits

Author SHA1 Message Date
288b54be6c restore rescan height dialog, use safe clear+resync approach 2026-03-22 11:23:48 -05:00
221231b53b fix rescan crash: use clear+resync instead of reinitializing lightclient 2026-03-22 11:16:50 -05:00
b7a04bebc1 fix rescan crash: shutdown old lightclient before overwriting 2026-03-22 11:12:19 -05:00
f5d26dd34d fix wallet restore: pass overwrite=true to allow restoring over existing wallet 2026-03-22 11:08:05 -05:00
ff8368ca97 fix birthday parse: treat empty input as 0, update hashes 2026-03-22 10:59:30 -05:00
7ec272df90 v1.1.1: release build with tx display fix, birthday parse fix 2026-03-22 10:52:25 -05:00
e2071653b9 Rebuild with memo filter fix for change detection
The previous fix checked memo.to_utf8().is_none() but empty memos
(all-zero bytes) have first byte 0x00 < 0xF5, so to_utf8() returns
Some(Ok("")) not None. Change outputs were never filtered.
Now checks for empty string as well as None.
2026-03-22 10:36:09 -05:00
90383b0f43 v1.1.1: Bump version, fix CFLAGS in lib/Makefile, rebuild binaries
- Bump APP_VERSION from 1.1.0 to 1.1.1
- Fix CFLAGS in lib/Makefile: remove quoted empty string that broke
  blake3 cross-compilation
- Rebuild Linux and Windows binaries with IVK change detection fix
- Update SHA-256 hashes in release notes
2026-03-22 10:02:51 -05:00
5fe5447474 v1.1.1: Fix sent tx showing wrong addresses, fix CRLF line endings in build.sh
- Fix change output detection using IVK-based decryption instead of
  static address list, so sent transactions only show the actual
  recipient address
- Fix CRLF line endings in build.sh
- Add release notes for v1.1.1
- Update Linux binary
2026-03-22 09:27:56 -05:00
cc34cc3f21 Add clean shutdown, wallet safety, and UI contrast fixes
Shutdown:
- Call litelib_shutdown() to stop Rust background threads on exit
- Add 15-second timeout on wallet save dialog to prevent hang on close
- Add litelib_shutdown FFI declaration in header and controller

UI Contrast (dragonx theme):
- Fix disabled buttons: white text was invisible on white background
- Add QWizard, QMessageBox, QTextBrowser, QPlainTextEdit styling for dark theme
- Add QCheckBox, QRadioButton, QDialogButtonBox contrast rules
- Fix seed word verification buttons: dark themed with explicit text color
- Fix chat bubbles: replace light backgrounds with dark themed colors
- Fix Terms of Service link color: #0000ff -> #6699ff for visibility
- Remove duplicate conflicting QLabel#lblMessage CSS rule

Add v1.1.0 release notes with checksums
2026-03-21 05:39:19 -05:00
e601048fd8 bump version to v1.1.0 2026-03-21 04:42:20 -05:00
15 changed files with 316 additions and 244 deletions

55
RELEASE_NOTES_v1.1.0.md Normal file
View File

@@ -0,0 +1,55 @@
# SilentDragonXLite v1.1.0 Release Notes
## What's New
### DragonX Compatibility
- Full compatibility with the DragonX blockchain
- Updated payment URIs from `hush:` to `drgx:`
- Updated branding and UI strings throughout
### Crash Fixes
- Fixed Rust FFI panics with `catch_unwind` wrappers and safe CString construction
- Handle poisoned mutex/RwLock from prior panics instead of crashing
- Fixed empty block list panics in `clear_blocks` and `invalidate_block`
- Removed `throw;` in exception handler that caused undefined behavior
### Reorg Detection & Stuck Sync Recovery
- Detects stuck syncs (10-second stall threshold) and prompts the user to repair
- Chain reorganization detection with one-time user prompt to clear and re-sync
- Prevents duplicate reorg dialogs
### Server Failover
- All 6 lite servers available: lite, lite1-5.dragonx.is
- Random server selection with connectivity probing — dead servers are automatically skipped
- Server dropdown in settings for manual selection
### Faster Block Sync
- Reuses Tokio runtime across block fetch batches, eliminating per-batch runtime creation overhead
### Clean Shutdown
- Added 15-second timeout on wallet save during exit — the app will no longer hang on close
- Rust background threads (mempool monitor) are now cleanly stopped on exit via `litelib_shutdown()`
### Wallet Safety
- Atomic wallet saves: writes to a temp file, then renames over the original — a crash during save can no longer corrupt the wallet
- Automatic `.bak` backup created before each save
- On startup, if the wallet file is missing or corrupted, automatically recovers from the backup
### Seed Phrase
- Added "Skip Verification" button to seed phrase wizard for faster wallet setup
### UI Contrast Improvements
- Fixed disabled buttons being invisible (white text on white background)
- Fixed setup wizard, message boxes, and dialog contrast for the dark theme
- Chat bubbles now use dark themed backgrounds matching the overall UI
- Seed verification buttons styled with proper contrast
- Fixed hyperlink color in Terms of Service (blue on dark was unreadable)
---
## Downloads
| File | SHA-256 |
|---|---|
| `SilentDragonXLite` (Linux) | `f9d3e3a8cd916b2d83dda89bc181670ef2cdd8b9ae5a50ef3a1c0e76e74f04fc` |
| `SilentDragonXLite.exe` (Windows) | `5064082c1300c42bef5c0f767e39743b08c66641eb495e1d975cbfb163b76cb0` |

18
RELEASE_NOTES_v1.1.1.md Normal file
View File

@@ -0,0 +1,18 @@
# SilentDragonXLite v1.1.1 Release Notes
## What's New
### Transaction Display Fix
- **Fixed sent transactions showing wrong addresses** — Previously, sending to a single address would display multiple addresses in the transaction history (the recipient plus the wallet's own diversified change addresses). Change outputs are now correctly detected using Incoming Viewing Key (IVK) decryption instead of a static address list, so only the actual recipient address is shown.
### Wallet Birthday Fix
- **Fixed "Failed to parse wallet birthday" error** — Rescanning the wallet no longer fails due to trailing whitespace in the birthday height input.
---
## Downloads
| File | SHA-256 |
|---|---|
| `SilentDragonXLite` (Linux) | `ac44fbdfa343ffb550829827e3fbb95407e2ca3086d6bc34befdc7b5644763a7` |
| `SilentDragonXLite.exe` (Windows) | `093b6830f23b1f1d407c47f2df90a2c1465b2882a0c3b375237a5b731e36362c` |

Binary file not shown.

138
build.sh
View File

@@ -1,69 +1,69 @@
#!/usr/bin/env bash
# Copyright 2019-2024 The Hush Developers
# Released under the GPLv3
UNAME=$(uname)
# check if rustc and cargo are installed, otherwise exit with error
if ! command -v rustc &> /dev/null
then
echo "rustc could not be found. Please install it and try again."
exit 1
fi
if ! command -v cargo &> /dev/null
then
echo "cargo could not be found. Please install it and try again."
exit 1
fi
if ! command -v qmake &> /dev/null
then
echo "qmake could not be found. Please install QT and try again."
exit 1
fi
if ! command -v make &> /dev/null
then
echo "make could not be found. Please install it and try again."
exit 1
fi
VERSION=$(grep APP_VERSION src/version.h |cut -d\" -f2)
QTVERSION=$(qmake --version | tail -n 1 | cut -d' ' -f4)
QT_MAJOR_VERSION=$(echo $QTVERSION | cut -d. -f1)
QT_SUB_VERSION=$(echo $QTVERSION | cut -d. -f2)
if [ "$QT_MAJOR_VERSION" != "5" ]; then
echo "Your QT version $QTVERSION is not compatible, only QT 5.x is supported"
exit 1
fi
if [ "$QT_SUB_VERSION" -lt "12" ]; then
echo "Your QT version $QTVERSION is not compatible, at least QT 5.12.0 is required"
exit 1
fi
echo "Compiling SilentDragonXLite $VERSION on $UNAME with QT $QTVERSION and args=$@"
CONF=silentdragonx-lite.pro
set -e
qbuild () {
qmake $CONF CONFIG+=debug
#lupdate $CONF
#lrelease $CONF
# default to 2 jobs or use the -j value given as argument to this script
make -j2 "$@"
}
if [ "$1" == "clean" ]; then
make clean
elif [ "$1" == "linguist" ]; then
lupdate $CONF
lrelease $CONF
elif [ "$1" == "cleanbuild" ]; then
make clean
qbuild "$@"
else
qbuild "$@"
fi
#!/usr/bin/env bash
# Copyright 2019-2024 The Hush Developers
# Released under the GPLv3
UNAME=$(uname)
# check if rustc and cargo are installed, otherwise exit with error
if ! command -v rustc &> /dev/null
then
echo "rustc could not be found. Please install it and try again."
exit 1
fi
if ! command -v cargo &> /dev/null
then
echo "cargo could not be found. Please install it and try again."
exit 1
fi
if ! command -v qmake &> /dev/null
then
echo "qmake could not be found. Please install QT and try again."
exit 1
fi
if ! command -v make &> /dev/null
then
echo "make could not be found. Please install it and try again."
exit 1
fi
VERSION=$(grep APP_VERSION src/version.h |cut -d\" -f2)
QTVERSION=$(qmake --version | tail -n 1 | cut -d' ' -f4)
QT_MAJOR_VERSION=$(echo $QTVERSION | cut -d. -f1)
QT_SUB_VERSION=$(echo $QTVERSION | cut -d. -f2)
if [ "$QT_MAJOR_VERSION" != "5" ]; then
echo "Your QT version $QTVERSION is not compatible, only QT 5.x is supported"
exit 1
fi
if [ "$QT_SUB_VERSION" -lt "12" ]; then
echo "Your QT version $QTVERSION is not compatible, at least QT 5.12.0 is required"
exit 1
fi
echo "Compiling SilentDragonXLite $VERSION on $UNAME with QT $QTVERSION and args=$@"
CONF=silentdragonx-lite.pro
set -e
qbuild () {
qmake $CONF CONFIG+=release
#lupdate $CONF
#lrelease $CONF
# default to 2 jobs or use the -j value given as argument to this script
make -j2 "$@"
}
if [ "$1" == "clean" ]; then
make clean
elif [ "$1" == "linguist" ]; then
lupdate $CONF
lrelease $CONF
elif [ "$1" == "cleanbuild" ]; then
make clean
qbuild "$@"
else
qbuild "$@"
fi

View File

@@ -3,7 +3,7 @@ ifeq ($(shell uname),Darwin)
CFLAGS := "-mmacosx-version-min=10.11"
else
EXT := a
CFLAGS := ""
CFLAGS :=
endif
PWD := $(shell pwd)

View File

@@ -9,12 +9,14 @@ extern bool litelib_wallet_exists (const char* chain_name);
extern char * litelib_initialize_new (bool dangerous, const char* server);
extern char * litelib_initialize_new_from_phrase
(bool dangerous, const char* server, const char* seed,
unsigned long long birthday, unsigned long long number);
unsigned long long birthday, unsigned long long number,
bool overwrite);
extern char * litelib_initialize_existing (bool dangerous,const char* server);
extern char * litelib_execute (const char* s, const char* args);
extern void litelib_rust_free_string (char* s);
extern char * blake3_PW (char* pw);
extern bool litelib_check_server_online (const char* server);
extern void litelib_shutdown (void);
#ifdef __cplusplus
}

View File

@@ -140,6 +140,17 @@ pub extern "C" fn litelib_initialize_new_from_phrase(dangerous: bool, server: *c
//println!("Initializing with server: {}, seed: {}", server_str, seed_str);
// Shut down the existing client if one is running, to stop background threads
if overwrite {
let old_lc = match LIGHTCLIENT.lock() {
Ok(l) => l.borrow().clone(),
Err(poisoned) => poisoned.into_inner().borrow().clone(),
};
if let Some(lc) = old_lc {
lc.shutdown();
}
}
let server = LightClientConfig::get_server_or_default(Some(server_str));
let (config, _latest_block_height) = match LightClientConfig::create(server, dangerous) {
Ok((c, h)) => {
@@ -290,6 +301,20 @@ pub extern "C" fn litelib_check_server_online(server: *const c_char) -> bool {
}
}
/// Cleanly shut down the light client, stopping mempool monitor threads.
/// Must be called before exit to prevent hangs.
#[no_mangle]
pub extern "C" fn litelib_shutdown() {
let lc_option = match LIGHTCLIENT.lock() {
Ok(l) => l.borrow().clone(),
Err(poisoned) => poisoned.into_inner().borrow().clone(),
};
if let Some(lc) = lc_option {
lc.shutdown();
}
}
/**
* Callers that receive string return values from other functions should call this to return the string
* back to rust, so it can be freed. Failure to call this function will result in a memory leak

View File

@@ -158,10 +158,9 @@ QPushButton:selected {
background-color: rgba(216, 38, 82, 0.75);
}
QPushButton:disabled {
color: rgba(255, 255, 255, 0.15);
color: rgba(255, 255, 255, 0.35);
border: 1px solid rgba(216, 38, 82, 0.15);
background-color: rgba(255, 255, 255, 0.796);
opacity: 25%;
background-color: rgba(41, 21, 21, 0.5);
}
QComboBox{
@@ -284,11 +283,6 @@ QLabel#lblMessage {
border: 1px solid rgba(216, 38, 82, 0.5);
background-color: rgba(216, 38, 82, 0.05);
}
QLabel#lblMessage{
color: rgb(24, 21, 21);
border: 1px solid rgba(255, 255, 255, 0.5);
background-color: rgba(216, 38, 82, 0.05);
}
@@ -532,4 +526,71 @@ QDialog#requestDialog QPushButton {
}
QDialog#requestDialog QPushButton#addContact {
min-width: 150px;
}
/* ===== SETUP WIZARD & DIALOG CONTRAST FIXES ===== */
QWizard, QWizardPage {
color: white;
background-color: rgb(24, 21, 21);
}
QWizard QLabel, QWizardPage QLabel {
color: rgba(255, 255, 255, 0.85);
}
QWizard QPushButton, QWizardPage QPushButton {
color: rgba(255, 255, 255, 0.75);
border: 1px solid rgba(216, 38, 82, 0.5);
background-color: rgba(216, 38, 82, 0.15);
}
QWizard QPushButton:hover, QWizardPage QPushButton:hover {
color: white;
border: 1px solid rgba(216, 38, 82, 0.75);
background-color: rgba(216, 38, 82, 0.45);
}
QTextBrowser, QPlainTextEdit, QTextEdit {
color: white;
border: 1px solid rgba(216, 38, 82, 0.5);
background-color: rgba(41, 21, 21, 0.75);
}
QCheckBox {
color: rgba(255, 255, 255, 0.85);
}
QCheckBox::indicator {
border: 1px solid rgba(216, 38, 82, 0.75);
background-color: rgba(41, 21, 21, 0.5);
}
QCheckBox::indicator:checked {
background-color: rgba(216, 38, 82, 0.75);
}
QRadioButton {
color: rgba(255, 255, 255, 0.85);
}
QDialogButtonBox QPushButton {
color: rgba(255, 255, 255, 0.75);
border: 1px solid rgba(216, 38, 82, 0.5);
background-color: rgba(216, 38, 82, 0.15);
min-width: 80px;
padding: 6px 16px;
}
QDialogButtonBox QPushButton:hover {
color: white;
border: 1px solid rgba(216, 38, 82, 0.75);
background-color: rgba(216, 38, 82, 0.45);
}
QMessageBox {
color: white;
background-color: rgb(24, 21, 21);
}
QMessageBox QLabel {
color: white;
}

View File

@@ -15,14 +15,16 @@
</property>
<property name="styleSheet">
<string notr="true">QWidget{
background: whitesmoke;
border: 1px solid #afafaf;
background: rgba(216, 38, 82, 0.15);
border: 1px solid rgba(216, 38, 82, 0.4);
border-radius: 3px;
color: white;
}
QLabel
{
background: none;
border: none;
color: rgba(255, 255, 255, 0.9);
}</string>
</property>
<widget class="QLabel" name="lblMessage">

View File

@@ -15,14 +15,16 @@
</property>
<property name="styleSheet">
<string notr="true">QWidget{
background: #c8e1ff;
border: 1px solid #fefefe;
background: rgba(41, 21, 21, 0.75);
border: 1px solid rgba(216, 38, 82, 0.3);
border-radius: 3px;
color: white;
}
QLabel
{
background: none;
border: none;
color: rgba(255, 255, 255, 0.85);
}</string>
</property>
<widget class="QLabel" name="lblMessage">

View File

@@ -7,6 +7,7 @@
#include "settings.h"
#include "version.h"
#include "camount.h"
#include "../lib/silentdragonxlitelib.h"
#include "Model/ChatItem.h"
#include "DataStore/DataStore.h"
#include <future>
@@ -2019,6 +2020,9 @@ void Controller::refreshDRAGONXPrice()
void Controller::shutdownhushd()
{
// Signal Rust to stop background threads (mempool monitor, etc.)
litelib_shutdown();
// Save the wallet and exit the lightclient library cleanly.
if (!zrpc) {
zrpc = new LiteInterface();
@@ -2040,7 +2044,7 @@ void Controller::shutdownhushd()
connD.topIcon->setMovie(movie2);
movie2->start();
connD.status->setText(QObject::tr("Please wait for SilentDragonXLite to exit"));
connD.statusDetail->setText(QObject::tr("It may take several minutes"));
connD.statusDetail->setText(QObject::tr("Saving wallet..."));
} else {
QMovie *movie1 = new QMovie(":/img/res/silentdragonxlite-animated-startup-dark.gif");;
movie1->setScaledSize(size);
@@ -2048,7 +2052,7 @@ void Controller::shutdownhushd()
connD.topIcon->setMovie(movie1);
movie1->start();
connD.status->setText(QObject::tr("Please wait for SilentDragonXLite to exit"));
connD.statusDetail->setText(QObject::tr("It may take several minutes"));
connD.statusDetail->setText(QObject::tr("Saving wallet..."));
}
bool finished = false;
@@ -2059,6 +2063,15 @@ void Controller::shutdownhushd()
qDebug() << __func__ << ": saveWallet finished";
});
// Add a timeout so the dialog can't hang forever
QTimer::singleShot(15000, &d, [&]() {
if (!finished) {
qDebug() << __func__ << ": saveWallet timed out after 15 seconds, forcing exit";
finished = true;
d.accept();
}
});
if (!finished)
d.exec();
} else {

View File

@@ -412,7 +412,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word1, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word1 + " ");
verifyseed.word1->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word1->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word1->font();
button.setStrikeOut(true);
verifyseed.word1->setFont(button);
@@ -421,7 +421,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word2, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word2);
verifyseed.word2->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word2->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word2->font();
button.setStrikeOut(true);
verifyseed.word2->setFont(button);
@@ -430,7 +430,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word3, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word3 + " ");
verifyseed.word3->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word3->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word3->font();
button.setStrikeOut(true);
verifyseed.word3->setFont(button);
@@ -439,7 +439,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word4, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word4 + " ");
verifyseed.word4->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word4->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word4->font();
button.setStrikeOut(true);
verifyseed.word4->setFont(button);
@@ -448,7 +448,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word5, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word5 + " ");
verifyseed.word5->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word5->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word5->font();
button.setStrikeOut(true);
verifyseed.word5->setFont(button);
@@ -457,7 +457,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word6, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word6 + " ");
verifyseed.word6->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word6->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word6->font();
button.setStrikeOut(true);
verifyseed.word6->setFont(button);
@@ -466,7 +466,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word7, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word7 + " ");
verifyseed.word7->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word7->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word7->font();
button.setStrikeOut(true);
verifyseed.word7->setFont(button);
@@ -475,7 +475,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word8, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word8 + " ");
verifyseed.word8->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word8->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word8->font();
button.setStrikeOut(true);
verifyseed.word8->setFont(button);
@@ -484,7 +484,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word9, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word9 + " ");
verifyseed.word9->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word9->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word9->font();
button.setStrikeOut(true);
verifyseed.word9->setFont(button);
@@ -493,7 +493,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word10, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word10 + " ");
verifyseed.word10->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word10->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word10->font();
button.setStrikeOut(true);
verifyseed.word10->setFont(button);
@@ -502,7 +502,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word11, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word11 + " ");
verifyseed.word11->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word11->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word11->font();
button.setStrikeOut(true);
verifyseed.word11->setFont(button);
@@ -511,7 +511,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word12, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word12 + " ");
verifyseed.word12->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word12->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word12->font();
button.setStrikeOut(true);
verifyseed.word12->setFont(button);
@@ -520,7 +520,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word13, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word13 + " ");
verifyseed.word13->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word13->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word13->font();
button.setStrikeOut(true);
verifyseed.word13->setFont(button);
@@ -529,7 +529,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word14, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word14 + " ");
verifyseed.word14->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word14->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word14->font();
button.setStrikeOut(true);
verifyseed.word14->setFont(button);
@@ -538,7 +538,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word15, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word15 + " ");
verifyseed.word15->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word15->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word15->font();
button.setStrikeOut(true);
verifyseed.word15->setFont(button);
@@ -547,7 +547,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word16, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word16 + " ");
verifyseed.word16->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word16->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word16->font();
button.setStrikeOut(true);
verifyseed.word16->setFont(button);
@@ -556,7 +556,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word17, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word17 + " ");
verifyseed.word17->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word17->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word17->font();
button.setStrikeOut(true);
verifyseed.word17->setFont(button);
@@ -565,7 +565,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word18, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word18 + " ");
verifyseed.word18->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word18->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word18->font();
button.setStrikeOut(true);
verifyseed.word18->setFont(button);
@@ -574,7 +574,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word19, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word19 + " ");
verifyseed.word19->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word19->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word19->font();
button.setStrikeOut(true);
verifyseed.word19->setFont(button);
@@ -583,7 +583,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word20, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word20 + " ");
verifyseed.word20->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word20->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word20->font();
button.setStrikeOut(true);
verifyseed.word20->setFont(button);
@@ -592,7 +592,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word21, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word21 + " ");
verifyseed.word21->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word21->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word21->font();
button.setStrikeOut(true);
verifyseed.word21->setFont(button);
@@ -601,7 +601,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word22, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word22 + " ");
verifyseed.word22->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word22->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word22->font();
button.setStrikeOut(true);
verifyseed.word22->setFont(button);
@@ -610,7 +610,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word23, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word23 + " ");
verifyseed.word23->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word23->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word23->font();
button.setStrikeOut(true);
verifyseed.word23->setFont(button);
@@ -619,7 +619,7 @@ bool NewSeedPage::validatePage() {
QObject::connect(verifyseed.word24, &QPushButton::clicked, [&] () {
verifyseed.verify->insertPlainText(word24 + " ");
verifyseed.word24->setStyleSheet("background-color: rgb(182,182,182);");
verifyseed.word24->setStyleSheet("background-color: rgba(216, 38, 82, 0.3); color: rgba(255,255,255,0.5);");
QFont button = verifyseed.word24->font();
button.setStrikeOut(true);
verifyseed.word24->setFont(button);
@@ -760,7 +760,7 @@ bool RestoreSeedPage::validatePage() {
QString reply = "";
try {
char *resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(),
seed.toStdString().c_str(), birthday, number);
seed.toStdString().c_str(), birthday, number, true);
if (resp != nullptr) {
reply = litelib_process_response(resp);
@@ -779,7 +779,7 @@ if (reply.toUpper().trimmed() != "OK") {
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);
seed.toStdString().c_str(), birthday, number, true);
if (resp != nullptr) {
reply = litelib_process_response(resp);
} else {
@@ -805,7 +805,7 @@ if (reply.toUpper().trimmed() != "OK") {
// make a new connection to the new server
char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(),
seed.toStdString().c_str(), birthday, number);
seed.toStdString().c_str(), birthday, number, true);
reply = litelib_process_response(resp);
// retry with the new server

View File

@@ -160,143 +160,37 @@ MainWindow::MainWindow(QWidget *parent) :
// Rescan
QObject::connect(ui->actionRescan, &QAction::triggered, [=]() {
DEBUG("rescan action triggered");
Ui_Restore restoreSeed;
QDialog dialog(this);
restoreSeed.setupUi(&dialog);
Settings::saveRestore(&dialog);
rpc->fetchSeed([=](json reply) {
if (isJsonError(reply)) {
// Ask user for rescan height
bool ok;
QString heightStr = QInputDialog::getText(this, tr("Rescan Wallet"),
tr("Rescan from height (0 to rescan from the beginning):"),
QLineEdit::Normal, "0", &ok);
if (!ok) return;
QString height = heightStr.trimmed();
if (height.isEmpty()) height = "0";
// Validate it's a number
height.toULongLong(&ok);
if (!ok) {
QMessageBox::warning(this, tr("Invalid height"),
tr("Please enter a valid block height number."),
QMessageBox::Ok);
return;
}
restoreSeed.seed->setReadOnly(true);
restoreSeed.seed->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap);
QString seedJson = QString::fromStdString(reply["seed"].get<json::string_t>());
restoreSeed.seed->setPlainText(seedJson);
QString birthday = QString::number(reply["birthday"].get<json::number_unsigned_t>());
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("SilentDragonXLite 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<ConnectionConfig>(new ConnectionConfig());
config->server = Settings::getInstance()->getSettings().server;
// 3. Attempt to restore wallet with the seed phrase
{
QString reply = "";
try {
char* resp = litelib_initialize_new_from_phrase(config->dangerous, config->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();
}
if (reply.toUpper().trimmed() != "OK") {
qDebug() << "Lite server " << config->server << " is down, getting a random one";
config->server = Settings::getRandomServer();
qDebug() << __func__ << ": new server is " << config->server;
// retry with the new server
char* resp = litelib_initialize_new_from_phrase(config->dangerous,config->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=" + config->server + "\n" + reply,
QMessageBox::Ok);
return false;
}
}
// 4. Finally attempt to save the wallet
{
QString reply = "";
try {
char* resp = litelib_execute("save", "");
QString reply = litelib_process_response(resp);
} catch (const std::exception& e) {
qDebug() << __func__ << ": caught an exception, ignoring: " << e.what();
}
if (reply.isEmpty()) {
qDebug() << "Lite server " << config->server << " is down, getting a random one";
config->server = Settings::getRandomServer();
qDebug() << __func__ << ": new server is " << config->server;
// make a new connection to the new server
char* resp = litelib_initialize_new_from_phrase(config->dangerous,config->server.toStdString().c_str(),
seed.toStdString().c_str(), birthday, number);
reply = litelib_process_response(resp);
// retry with the new server
try {
resp = litelib_execute("save", "");
reply = litelib_process_response(resp);
} catch (const std::exception& e) {
qDebug() << __func__ << ": caught an exception with new server, something is fucky: " << e.what();
}
}
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" + "server=" + config->server + "\n" + reply,
QMessageBox::Ok);
} else {
qDebug() << __func__ << ": saved wallet correctly";
}
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) {
qDebug() << "Clearing wallet...";
// Save the wallet
// Clear wallet state from the specified height, then resync
rpc->getConnection()->doRPCWithDefaultErrorHandling("clear", height, [=] (auto) {
qDebug() << "Cleared wallet state to height" << height;
this->getRPC()->saveWallet([=] (auto) {
qDebug() << "Saving wallet...";
// Then reload the connection. The ConnectionLoader deletes itself.
auto cl = new ConnectionLoader(this, rpc);
cl->loadConnection();
qDebug() << "Saved cleared wallet, reloading connection to start rescan...";
auto cl = new ConnectionLoader(this, rpc);
cl->loadConnection();
});
});
}
});
dialog.exec();
}); // actionReason
}); // actionRescan
// Import Privkey
QObject::connect(ui->actionImport_Privatkey, &QAction::triggered, this, &MainWindow::importPrivKey);

View File

@@ -90,7 +90,7 @@
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;h1 align=&quot;center&quot; style=&quot; margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:xx-large; font-weight:600;&quot;&gt;DragonX + HushChat Terms of Service&lt;/span&gt;&lt;/h1&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;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 &lt;a href=&quot;https://en.wikipedia.org/wiki/Non-aggression_principle&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Non-Aggression Principle&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;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 &lt;a href=&quot;https://en.wikipedia.org/wiki/Non-aggression_principle&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#6699ff;&quot;&gt;Non-Aggression Principle&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;THE SERVICE IS PROVIDED “AS IS” AND The Hush Developers DO NOT MAKE ANY SPECIFIC COMMITMENTS OR WARRANTIES ABOUT THE SERVICE.&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;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.&lt;/p&gt;

View File

@@ -1 +1 @@
#define APP_VERSION "1.0.0"
#define APP_VERSION "1.1.1"