diff --git a/USERGUIDE.md b/USERGUIDE.md new file mode 100644 index 0000000..19afaa8 --- /dev/null +++ b/USERGUIDE.md @@ -0,0 +1,856 @@ +# 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)](#1-what-palladium-wallet-is-and-is-not) +2. [Key concepts you must understand before holding funds](#2-key-concepts) +3. [Installation and platform differences](#3-installation-and-platform-differences) +4. [First launch: the setup wizard](#4-first-launch-the-setup-wizard) +5. [Opening, closing and managing multiple wallets](#5-opening-closing-and-managing-multiple-wallets) +6. [The main screen](#6-the-main-screen) +7. [Receiving funds](#7-receiving-funds) +8. [Sending funds](#8-sending-funds) +9. [Transaction history and details](#9-transaction-history-and-details) +10. [The Addresses tab](#10-the-addresses-tab) +11. [Contacts](#11-contacts) +12. [Connection, servers and certificate pinning](#12-connection-servers-and-certificate-pinning) +13. [Settings](#13-settings) +14. [Wallet Information (xpub, seed, fingerprint)](#14-wallet-information) +15. [Backup and recovery](#15-backup-and-recovery) +16. [Security model and known limitations](#16-security-model-and-known-limitations) +17. [Command-line interface (CLI)](#17-command-line-interface-cli) +18. [Troubleshooting and error messages](#18-troubleshooting-and-error-messages) +19. [Glossary](#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](#16-security-model-and-known-limitations) 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**: +`/mainnet/wallets/.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](#15-backup-and-recovery).) + +### 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](#5-opening-closing-and-managing-multiple-wallets). +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](#14-wallet-information)).* 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](#22-the-optional-passphrase-25th-word) + 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.2–2.3](#22-the-optional-passphrase-25th-word)). + +### 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](#24-wallet-types). + +### 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 `/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](#26-confirmations-and-spendability)). +- **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](#23-script-type-address-format)); 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](#17-command-line-interface-cli)). 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](#83-how-the-transaction-is-built-facts-you-may-need)) — 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](#15-backup-and-recovery)). + +--- + +## 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. +Verified data is cached in the wallet file, so later syncs only fetch what is new — even +after a restart. If a proof 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. (A few low-level error messages are currently shown in + Italian regardless of language.) +- **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](#7-receiving-funds)). 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 +`/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](#25-the-wallet-file-and-its-encryption)) — + 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](#122-tls-certificate-pinning-tofu--read-before-fixing-a-certificate-error)). + +**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](#1-what-palladium-wallet-is-and-is-not)): +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 currently in Italian. Run it +as `dotnet run --project src/Cli -- ` from the repository (or the published `Cli` +binary); with no arguments it prints usage. + +**Shared conventions.** Default wallet file: +`~/.palladium-wallet//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 "" [same options as create] +``` +Restores from an existing mnemonic (quoted, words space-separated). + +``` +restore-xpub [--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 "" [--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](#122-tls-certificate-pinning-tofu--read-before-fixing-a-certificate-error)). + +--- + +## 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](#152-restoring-step-by-step)). | +| *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](#122-tls-certificate-pinning-tofu--read-before-fixing-a-certificate-error) **before** resetting certificates. | +| Sync aborts, "server is not trustworthy" | A Merkle proof failed: the server served data it cannot prove. | 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](#84-why-insufficient-funds-can-appear-despite-a-visible-balance). Wait, or use Send all. | +| Restored wallet shows zero balance | Wrong passphrase, wrong script type, or funds beyond the gap limit. | See [15.2](#152-restoring-step-by-step) — 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](#32-android). | +| 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](SECURITY.md); for per-release changes see +[CHANGELOG.md](CHANGELOG.md).*