DragonX compatibility: crash fixes, reorg detection, server failover, sync perf

- Fix Rust FFI panics with catch_unwind wrappers and safe CString handling
- Handle poisoned mutex/RwLock from prior panics instead of crashing
- Add stuck sync detection (10s stall threshold) and chain reorg user prompt
- Add "Skip Verification" button to seed phrase wizard
- Update payment URIs from hush: to drgx:
- Update branding strings throughout UI
- Add all 6 lite servers (lite, lite1-5.dragonx.is) with random selection
- Add server connectivity probing to skip unreachable servers
- Reuse Tokio runtime across block fetch batches to reduce sync overhead
- Update Cargo.lock dependencies
This commit is contained in:
2026-03-21 03:43:23 -05:00
parent b0d7319182
commit cd5a9f3736
283 changed files with 124331 additions and 124080 deletions

View File

@@ -1,62 +1,62 @@
# Developer Docs for SDL
Random stuff that is useful for devs.
# Checking return values from litelib
There are 3 functions written in Rust that live in lib/src/lib.rs :
* `litelib_initialize_new`
* create a new client/connection and brand new wallet
* `litelib_initialize_new_from_phrase`
* create a new client/connection from a seedphrase (restoring from seedphrase)
* `litelib_initialize_existing`
* create a new client/connection with an already existing wallet
The Rust code calls it a "LightClient" while the C++ of SDL calls it a "Connection".
When `litelib_initialize_existing` or `litelib_initialize_new_from_phrase` return successfully, they return the string "OK" (which is not JSON).
When `litelib_initialize_new` returns successfully it returns JSON that looks like :
```
{"seed":"seed","birthday":birthday}
```
where "seed" is a 24 word seed and birthday is an integer block height.
So when calling these 3 functions, which looks almost the same in the calling code, the code which checks if they worked will be different, depending on what each returns on success.
When checking the return value of `litelib_initialize_existing` or `litelib_initialize_new_from_phrase` it should look like :
```
QString reply = "";
try {
char* resp = litelib_initialize_new_from_phrase(...);
reply = litelib_process_response(resp);
} catch {
...
}
if (reply.isEmpty())) {
// litelib_initialize_new_from_phrase failed
...
}
```
Yes, `isEmpty()` is not a very strict check, we could actually check for valid-looking JSON (starts with a { and ends with a }) as well as making sure the keys "seed" and "birthday" exist. Please implement this.
When checking the return value of `litelib_initialize_new` it should look like :
```
QString reply = "";
try {
char* resp = litelib_initialize_new(...);
reply = litelib_process_response(resp);
} catch {
...
}
if (reply.toUpper().trimmed() != "OK") {
// litelib_initialize_new failed
...
}
```
# Developer Docs for SDL
Random stuff that is useful for devs.
# Checking return values from litelib
There are 3 functions written in Rust that live in lib/src/lib.rs :
* `litelib_initialize_new`
* create a new client/connection and brand new wallet
* `litelib_initialize_new_from_phrase`
* create a new client/connection from a seedphrase (restoring from seedphrase)
* `litelib_initialize_existing`
* create a new client/connection with an already existing wallet
The Rust code calls it a "LightClient" while the C++ of SDL calls it a "Connection".
When `litelib_initialize_existing` or `litelib_initialize_new_from_phrase` return successfully, they return the string "OK" (which is not JSON).
When `litelib_initialize_new` returns successfully it returns JSON that looks like :
```
{"seed":"seed","birthday":birthday}
```
where "seed" is a 24 word seed and birthday is an integer block height.
So when calling these 3 functions, which looks almost the same in the calling code, the code which checks if they worked will be different, depending on what each returns on success.
When checking the return value of `litelib_initialize_existing` or `litelib_initialize_new_from_phrase` it should look like :
```
QString reply = "";
try {
char* resp = litelib_initialize_new_from_phrase(...);
reply = litelib_process_response(resp);
} catch {
...
}
if (reply.isEmpty())) {
// litelib_initialize_new_from_phrase failed
...
}
```
Yes, `isEmpty()` is not a very strict check, we could actually check for valid-looking JSON (starts with a { and ends with a }) as well as making sure the keys "seed" and "birthday" exist. Please implement this.
When checking the return value of `litelib_initialize_new` it should look like :
```
QString reply = "";
try {
char* resp = litelib_initialize_new(...);
reply = litelib_process_response(resp);
} catch {
...
}
if (reply.toUpper().trimmed() != "OK") {
// litelib_initialize_new failed
...
}
```

View File

