The lightwalletd server controls the compact ciphertext length, the block, prev-block and tx hash lengths, and (through the chain) the full txs' epks. Each of these could wedge or poison a sync: - try_sapling_compact_note_decryption asserts a 52-byte ciphertext. A shorter (or full 580-byte) one panicked a pool job in scan_output_internal while the original sender stayed alive, so the collector waited forever with sync_lock, txs.write() and a wallet read guard held. - scan_taddress_txids kept its own sender alive too: one panicking t-address job (scan_full_tx) left crx.iter().take(n) blocked forever. - CompactBlock::hash()/prev_hash() assert 32 bytes when no header is sent, and every vtx hash is copied into a [u8; 32], one of them under txs.write(): a 31-byte tx hash poisoned the wallet for good, and a bad hash in the block's txid list panicked after the witnesses had moved. - scan_full_tx and scan_full_mempool_tx unwrapped as_prime_order() on the epk. Consensus rejects only a small-order epk, so a mixed-order one can be mined: an own tx then failed every sync, and the mempool receiver thread died silently. Changes: - append_leaf(node: Node, ..) commits a leaf to the existing, block and new witnesses and the tree; the epk-error path, the new short-ciphertext path and the normal path all use it (a behaviour-neutral extraction). - A compact ciphertext under 52 bytes is skipped with its cmu still committed; a longer one is truncated to 52 bytes, which is exact (the compact plaintext is those bytes and the cmu re-check validates it). - Each decryption job catches a panic and sends exactly one message; drop(tx) after the dispatch, and the collector logs a vanished or panicked job and treats the output as not ours. - scan_taddress_txids runs through the private seam scan_taddress_txids_with(job): catch_unwind per job, drop(ctx), and a count check, so a dead job is an error, never a hang or a silent partial success. - scan_block_with_pool checks the block, prev-block and vtx hash lengths right after the parse and returns Err(-1), as for an unparsable block, before any change (Err(height) would refetch the same block forever under sync_lock). - scan_full_tx and scan_full_mempool_tx skip an output whose epk is not in the prime-order subgroup (one check per output, used by every decryption and the outgoing recovery). - The mempool receiver thread catches a panic of scan_full_mempool_tx. Flagged behaviour changes: - a compact ciphertext under 52 bytes is skipped (its cmu is still committed); one over 52 bytes is truncated; - pool-job panics are reported (logged; the output is treated as not ours, which a rescan repairs) instead of hanging the sync; - bad hash lengths return Err(-1) before any change; - outputs with a non-prime-order epk are skipped; - the mempool thread survives a bad tx. Wallet format v9 is unchanged; no ABI or symbol change. Honest data takes the same path as before (an old-vs-new run over generated honest chains is byte-identical). Tests (each on its own thread under a 15 s watchdog): 0/51/52/53/580-byte ciphertexts in one block on the inline and deferred witness paths (the 51-byte notes are skipped, the 53- and 580-byte notes are found, the tree and every witness match the reference); a 31-byte tx hash, an empty block hash, a 31-byte prev hash and a 33-byte foreign tx hash each return Err(-1) with the txs lock usable and last_scanned_height, trees and witnesses unchanged; a mixed-order epk in scan_full_tx and scan_full_mempool_tx does not panic and decrypts nothing while the real epk still decrypts; a t-address job panicking for 1 of 3 addresses is an Err. The oracle generator gains short (0..=51-byte) and full (580-byte) ciphertext outputs without an extra random draw, so each seed keeps its sequence of blocks, values and keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ObsidianDragon - DragonX Wallet
A lightweight, portable full-node cryptocurrency wallet for DragonX (DRGX), built with Dear ImGui.
Current pre-release: 1.2.0-rc1.
Features
- Full Node Support: Connects to dragonxd for complete blockchain verification
- Shielded Transactions: Full z-address support with encrypted memos
- Address Management: Labels, icons, favorites, hidden addresses, and address-to-address transfers
- Integrated Mining: Solo CPU mining plus pool mining through xmrig, with idle-mining controls
- Explorer Tools: Block/transaction lookup and bootstrap snapshot download
- Market Data: Real-time price charts from CoinGecko
- QR Codes: Generate and display QR codes for receiving addresses
- Multi-language: i18n support for English, German, Spanish, French, Japanese, Korean, Portuguese, Russian, and Chinese
- CJK Fonts: Bundled CJK subset font for translated interfaces
- Lightweight: ~5-10MB binary vs ~50MB+ for Qt version
- Fast Builds: Compiles in seconds, not minutes
Screenshots
Building
Quick Setup
The setup script detects your OS, installs all build dependencies, and validates your environment:
./setup.sh # Install core build deps (interactive)
./setup.sh --check # Just report what's missing
./setup.sh --all # Core + Windows/macOS cross-compile + Sapling params
./setup.sh --win # Also install mingw-w64 + libsodium-win
Manual Prerequisites
Click to expand manual install commands
Linux (Ubuntu/Debian):
sudo apt install build-essential cmake git pkg-config
sudo apt install libgl1-mesa-dev libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev
sudo apt install libsodium-dev libcurl4-openssl-dev
Linux (Arch):
sudo pacman -S base-devel cmake git pkg-config mesa libx11 libxcursor libxrandr libxinerama libxi libsodium curl
macOS:
xcode-select --install
brew install cmake
Windows:
- Visual Studio 2019+ with C++ workload
- CMake 3.20+
Binaries
Download linux and windows binaries of latest releases and place in binary directories:
DragonX daemon (https://git.dragonx.is/DragonX/dragonx):
- prebuilt-binaries/dragonxd-linux/
- prebuilt-binaries/dragonxd-win/
- prebuilt-binaries/dragonxd-mac/
DRG-XMRig fork (https://git.dragonx.is/DragonX/drg-xmrig):
- prebuilt-binaries/drg-xmrig/
Build Steps
### Clone repository (if not already)
git clone https://git.dragonx.is/dragonx/ObsidianDragon.git
cd ObsidianDragon/
Windows Build
./build.sh --win-release
Release Build
./build.sh --linux-release # Linux release + AppImage
./build.sh --win-release # Windows cross-compile
./build.sh --mac-release # macOS .app bundle + DMG
./build.sh --clean --linux-release # Clean + Release
Running
-
Start dragonxd (if not using embedded daemon):
dragonxd -daemon -
Run the wallet:
cd build/bin ./ObsidianDragon
The wallet will automatically connect to the daemon using credentials from ~/.hush/DRAGONX/DRAGONX.conf.
Using Custom Node Binaries
The wallet checks its own directory first when looking for DragonX node binaries. This means you can test new or different branch builds of hush-arrakis-chain/hushd without waiting for a new wallet release:
- Build or download the node binaries you want to test
- Place them in the same directory as the wallet executable (e.g.
build/bin/) - Launch the wallet — it will use the local binaries instead of the bundled ones
Search order:
- Wallet executable directory (highest priority)
- Embedded/extracted daemon (app data directory)
- System-wide locations (
/usr/local/bin,~/dragonx/src, etc.)
This is useful for testing new branches or hotfixes to the node software before they are bundled into a wallet release.
Configuration
Configuration is stored in ~/.hush/DRAGONX/DRAGONX.conf:
rpcuser=your_rpc_user
rpcpassword=your_rpc_password
rpcport=21769
Project Structure
ObsidianDragon/
├── src/
│ ├── main.cpp # Entry point, SDL/ImGui setup
│ ├── app.cpp/h # Main application class
│ ├── data/ # WalletState, address book, exchange info
│ ├── config/ # Settings persistence and committed/generated version.h
│ ├── ui/
│ │ ├── schema/ # TOML UI schema and skin manager
│ │ ├── material/ # Material components, typography, layout
│ │ ├── windows/ # Tabs and dialogs
│ │ └── pages/ # Multi-page screens such as Settings
│ ├── rpc/
│ │ ├── rpc_client.cpp # JSON-RPC client
│ │ └── connection.cpp # Daemon connection
│ ├── resources/ # Embedded resource extraction
│ ├── platform/ # Windows DX11/backdrop helpers
│ ├── util/
│ │ ├── i18n.cpp # Internationalization
│ │ └── ...
│ └── daemon/
│ └── embedded_daemon.cpp
├── res/
│ ├── fonts/ # Ubuntu, icon, and CJK fonts
│ └── lang/ # Translation files
├── libs/
│ └── qrcode/ # QR code generation
├── CMakeLists.txt
├── build.sh # Release/cross-platform build script
└── scripts/create-appimage.sh # AppImage packaging
Dependencies
Fetched or discovered by CMake:
- SDL3 — Cross-platform windowing/input
- nlohmann/json — JSON parsing
- toml++ — TOML parsing (UI schema/themes)
- libcurl — HTTP/HTTPS transport for daemon RPC and network calls (system on Linux/macOS, fetched on Windows)
Bundled in libs/:
- Dear ImGui — Immediate mode GUI
- libsodium — Cryptographic operations (system on Linux or fetched by
scripts/fetch-libsodium.sh) - QR-Code-generator — QR code rendering
- miniz — ZIP compression
- GLAD — OpenGL loader (Linux/macOS)
- stb_image — Image loading
- incbin — Binary resource embedding (Windows builds)
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
| Ctrl+, | Settings |
| F5 | Refresh |
| Alt+F4 | Exit |
Translation
Current language files live in res/lang/ as de, es, fr, ja, ko, pt, ru, and zh JSON files, with built-in English fallbacks.
To add a new language:
- Copy
res/lang/es.jsontores/lang/<code>.json - Translate all strings
- The language will appear in Settings automatically
License
This project is licensed under the GNU General Public License v3 (GPLv3).
Credits
- The Hush Developers
- DragonX Community
- Dear ImGui by Omar Cornut
- SDL by Sam Lantinga
Links
- Website: https://dragonx.is
- Explorer: https://explorer.dragonx.is
- Source: https://git.dragonx.is/dragonx/ObsidianDragon








