Files
davide e349a80ddc feat(spv): anchor header trust to hardcoded mainnet checkpoints
ChainProfiles.Mainnet.Checkpoints was an empty array with a "populate
before release" TODO, and even BlockHeaderInfo.MatchesCheckpoint()/
IsValidChild() — the methods meant to enforce it — were never called
anywhere in WalletSynchronizer. So on this LWMA chain, where PoW can't
be recomputed client-side (SkipPowValidation), a malicious or
eclipsing server could hand back any internally-consistent 80-byte
header for a Merkle proof: nothing tied it to the real Palladium
chain.

Populated Mainnet.Checkpoints with 24 real [height, hash, bits]
checkpoints (every 20,000 blocks + one near tip), pulled via RPC from
a fully-synced palladiumd. Testnet/Regtest are left empty (no node
available to verify against, and WalletSynchronizer already treats a
missing checkpoint as a no-op, so this is safe, just unanchored).

Added WalletSynchronizer.AnchorToCheckpointAsync: for every header
used in a Merkle proof, downloads the intervening headers back to the
nearest checkpoint at or below that height and verifies an unbroken
prev-hash chain terminating in the checkpoint's exact hash, finally
wiring up the previously-dead MatchesCheckpoint/IsValidChild. Verified
ranges are memoized in-memory per sync session to avoid re-walking.

Updated SECURITY.md and USERGUIDE.md to describe what is actually
enforced now (previously the guide deliberately avoided promising
checkpoint anchoring, since the array was empty).
2026-07-07 15:12:17 +02:00

44 KiB
Raw Permalink Blame History

Palladium Wallet — User Guide

This guide covers every user-facing feature of Palladium Wallet (GUI and CLI), including default values, validation rules, limits, and edge cases. It is written so that no behavior has to be guessed: when the wallet enforces a rule, the rule is stated here with its exact numbers.

Applies to version 0.9.x. Where the GUI and the CLI differ, both are described.


Table of contents

  1. What Palladium Wallet is (and is not)
  2. Key concepts you must understand before holding funds
  3. Installation and platform differences
  4. First launch: the setup wizard
  5. Opening, closing and managing multiple wallets
  6. The main screen
  7. Receiving funds
  8. Sending funds
  9. Transaction history and details
  10. The Addresses tab
  11. Contacts
  12. Connection, servers and certificate pinning
  13. Settings
  14. Wallet Information (xpub, seed, fingerprint)
  15. Backup and recovery
  16. Security model and known limitations
  17. Command-line interface (CLI)
  18. Troubleshooting and error messages
  19. Glossary

1. What Palladium Wallet is (and is not)

Palladium Wallet is a self-custody SPV (Simplified Payment Verification) wallet for the Palladium (PLM) cryptocurrency, a Bitcoin-derived UTXO chain with 2-minute blocks. It runs on Windows, Linux and Android from the same codebase, plus a separate command-line interface.

Self-custody means: you hold the keys. There is no account, no server-side backup, no password recovery service. If you lose your seed phrase (and your wallet file plus its password), your funds are permanently unrecoverable. Nobody — including the developer — can restore them.

SPV means the wallet does not download or validate the full blockchain. It connects to an indexing server (ElectrumX-compatible, ports 50001 TCP / 50002 SSL) and downloads only the data relevant to your addresses. Every confirmed transaction the server reports is independently verified with a Merkle proof against the block header; a server that lies about confirmed transactions is detected and the synchronization aborts. See section 16 for exactly what the server can and cannot do to you.

What this wallet intentionally does not include (as of this version):

  • Lightning Network
  • Hardware-wallet integration
  • Coin control (manual UTXO selection) — coin selection is always automatic
  • RBF fee bumping (transactions signal RBF, but there is no "bump fee" button)
  • Tor/proxy support — the indexing server can observe which addresses you query
  • Fiat currency conversion
  • Network selection in the GUI — the GUI operates on mainnet only; testnet and regtest are available through the CLI (--net)

2. Key concepts

Read this section once, carefully. Every rule below is enforced by the software exactly as written.

2.1 The seed phrase (BIP39 mnemonic)

  • When you create a new wallet in the GUI, it generates a 12-word English BIP39 mnemonic. It is shown once, during the wizard, and you must write it down on paper, in order.
  • Whoever knows these words controls the funds — from any device, forever, with no further information needed (unless you also set a passphrase, see below).
  • When restoring, the wallet accepts any valid BIP39 mnemonic (12 or 24 words in the GUI prompt; the parser also accepts 15/18/21-word mnemonics and auto-detects the wordlist language). The checksum is validated: a mistyped word is rejected, not silently accepted.

2.2 The optional passphrase ("25th word")