@@ -1,67 +1,67 @@
# SilentDragonXLite Release Process
## High-Level Philosophy
Beware of making high-risk changes too close to a new release, because they will not get as much testing as they should. Don't merge large branches which haven't undergone lots of testing just before a release.
It is best to keep doc/relnotes/README.md up to date as changes and bug fixes are made. It's more work to summarize all changes and bugfixes just before the release.
## Check for changes on master that should be on dev
See https://git.hush.is/hush/hush3/src/branch/master/doc/release-process.md#check-for-changes-on-master-that-should-be-on-dev , there is no sense repeating the exact same thing here.
SD+SDL very often has merge conflicts in generated translation files, because QT embeds line numbers in XML.
Read how to deal with them efficiently here: https://git.hush.is/hush/SilentDragon/src/branch/dev/doc/release-process.md#dealing-with-merge-conflicts
## Git Issues
Look for Git issues that should be fixed in the next release: https://git.hush.is/hush/SilentDragonLite/issues Especially low-risk and simple things and like documentation changes and improvements to error messages. Take note that changing strings in the source code, such as adding a new string or changing an existing one, will affect translations.
## Translations
...
```
# update generated translation data
./build.sh linguist
git commit -am "update translations"
git push
```
## Adding Checkpoints
Adding checkpoints make SDL sync much faster, especially for brand new wallets. If there are no recent checkpoints,
when a user makes a new wallet, it will sync from a block far in the past, which wastes time, bandwidth and CPU resources. To add a checkpoint , they are added to the file `lib/src/lightclient/checkpoints.rs` in the silentdragonxlite-cli repo, and then the dependency on silentdragonxlite-cli is updated in this SDL repo. Here is an example commit that updates checkpoints:
https://git.hush.is/hush/silentdragonlite-cli/commit/ef477f152e1a8bb8a5f7883a99e2a74a6f9eeb0b
To actually generate the checkpoint data, use the `sdl_checkpoints.pl` script in the hush3 repo: https://git.hush.is/hush/hush3/src/branch/master/contrib/sdl_checkpoints.pl . It uses the `getblockmerkletree` RPC to get the merkle tree data for a block height. It prints the data out in the format that checkpoints.rs wants it in, you simply need to copy and paste the output into the checkpoints.rs file. Once the data is updated in silentdragonlite-cli checkpoints.rs file, the file `lib/Cargo.toml` must be updated in this repo, and point to the commit id of the updated data. Once you update the manually-edited `Cargo.toml` you must run `cargo update` to update the generated `Cargo.lock` file. See https://doc.rust-lang.org/cargo/commands/cargo-update.html for more info. Once both files are updates, commit and push.
---
To fix `error: failed to select a version for the requirement 'aes = "^0.3"'` add the following to `.cargo/config.toml`:
```
[source.crates-io]
replace-with = "vendored-sources"
[source.vendored-sources]
directory = "vendor"
```
To update the file run `cargo vendor` as was mentioned in https://git.hush.is/hush/SilentDragonLite/issues/91.
---
## Release process
* Write release notes
* Choose a release name
* Make Gitea release from master branch
* You can either manually make a git tag or let Gitea do it, which is easier
* Make binaries
* Windows exe
* Windows msi
* Linux
* Mac
* Debian package
# SilentDragonXLite Release Process
## High-Level Philosophy
Beware of making high-risk changes too close to a new release, because they will not get as much testing as they should. Don't merge large branches which haven't undergone lots of testing just before a release.
It is best to keep doc/relnotes/README.md up to date as changes and bug fixes are made. It's more work to summarize all changes and bugfixes just before the release.
## Check for changes on master that should be on dev
See https://git.hush.is/hush/hush3/src/branch/master/doc/release-process.md#check-for-changes-on-master-that-should-be-on-dev , there is no sense repeating the exact same thing here.
SD+SDL very often has merge conflicts in generated translation files, because QT embeds line numbers in XML.
Read how to deal with them efficiently here: https://git.hush.is/hush/SilentDragon/src/branch/dev/doc/release-process.md#dealing-with-merge-conflicts
## Git Issues
Look for Git issues that should be fixed in the next release: https://git.hush.is/hush/SilentDragonLite/issues Especially low-risk and simple things and like documentation changes and improvements to error messages. Take note that changing strings in the source code, such as adding a new string or changing an existing one, will affect translations.
## Translations
...
```
# update generated translation data
./build.sh linguist
git commit -am "update translations"
git push
```
## Adding Checkpoints
Adding checkpoints make SDL sync much faster, especially for brand new wallets. If there are no recent checkpoints,
when a user makes a new wallet, it will sync from a block far in the past, which wastes time, bandwidth and CPU resources. To add a checkpoint , they are added to the file `lib/src/lightclient/checkpoints.rs` in the silentdragonxlite-cli repo, and then the dependency on silentdragonxlite-cli is updated in this SDL repo. Here is an example commit that updates checkpoints:
https://git.hush.is/hush/silentdragonlite-cli/commit/ef477f152e1a8bb8a5f7883a99e2a74a6f9eeb0b
To actually generate the checkpoint data, use the `sdl_checkpoints.pl` script in the hush3 repo: https://git.hush.is/hush/hush3/src/branch/master/contrib/sdl_checkpoints.pl . It uses the `getblockmerkletree` RPC to get the merkle tree data for a block height. It prints the data out in the format that checkpoints.rs wants it in, you simply need to copy and paste the output into the checkpoints.rs file. Once the data is updated in silentdragonlite-cli checkpoints.rs file, the file `lib/Cargo.toml` must be updated in this repo, and point to the commit id of the updated data. Once you update the manually-edited `Cargo.toml` you must run `cargo update` to update the generated `Cargo.lock` file. See https://doc.rust-lang.org/cargo/commands/cargo-update.html for more info. Once both files are updates, commit and push.
---
To fix `error: failed to select a version for the requirement 'aes = "^0.3"'` add the following to `.cargo/config.toml`:
```
[source.crates-io]
replace-with = "vendored-sources"
[source.vendored-sources]
directory = "vendor"
```
To update the file run `cargo vendor` as was mentioned in https://git.hush.is/hush/SilentDragonLite/issues/91.
---
## Release process
* Write release notes
* Choose a release name
* Make Gitea release from master branch
* You can either manually make a git tag or let Gitea do it, which is easier
* Make binaries
* Windows exe
* Windows msi
* Linux
* Mac
* Debian package