During creation or restore you may set a BIP39 passphrase. Understand precisely what it does:

  • The passphrase is combined with the seed words to derive the keys. Seed + passphrase produce a completely different wallet than the same seed without a passphrase (or with any other passphrase, including one differing by a single character or by case).
  • There is no validity check possible: entering the "wrong" passphrase during a restore does not produce an error — it silently opens a different, empty wallet. If you restore and see a zero balance where you expected funds, the first thing to check is the passphrase (then the script type, see 2.3).
  • Store the passphrase separately from the seed words. Losing the passphrase makes the funds unrecoverable even if you still have the 12 words.

2.3 Script type (address format)

Each wallet is created with exactly one script type, which determines the address format and the derivation path. It cannot be changed later; to switch, create a new wallet and move the funds.

Script type Standard Derivation Mainnet addresses look like
Legacy BIP44 m/44'/746'/0' start with P
Wrapped SegWit BIP49 m/49'/746'/0' start with 3
Native SegWit (default, recommended) BIP84 m/84'/746'/0' start with plm1q
Taproot BIP86 m/86'/746'/0' start with plm1p

Restoring with the wrong script type is the same trap as the wrong passphrase: the seed is accepted, but different addresses are derived and the balance shows zero. When restoring, select the same script type the wallet was created with. If unsure, try Native SegWit first (the default), then the others.

The coin type in the derivation path is 746 on mainnet (1 on testnet/regtest).

2.4 Wallet types

Type Created via Can sign/spend Notes
HD (BIP39 seed) Create new / Restore from seed Yes The normal case
HD (imported xprv) Import extended key (xprv/yprv/zprv) Yes Full account key, no seed words
Watch-only (xpub) Import extended key (xpub/ypub/zpub) No Sees balances/history; cannot sign. In the GUI it can prepare a transaction preview but not sign or broadcast it. The CLI produces an unsigned PSBT for offline signing
Imported WIF keys Import WIF key(s) Yes Fixed address list, no HD derivation and no change chain — change always returns to the first imported address (this links your coins together; prefer an HD wallet for privacy)

The extended-key format is SLIP-132: xpub/xprv (Legacy and Taproot), ypub/yprv (Wrapped SegWit), zpub/zprv (Native SegWit). The script type is auto-detected from the prefix when importing.

2.5 The wallet file and its encryption

Everything the wallet knows is stored in one file per wallet: <data folder>/mainnet/wallets/<name>.wallet.json (default name default.wallet.json). It contains the seed (or xpub/xprv/WIF keys), the derivation settings, your contacts, and a sync cache (balances, history, verified proofs).

  • If you set a password, the file is encrypted with AES-256-GCM; the key is derived with PBKDF2-HMAC-SHA512, 600,000 iterations, random 16-byte salt (fresh salt and nonce on every save). Tampering with the file is detected before decryption.
  • If you decline encryption (the wizard checkbox, or omitting --password in the CLI), the seed is stored in plaintext on disk. The wizard warns you explicitly. Only do this on a disk you fully trust (e.g. an encrypted volume).
  • There are no password strength requirements and no attempt limits. An empty password is not allowed when encryption is enabled. Choose a strong password yourself: an attacker who copies the file can try passwords offline at their leisure.
  • There is currently no "change password" function in the GUI. To change the password, restore the wallet from its seed into a new wallet file with the new password, verify the new file opens and syncs, then delete the old file. (Contacts must be re-entered — see section 15.)

2.6 Confirmations and spendability

Incoming funds are not immediately spendable. The exact rules on mainnet:

  • Unconfirmed (mempool) transactions: shown as "pending confirmation … not yet spendable". Never spendable, and — important — unconfirmed amounts are reported by the server without cryptographic proof, so treat them as provisional until confirmed.
  • Regular outputs: spendable after 6 confirmations (~12 minutes at 2-minute blocks).
  • Mining (coinbase) outputs: spendable after 121 confirmations (~4 hours). Until then they appear as "maturing … not yet spendable".

The main balance shown is confirmed minus immature; pending and maturing amounts are shown as separate amber lines under the balance when present.


3. Installation and platform differences

3.1 Desktop (Windows / Linux)

Release binaries are self-contained — no runtime to install. Run the single executable (PalladiumWallet.exe on Windows, PalladiumWallet on Linux).

3.2 Android

Install the .apk (sideloading must be allowed). Minimum Android version: 6.0 (API 23). The app requests the camera permission only if you use the QR scanner; internet is required for synchronization.

Updating in place: releases built with the project's official signing key update over the installed app. If Android refuses to install an update ("app not installed" / signature mismatch), the new apk was signed with a different key — you would have to uninstall first, which deletes the wallet file. Back up your seed before uninstalling, always.

3.3 What differs between desktop and Android