View File

@@ -1,80 +1,80 @@
## Crosscompile for Windows (only tested for Ubuntu 18.04) by DenioD
```
# build dependencies
sudo apt install -y clang g++ build-essential make mingw-w64 git pkg-config libc6-dev m4 g++-multilib autoconf libtool-bin ncurses-dev unzip python python-zmq zlib1g-dev wget curl bsdmainutils automake libgl1-mesa-dev libglu1-mesa-dev libfontconfig1-dev autopoint libssl-dev
# MXE dependencies
sudo apt install -y bash bison bzip2 flex gettext git gperf intltool libc6-dev-i386 libgdk-pixbuf2.0-dev libltdl-dev libtool-bin libxml-parser-perl make openssl p7zip-full patch perl pkg-config python ruby sed unzip wget xz-utils
```
## more dependencies
```
apt-get -y update && apt-get install -y \
curl libdbus-1-3 libexpat1 \
libgl1-mesa-dev libglu1-mesa-dev libfontconfig1-dev libssl-dev \
libfreetype6 libgl1-mesa-glx libglib2.0-0 \
libx11-6 libx11-xcb1 \
g++ build-essential cmake wget git clang++-6.0 \
software-properties-common \
autoconf automake autopoint bison flex gperf libtool libtool-bin intltool lzip python ruby unzip p7zip-full libgdk-pixbuf2.0-dev libltdl-dev
```
# Compile OpenSSL
```
# Download openssl 1.0.2 from https://openssl.org/source/
wget https://www.openssl.org/source/openssl-1.0.2t.tar.gz
tar zxvpf openssl-1.0.2t.tar.gz
cd openssl-1.0.2t
./config # linux-x86_64
make -j$(nproc)
```
## Static build of Qt5
# Download Qt5 sources
```
mkdir -p ~/Qt/5.11.2 && cd ~/Qt/5.11.2
wget https://download.qt.io/archive/qt/5.11/5.11.2/single/qt-everywhere-src-5.11.2.tar.xz
tar xvpf qt-everywhere-src-5.11.2.tar.xz && cd qt-everywhere-src-5.11.2
```
# Configure and build Qt5 statically.
```
OPENSSL_LIBS='-L/PATH/TO/openssl-1.0.2q -lssl -lcrypto' ./configure -static -prefix ~/Qt/5.11.2/static -skip qtlocation -skip qtmacextras -skip qtpurchasing -skip qtscript -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtdatavis3d -skip qtdoc -skip qtcharts -skip qtdeclarative -skip qt3d -skip qtwebengine -skip qtandroidextras -skip qtwebview -skip qtgamepad -skip qtquickcontrols -skip qtquickcontrols2 -skip qtremoteobjects -skip qtwebview -skip qtwebchannel -skip qtwebglplugin -nomake examples -nomake tests -qt-zlib -qt-libpng -qt-xcb -qt-xkbcommon -feature-fontconfig -no-feature-getentropy -release -openssl-linked -opensource
make -j$(nproc)
make -j$(nproc) install
```
# Build MXE (Cross-compiled Qt5 for Windows in Linux)
```
mkdir ~/git && cd ~/git
git clone https://github.com/mxe/mxe.git
cd mxe
make -j$(nproc) MXE_TARGETS=x86_64-w64-mingw32.static qtbase
```
# Build SilentDragonLite .exe
```
cd SilentDragonLite
curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.38.0 -y
echo 'source $HOME/.cargo/env' >> $HOME/.bashrc
~/.cargo/bin/rustup target add x86_64-pc-windows-gnu
echo "[target.x86_64-pc-windows-gnu]" >> ~/.cargo/config
echo "linker = 'x86_64-w64-mingw32.static-gcc'" >> ~/.cargo/config
./win-static-build.sh
```
# Adding a new SDL lite server backend to the code
* Add the new server name to the array in getRandomServer() in settings.cpp
* Add the new server to dropdown in mainwindow.cpp
TODO: Make both of these places use a single list of servers.
## Crosscompile for Windows (only tested for Ubuntu 18.04) by DenioD
```
# build dependencies
sudo apt install -y clang g++ build-essential make mingw-w64 git pkg-config libc6-dev m4 g++-multilib autoconf libtool-bin ncurses-dev unzip python python-zmq zlib1g-dev wget curl bsdmainutils automake libgl1-mesa-dev libglu1-mesa-dev libfontconfig1-dev autopoint libssl-dev
# MXE dependencies
sudo apt install -y bash bison bzip2 flex gettext git gperf intltool libc6-dev-i386 libgdk-pixbuf2.0-dev libltdl-dev libtool-bin libxml-parser-perl make openssl p7zip-full patch perl pkg-config python ruby sed unzip wget xz-utils
```
## more dependencies
```
apt-get -y update && apt-get install -y \
curl libdbus-1-3 libexpat1 \
libgl1-mesa-dev libglu1-mesa-dev libfontconfig1-dev libssl-dev \
libfreetype6 libgl1-mesa-glx libglib2.0-0 \
libx11-6 libx11-xcb1 \
g++ build-essential cmake wget git clang++-6.0 \
software-properties-common \
autoconf automake autopoint bison flex gperf libtool libtool-bin intltool lzip python ruby unzip p7zip-full libgdk-pixbuf2.0-dev libltdl-dev
```
# Compile OpenSSL
```
# Download openssl 1.0.2 from https://openssl.org/source/
wget https://www.openssl.org/source/openssl-1.0.2t.tar.gz
tar zxvpf openssl-1.0.2t.tar.gz
cd openssl-1.0.2t
./config # linux-x86_64
make -j$(nproc)
```
## Static build of Qt5
# Download Qt5 sources
```
mkdir -p ~/Qt/5.11.2 && cd ~/Qt/5.11.2
wget https://download.qt.io/archive/qt/5.11/5.11.2/single/qt-everywhere-src-5.11.2.tar.xz
tar xvpf qt-everywhere-src-5.11.2.tar.xz && cd qt-everywhere-src-5.11.2
```
# Configure and build Qt5 statically.
```
OPENSSL_LIBS='-L/PATH/TO/openssl-1.0.2q -lssl -lcrypto' ./configure -static -prefix ~/Qt/5.11.2/static -skip qtlocation -skip qtmacextras -skip qtpurchasing -skip qtscript -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qtdatavis3d -skip qtdoc -skip qtcharts -skip qtdeclarative -skip qt3d -skip qtwebengine -skip qtandroidextras -skip qtwebview -skip qtgamepad -skip qtquickcontrols -skip qtquickcontrols2 -skip qtremoteobjects -skip qtwebview -skip qtwebchannel -skip qtwebglplugin -nomake examples -nomake tests -qt-zlib -qt-libpng -qt-xcb -qt-xkbcommon -feature-fontconfig -no-feature-getentropy -release -openssl-linked -opensource
make -j$(nproc)
make -j$(nproc) install
```
# Build MXE (Cross-compiled Qt5 for Windows in Linux)
```
mkdir ~/git && cd ~/git
git clone https://github.com/mxe/mxe.git
cd mxe
make -j$(nproc) MXE_TARGETS=x86_64-w64-mingw32.static qtbase
```
# Build SilentDragonLite .exe
```
cd SilentDragonLite
curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.38.0 -y
echo 'source $HOME/.cargo/env' >> $HOME/.bashrc
~/.cargo/bin/rustup target add x86_64-pc-windows-gnu
echo "[target.x86_64-pc-windows-gnu]" >> ~/.cargo/config
echo "linker = 'x86_64-w64-mingw32.static-gcc'" >> ~/.cargo/config
./win-static-build.sh
```
# Adding a new SDL lite server backend to the code
* Add the new server name to the array in getRandomServer() in settings.cpp
* Add the new server to dropdown in mainwindow.cpp
TODO: Make both of these places use a single list of servers.