Aspect Desktop Android
Data location Chosen at first run (default or custom folder) Fixed: the app's private sandbox (step skipped)
Menu bar File / Network / Settings / Wallet / Help No menu bar; same functions reachable from the UI
Close overlays Esc key or click the dark backdrop Hardware/gesture Back button or tap the backdrop
QR code scanning (Send) Not available Camera scan button in the Send form
CLI Available Not available

Everything else — wallet formats, security, sync, features — is identical.

3.4 Where your data lives (desktop)

Resolution order:

  1. A palladium-data/ folder next to the executable, if present (portable mode — create the folder manually before first launch to get a fully portable install).
  2. The custom folder you picked in the first-run wizard (remembered via a small pointer file in the default location).
  3. The default: %APPDATA%\PalladiumWallet on Windows, ~/.palladium-wallet on Linux.

Inside the data root: mainnet/wallets/*.wallet.json (your wallets), mainnet/server-certs.json (pinned TLS certificates), mainnet/servers.json (discovered servers), config.json (language, unit, last server — shared across wallets).


4. First launch: the setup wizard

4.1 Step: data location (desktop only, very first run)

Choose where the wallet stores its data: "Use the default path" (shown on screen) or "Choose a folder…" (native folder picker). This step never reappears once configured. On Android it is skipped entirely.

4.2 Step: start

Five options:

  1. Open existing wallet — see section 5.
  2. Create a new wallet
  3. Restore from seed
  4. Import xpub / xprv
  5. Import WIF key

4.3 Creating a new wallet

  1. Your seed (12 words) — the freshly generated mnemonic is displayed. Write the words on paper, in order. They are never shown in full again except through the password-gated "Show seed" function (section 14). Do not photograph them, do not store them in a cloud note.
  2. Confirm seed — retype the 12 words, space-separated. Comparison is case-insensitive and tolerant of extra spaces. A mismatch shows "The words do not match: check what you wrote on paper." and lets you retry.
  3. Optional passphrase — leave empty to skip. Re-read section 2.2 before setting one.
  4. Script type — default Native SegWit. If unsure, keep the default.
  5. Password step — see 4.7.

4.4 Restoring from seed

  1. Enter the mnemonic, words separated by spaces. Invalid words or a bad checksum produce "Invalid mnemonic (wrong words or checksum): check again."
  2. Enter the same passphrase used originally (empty if none was used).
  3. Select the same script type used originally.
  4. Password step (4.7).

After the first synchronization the balance and full history reappear. If the balance is zero when it shouldn't be: wrong passphrase or wrong script type (sections 2.22.3).

4.5 Importing an extended key (xpub / xprv)

Paste a SLIP-132 extended key:

  • Public key (xpub/ypub/zpub) → watch-only wallet: monitors balances and history, cannot spend.
  • Private key (xprv/yprv/zprv) → fully spendable HD wallet (account level, no seed words).

The script type is detected automatically from the key prefix and shown for confirmation (e.g. "NativeSegwit (watch-only)"). An unrecognized key shows "Extended key not recognised for this network." — check that it is a Palladium key of a supported format, not a key from another coin.

4.6 Importing WIF private keys

Paste one or more WIF keys, one per line. Each key controls exactly one address; there is no HD derivation. Select the script type (which address form the keys map to), then the password step. Remember the change-address caveat from section 2.4.

4.7 The password step (all flows)

  • Wallet name (optional): letters/numbers recommended; invalid filesystem characters are replaced with _. Left blank → automatic name (default, then wallet-2, wallet-3, …). A name that already exists is rejected: "A wallet with this name already exists."
  • "Encrypt the wallet file with the password" — checked by default. If you uncheck it, the file (including the seed) is written in plaintext and the UI warns you.
  • Password + confirmation — must match and be non-empty when encryption is on. No other rules are imposed; strength is your responsibility.
  • Create wallet finalizes: the file is written, locked against concurrent access, opened, and the first connection/sync starts automatically.

5. Opening, closing and managing multiple wallets

  • You can keep any number of wallets: each is a separate *.wallet.json file in the wallets folder. With more than one file, "Open existing wallet" shows a chooser list; with exactly one, it goes straight to the password prompt.
  • Password prompt: leave empty for an unencrypted wallet. Wrong password → "Wrong password." — retries are unlimited.
  • The GUI only lists wallets inside its own wallets folder. To use a wallet file from elsewhere, copy it into <data folder>/mainnet/wallets/ first (while the app is closed, or before pressing Open).
  • Single-instance lock: a wallet file can be open in only one running instance at a time. A second attempt fails with "Wallet already open in another instance of the application." A stale .lock file left by a crash is released automatically when the owning process is gone.
  • Switching wallets: menu File → Close wallet (returns to the wizard), then Open existing wallet. File → New / restore wallet… also closes the current wallet first.
  • Deleting a wallet: there is no in-app delete. Close the app and delete the .wallet.json file manually — only after verifying you have the seed on paper (or, for imported wallets, the original keys). Deleting the file of an unbacked-up wallet destroys the funds' keys.

After opening, the header shows the wallet's identity, e.g. Mainnet · NativeSegwit · m/84'/746'/0', with a · watch-only or · imported tag when applicable.


6. The main screen

Five tabs: History, Send, Receive, Addresses, Contacts.

  • Balance (top): confirmed, spendable balance in your chosen unit. Below it, when applicable, two amber advisory lines: pending confirmation (mempool, unproven, not spendable) and maturing (young coinbase, not spendable — see section 2.6).
  • Status bar (bottom): left, the sync status (e.g. "Synchronized: height 123456, 42 SPV-verified transactions. Real-time updates active."); right, the connection indicator (connected host:port / connecting… / not connected / reconnecting…). Click/tap the connection indicator to open the server settings.
  • All secondary screens (settings, details, wallet info, help) are in-app overlays, not separate windows. Close them with the ✕ button, by clicking the dark backdrop, with Esc (desktop) or Back (Android).

7. Receiving funds

The Receive tab always shows the next unused receive address, as text and as a QR code (the QR encodes the bare address).

  • Copy puts the address on the clipboard ("Address copied to clipboard").
  • Give a fresh address to each payer. After an address receives a payment and a sync runs, the tab automatically advances to the next unused address. Reusing addresses is not blocked, but it degrades your privacy by linking payments together.
  • Incoming payments appear in History at the next synchronization — normally within seconds, because the wallet subscribes to server push notifications. A payment shows as mempool first, then with its block height once mined.
  • The address format is fixed by the wallet's script type (section 2.3); senders must support that format (in particular, very old software may not send to plm1… bech32 addresses).

Gap limit — the one receiving rule you must know. The wallet derives addresses on demand and, when restoring from seed, scans forward until it finds 20 consecutive unused addresses and then stops. Consequence: if you hand out many addresses that never receive funds, do not skip ahead by more than 20 — a payment to address #30, with #10#29 unused, would not be found after a restore from seed. Under normal use (addresses handed out sequentially, most getting used) this never triggers. The limit (20) is stored per wallet and is not editable in the GUI.


8. Sending funds

Prerequisites: the wallet must be connected and synchronized (otherwise: "Connect to the server and synchronize before sending" / "Synchronize before sending"), and the wallet must be spendable (not watch-only) to actually broadcast.

8.1 The form

  • From contacts — optional dropdown that fills the recipient address from your address book.
  • Recipient address — validated when you prepare: an address of the wrong network or with a typo is rejected (checksums make silent typos virtually impossible).
  • Amount — interpreted in the currently selected display unit (PLM by default — check the unit in Settings before typing!). Rejected if negative, malformed, or more precise than 1 satoshi (0.00000001 PLM).
  • Send all — checkbox; disables the amount field and sends the entire spendable balance, with the fee deducted from the amount (the recipient receives balance fee).
  • Fee (sat/vB) — a single manually-entered fee rate. Default: 1 sat/vB. There are no presets and no automatic fee estimation. On the Palladium chain, blocks are rarely full, so 1 sat/vB normally confirms in the next few blocks; raise it if a transaction lingers in the mempool. Must be a number greater than zero.
  • QR scan (Android only) — camera button; reads a plain address or a palladium: payment URI (the address part is used).

8.2 Prepare, then confirm

Sending is a two-step operation:

  1. Prepare transaction — builds and signs the transaction locally, without sending anything. The summary card shows the txid (truncated), the exact fee, and the virtual size, e.g. txid 4f3a…| fee 0.00000141 PLM (141 vB). Nothing has left your wallet yet; you can change the fields and prepare again, or simply navigate away to abandon it.
  2. CONFIRM AND BROADCAST — transmits the prepared transaction to the server. Success shows the full txid; the form clears and a re-sync starts. After broadcasting, a transaction cannot be cancelled — it is in the network's mempool and will confirm.

8.3 How the transaction is built (facts you may need)

  • Coin selection is automatic (there is no coin control). The wallet spends from its spendable UTXOs and sends any change back to its own internal change chain — this is why, in transaction details, one output to an address you don't recognize as "yours" may still be marked as yours: it is your change.
  • All transactions signal RBF (BIP125) and use transaction version 2. The wallet does not offer fee bumping; if you underpay the fee, wait — with RBF signaled, other wallets could in principle replace it, but this wallet has no UI for that.
  • Dust change is absorbed into the fee: if the change output would be uneconomically small, it is added to the fee instead of creating a dust output. The fee shown in the summary already accounts for this — always check the summary fee before confirming.
  • A prepared transaction is fully verified against standardness policy before it can be confirmed; a policy failure surfaces as "Invalid transaction: …" instead of a broadcast.

8.4 Why "insufficient funds" can appear despite a visible balance

The error message itemizes the reasons. Funds may be temporarily unspendable because they are:

  • in the mempool (unconfirmed — never spendable),
  • recently confirmed (fewer than 6 confirmations),
  • immature coinbase (mining rewards younger than 121 blocks).

Wait for confirmations and retry. Also remember that the fee itself must fit: sending your exact full balance fails unless you use Send all.

8.5 Watch-only wallets and offline signing

A watch-only (xpub) wallet in the GUI can prepare a transaction to preview the fee and size — the summary is tagged "unsigned (watch-only)" — but the confirm button stays disabled: the GUI cannot export the unsigned transaction. To actually use the watch-only + offline-signing workflow, use the CLI, whose send command prints an unsigned PSBT (base64) for a watch-only wallet (section 17). Sign that PSBT on the offline machine with software of your choice, then broadcast the finalized transaction.

8.6 The Donate tab (Help → Donate)

The Help overlay includes a donation form (developer address plm1qdq3gu2zvg9lyr8gxd6yln4wavc5tlp8prmvfay) using the same prepare/confirm flow and the fee rate from the Send tab (falling back to 1 sat/vB if invalid). Entirely optional.


9. Transaction history and details

The History tab lists all wallet transactions, newest first; unconfirmed ones are labeled mempool and sorted on top, confirmed ones show their block height. The amount is the transaction's net effect on your wallet (+ incoming).

Double-click (desktop) or tap (Android) a row to open the full details. This requires a live server connection (details are fetched on demand): otherwise "Connect to the server to view transaction details."

The details overlay shows:

  • Overview — status ("N confirmations (block H)" or "0 confirmations · in mempool"), local date/time, counterparty addresses, and the signed net amount. Mining rewards show "Newly generated (mining)" as the sender.
  • Amounts & fees — the absolute fee, your net amount, and the fee rate in sat/vB.
  • Technical details — full transaction ID, total size, virtual size, Replaceable (RBF) yes/no, version, locktime.
  • Inputs — each spent outpoint with its address and amount; your own inputs are highlighted. Coinbase inputs display the miner's scriptSig message when it is readable text.
  • Outputs — each output with index, address and amount; your own outputs (including change) are highlighted. OP_RETURN outputs display their decoded text message when the payload is valid readable text; non-standard outputs show their script type.

Notes and limits:

  • Confirmation counts advance automatically as blocks arrive (real-time header subscription).
  • Every confirmed transaction in your history has been verified with a Merkle proof during sync. Unconfirmed entries are the server's word only — do not treat a mempool payment as received until it confirms.
  • There are no per-transaction labels and no block-explorer links in this version. The public explorer is at https://explorer.palladium-coin.com/ — paste the txid there manually if needed.

10. The Addresses tab

A complete table of every derived address: type (receive/change), index, address, balance, and transaction count. Before the first sync it shows the first 10 receive addresses with no data.

Tap (or right-click) a row to open the address details overlay:

  • the full address and its derivation path (e.g. m/84'/746'/0'/0/3),
  • the public key (hex),
  • the private key (WIF), hidden behind a "Show" button. For an encrypted wallet, revealing it requires re-entering the wallet password ("Enter the wallet password to reveal the private key."); for an unencrypted wallet it is shown directly. Never reveal a private key with anyone watching your screen — one key controls that one address's funds. Watch-only wallets have no private keys to show.

change addresses are where your own transactions send their change (section 8.3) — seeing balance on them is normal.


11. Contacts

A simple per-wallet address book, on its own tab:

  • Add: name + address, both required (whitespace is trimmed). Note: the address format is not validated when saving — it is only validated when you actually send to it. Copy addresses carefully.
  • Remove selected: deletes the highlighted contact. There is no edit function — remove and re-add.
  • Contacts are used by the From contacts dropdown on the Send tab.
  • Contacts are stored inside the wallet file. They travel with a file backup, but are not recoverable from the seed phrase (section 15).

12. Connection, servers and certificate pinning

12.1 Server settings

Open by clicking the connection indicator in the status bar (or Settings → Indexing server…, or menu Network on desktop). Fields:

  • Host and Port — defaults: port 50001 (plain TCP) or 50002 (SSL). Editing one of the known ports auto-toggles the SSL switch to match, and toggling SSL swaps the port. Note these are the indexing server ports — not the Palladium node's P2P port (2333), which this wallet never uses.
  • Use SSL — default on. Strongly recommended: without SSL, traffic (including which addresses you query) is readable on the wire.
  • Known servers list — click an entry to select it. The wallet ships with four bootstrap mainnet servers and remembers any servers learned via discovery.
  • Discover servers (peers) — asks the connected server for its known peers and adds new ones to the list.

Connection behavior: the wallet tries your selected server first, then walks the rest of the known list until one answers. The last working server is remembered and reused at next launch. A 20-second keep-alive ping detects drops and reconnects automatically; server push notifications trigger instant re-syncs when a new block or a relevant transaction appears ("Real-time updates active").

12.2 TLS certificate pinning (TOFU) — read before "fixing" a certificate error

SSL connections use Trust On First Use: the first time you connect to a server, its certificate's fingerprint is saved (in server-certs.json). Every later connection must present the same certificate. If it doesn't, the connection is refused with a message stating that the TLS certificate of that server has changed.

This is a security feature, not a bug. A changed certificate means one of two things:

  1. Benign: the server operator renewed/rotated the certificate (common, e.g. Let's Encrypt renewals).
  2. Hostile: someone is intercepting your connection (man-in-the-middle).

You cannot distinguish the two from the wallet alone. If the change is expected or you can verify it out-of-band, clear the pins: menu Network → Reset SSL certificates (desktop), the Reset certs button in server settings, or reset-certs in the CLI. This deletes all pinned certificates for the network; the next connection re-pins whatever it sees. If you have any reason to suspect interception, switch networks (e.g. off a public Wi-Fi) or servers instead of resetting.

12.3 What synchronization actually does

Each sync: gets the chain tip → scans your receive and change address chains (gap limit 20) → downloads your transactions → verifies a Merkle proof for every confirmed transaction against its block header → rebuilds your UTXO set and balances locally. On mainnet, each block header used for a proof is also chained back (via its previous-block hash) to the nearest built-in checkpoint, so a server cannot substitute a fabricated header for a real one. Verified data is cached in the wallet file, so later syncs only fetch what is new — even after a restart. If a proof or the checkpoint chain does not check out, the sync aborts with an explicit "server is not trustworthy" error rather than showing you unverified data; switch servers.

If the server is overloaded (busy responses), the wallet retries automatically up to 8 times with increasing back-off — a large wallet's first sync may take a little while, but it resumes from the cache instead of restarting.


13. Settings

The Settings overlay (gear icon / menu Settings) contains exactly two preferences, plus the door to the server settings:

  • Language — Italiano, English, Español, Français, Português, Deutsch. Applies immediately. Default: English.

  • Amount unit — how amounts are displayed and interpreted when you type them:

    Unit In satoshi Decimals shown
    PLM (default) 100,000,000 8
    mPLM 100,000 5
    µPLM 100 2
    sat 1 0

    ⚠ The Send form's amount field uses this unit. If you switch to sat and forget, typing 100 means 100 satoshi, not 100 PLM. Double-check the unit before sending.

Settings are saved globally (per data folder, shared by all wallets), not per wallet. There is no theme selector (the app uses its built-in dark theme) and no fiat display.


14. Wallet Information

Menu Wallet → Wallet Information (desktop) or the equivalent button. Shows:

  • File name, network, wallet type (HD (BIP39 seed) / HD (imported xprv) / Imported WIF key / Watch-only (xpub)), script type, derivation path.
  • Extended public key (xpub) — displayed as selectable text. This is how you export the xpub: select and copy it. Give the xpub to another device/app to create a watch-only copy of this wallet — it reveals your entire address history and balance to whoever holds it (privacy risk), but can never spend.
  • Master fingerprint — 4-byte identifier of the master key, used in PSBT workflows.
  • BIP39 passphrase — shows only whether one is set; the passphrase itself is never displayed anywhere.
  • Show seed — reveals the mnemonic, after re-entering the wallet password (for encrypted wallets). Use it to re-verify your paper backup. The on-screen warning is literal: never share these words; whoever holds them controls the funds. Watch-only and imported wallets have no seed to show.

15. Backup and recovery

15.1 What to back up

There are two complementary backups; know exactly what each one restores:

Backup Restores Does NOT restore
Seed words on paper (+ passphrase if set, + script type) All keys, addresses, balance and on-chain history, on any device, forever Contacts; wallet name; settings
The wallet file (+ its password) Everything, including contacts

Recommended: always have the paper seed (it survives disk failure, device loss, and software obsolescence); additionally copy the .wallet.json file if you care about your contacts list. An encrypted wallet file is safe to store on ordinary media — but it is only as strong as its password, and it is useless without it.

For a watch-only wallet, the file only restores the watching capability; the actual keys live wherever you keep the corresponding seed/xprv — back that up.

For an imported WIF wallet, back up the WIF keys themselves; they are not derivable from anything else.

15.2 Restoring, step by step

  1. Install the wallet on the new device.
  2. Wizard → Restore from seed → enter the words → enter the same passphrase (or leave empty if none) → choose the same script type → set a (new) password.
  3. Let it synchronize. Balance and history are rebuilt from the chain.

If the balance is zero: wrong passphrase, or wrong script type, or (rare) funds beyond the gap limit (section 7). Nothing is lost — the coins are still on the chain; you are simply looking at the wrong derived wallet. Retry with the right parameters.

Restoring from a file copy instead: place the .wallet.json into <data folder>/mainnet/wallets/ and open it with its password.

15.3 Unrecoverable situations — be aware

  • Seed lost and wallet file (or its password) lost → funds gone. No exceptions.
  • Passphrase forgotten → funds gone, even with the 12 words in hand.
  • Encrypted file's password forgotten, no seed backup → funds gone (the encryption has no backdoor).

16. Security model and known limitations

A condensed version of the project's published threat model (SECURITY.md).

The wallet protects you against:

  • Theft of the wallet file at rest (AES-256-GCM + PBKDF2, section 2.5) — provided you set a good password.
  • A lying indexing server: it cannot fabricate a confirmed transaction or forge a payment to a wrong address, because every confirmed transaction must carry a valid Merkle proof, which the wallet checks itself.
  • Silent TLS interception after first contact (certificate pinning, section 12.2).

The server can still (semi-trusted component):

  • lie about unconfirmed transactions (which is why they are marked not-spendable and should not be trusted until confirmed);
  • withhold information — hide transactions, delay new blocks, refuse to broadcast;
  • observe which addresses belong to you (no Tor/proxy support in this version; using your own indexing server is the strongest mitigation).

The wallet cannot protect you against:

  • malware on your device (anything that can read process memory can take the keys once the wallet is unlocked);
  • an attacker holding both your wallet file and its password (or your seed);
  • yourself: there are no confirmation "cool-downs", no address whitelists, and broadcast is irreversible.

Honest limitations of this version (also listed in section 1): single server connection (no pooling), no coin control, no fee estimation, no RBF bumping, no hardware wallets, no Tor, GUI mainnet-only, and PSBT export only via the CLI.


17. Command-line interface (CLI)

The CLI (src/Cli) runs on the same core as the GUI: same wallet files, same validation, same security. It is desktop-only and its console output is in English. Run it as dotnet run --project src/Cli -- <command> from the repository (or the published Cli binary); with no arguments it prints usage.

Shared conventions. Default wallet file: ~/.palladium-wallet/<network>/wallets/default.wallet.json — override with --file PATH. Default network mainnet — override with --net testnet|regtest (the CLI is the only way to use test networks). --password P both decrypts an existing file and encrypts on save; omitting it on create/restore writes the seed in plaintext (a warning is printed). --kind legacy|wrapped|segwit selects the script type (default Native SegWit — note that only the literal values legacy and wrapped switch away from the default). Errors print to stderr and set exit code 1.

Wallet commands

newseed  [--words 24]

Prints a fresh mnemonic (12 words unless --words 24) and writes nothing to disk.

create   [--words 24] [--kind K] [--net N] [--passphrase W] [--password P] [--file PATH] [--path m/...]

Generates a mnemonic, prints it once, saves the wallet, prints the file path and the first receive address. --path overrides the derivation path (advanced; you must remember it to restore).

restore  "<mnemonic>" [same options as create]

Restores from an existing mnemonic (quoted, words space-separated).

restore-xpub <slip132-key> [--net N] [--password P] [--file PATH]

Creates a watch-only wallet from an xpub/ypub/zpub; the script type is inferred from the key prefix.

info     [--net N] [--password P] [--file PATH] [--addresses]

Prints the wallet's identity and, if it has ever synced, the balance breakdown (spendable / maturing / pending), tip height, transaction count and next receive address. --addresses adds the per-address list with balances.

addresses "<mnemonic>" [--kind K] [--net N] [--count N] [--passphrase W] [--path m/...]

Stateless tool: derives and prints receive (default 5) and change addresses from a mnemonic without creating any file. Useful to check "which script type was this seed used with" before restoring.

Network commands

sync     [--server host[:port]] [--ssl] [--net N] [--password P] [--file PATH]

Connects (default: the first known server; port defaults to 50001, or 50002 with --ssl), synchronizes with full Merkle verification, persists the cache into the wallet file, and prints balance and history. Transactions the server reported but that are unconfirmed are marked as unverified.

send     --to ADDRESS (--amount X | --all) [--feerate R] [--broadcast]
         [--server ...] [--ssl] [--net N] [--password P] [--file PATH]

Builds a transaction from the synced cache (sync must have been run first). --amount is in PLM; --all sends everything minus the fee. --feerate is in sat/vB, default 1. Behavior by wallet type and flags:

  • Watch-only wallet → prints the unsigned PSBT in base64 and stops. This is the air-gapped workflow: carry the PSBT to the offline signer, sign it there, broadcast the final transaction by any means.
  • Spendable wallet, without --broadcast → signs and prints the raw transaction hex, explicitly marked as not transmitted. Nothing is sent — a dry run you can inspect or broadcast elsewhere.
  • Spendable wallet, with --broadcast → signs, transmits, prints the txid. Irreversible from this point.
servers  [--discover] [--server ...] [--ssl] [--net N]

Lists known servers; with --discover, connects and asks the server for its peers, adding new ones.

reset-certs [--net N]

Deletes all pinned TLS certificates for the network (the CLI counterpart of Network → Reset SSL certificates — see section 12.2).


18. Troubleshooting and error messages

Symptom / message Meaning What to do
Wrong password. The password does not decrypt the file (or the file was tampered with — the two are indistinguishable by design). Retry; check keyboard layout/caps lock. If truly lost, restore from seed (15.2).
Wallet already open in another instance of the application. Another running process holds this wallet's lock. Close the other instance (GUI or CLI).
The TLS certificate of host:port has changed… Certificate pin mismatch — renewal or interception. Read 12.2 before resetting certificates.
Sync aborts, "server is not trustworthy" A Merkle proof failed, or (mainnet) a block header did not chain back to a known checkpoint. Switch to another server. Your local data is intact; the wallet refused the bad data.
Insufficient funds with a non-zero balance Funds are unconfirmed, under 6 confirmations, or immature coinbase; or the fee doesn't fit. See 8.4. Wait, or use Send all.
Restored wallet shows zero balance Wrong passphrase, wrong script type, or funds beyond the gap limit. See 15.2 — the coins are not lost.
Invalid mnemonic (wrong words or checksum) A word is misspelled, not on the BIP39 list, or the checksum fails. Compare against your paper backup, word by word.
Extended key not recognised for this network. The pasted xpub/xprv is not a SLIP-132 key of this network. Check the key's prefix and the source wallet's export format.
A wallet with this name already exists. Filename collision in the wallets folder. Pick another name, or leave blank for an automatic one.
Payment sent to me doesn't appear Not yet synced/connected, or sender hasn't broadcast. Check the connection indicator; mempool entries appear within seconds of broadcast when connected.
Update prompt at startup ("Update available") A newer GitHub release exists (checked once at startup, silently skipped offline). Download opens the release page; Dismiss continues. Never enter your seed into anything but the wallet itself.
Android: update apk refuses to install Signature mismatch between builds. Back up the seed before uninstalling; see 3.2.
First sync is slow / server busy errors Server throttling; the wallet retries automatically (up to 8 attempts, growing back-off). Wait; progress is cached, so restarting resumes rather than repeats.

19. Glossary

  • SPV — Simplified Payment Verification: validating that transactions are included in blocks via Merkle proofs, without running a full node.
  • Seed / mnemonic — the 12 (or 24) BIP39 words that deterministically generate every key in the wallet.
  • Passphrase (BIP39) — optional extra secret combined with the seed; a different passphrase yields a different wallet.
  • Script type — the address format standard (Legacy/BIP44, Wrapped SegWit/BIP49, Native SegWit/BIP84, Taproot/BIP86).
  • xpub / xprv — extended public/private key of the wallet's account; the xpub watches, the xprv spends. SLIP-132 variants: ypub/zpub etc.
  • WIF — Wallet Import Format: a single address's private key as text.
  • UTXO — Unspent Transaction Output: a discrete "coin" the wallet can spend.
  • Change — the portion of spent UTXOs returned to your own (internal) addresses.
  • Coinbase — the transaction paying the miner of a block; spendable after 121 confirmations.
  • Mempool — the set of broadcast-but-unconfirmed transactions.
  • Gap limit — how many consecutive unused addresses the wallet scans past before stopping (20).
  • PSBT — Partially Signed Bitcoin Transaction: the standard interchange format for signing a transaction on a device other than the one that built it.
  • RBF — Replace-By-Fee: a signal that a transaction may be replaced by a higher-fee version while unconfirmed.
  • TOFU — Trust On First Use: pinning a server's TLS certificate at first contact and refusing silent changes afterwards.
  • Watch-only — a wallet holding only public keys: full visibility, zero spending ability.

This guide documents observed behavior of the software and is kept in sync with the code. For the formal threat model see SECURITY.md; for per-release changes see CHANGELOG.md.