Commit Graph
13 Commits
Author SHA1 Message Date
davide c8ba2294f2 feat(app): suggest fee rates from the server and enforce the relay fee
After connecting, the Send tab offers Fast/Normal/Economy rates from the
server's fee estimates (never below the relay fee, implausible values
ignored). A manual rate below the relay fee is refused before building and
a fee above 1% of the amount is flagged in the preview. See ADR 0039.
2026-11-03 14:33:32 +01:00
davide 06d1f59c2b fix(app): derive an address private key only when revealed
Address rows and the address detail sheet no longer carry the WIF of
every listed address for the whole session. The key is derived after the
password gate and dropped when hidden, when the sheet closes or when the
wallet closes. See ADR 0037.
2026-11-03 14:10:58 +01:00
davide 8bcee27c23 feat(spv): verify the chain identity of a server on connect
After the handshake the wallet checks server.features genesis_hash and,
when the profile has checkpoints, the header at the highest checkpoint
not above the server's tip (mainnet shares Bitcoin's genesis, so the
checkpoint is what tells the chains apart). A server on another chain is
refused with WrongChainException and the next candidate is tried. Used by
the GUI, peer discovery, the CLI and the server probe. See ADR 0036.
2026-11-03 14:01:34 +01:00
davide 65c515bf7a fix(net): cap the length of a server line
A hostile server could stream an endless line with no newline and exhaust
the client's memory. A single reply is now capped at 16 MiB (configurable
via maxLineBytes in ConnectAsync); on excess the connection fails with
InvalidDataException. See ADR 0035.
2026-11-03 13:52:49 +01:00
davide bbed21e820 docs: reconcile README/SECURITY with current repo state
README.md was out of date after several recent features: it listed 6
UI languages (missing Chinese Simplified), described watch-only as
xpub-only (address-only import also exists), overclaimed multisig as a
working PSBT flow (derivation for it actually throws — not
implemented), and its CLI quick-reference omitted restore-address and
servers. Also links the new USERGUIDE.md, previously unreferenced from
README.

SECURITY.md's "known limitations" list didn't mention multisig is
unsupported, worth stating explicitly since it's fund-safety adjacent.
2026-07-19 12:59:15 +02:00
davide 11b6a9a9ab docs(security): document address-only watch-only wallets
Keeps the key-management section of the threat model accurate for the
new restore-address / pure address import path (SECURITY.md must stay
in sync with any change to key/seed handling per project convention).
2026-07-19 12:39:52 +02:00
davide 3460e53b4f feat(spv): verify Merkle proofs progressively, gate spendability on it
Balance/history now render as soon as tx downloads finish instead of
blocking on every historical Merkle proof, critical for mobile where
proof-checking can take much longer than the download itself. Proofs
continue to be checked in the background and each tx's Verified flag
catches up progressively; header ranges are now fetched in batches
(blockchain.block.headers) instead of one call per header to keep this
fast over high-latency links.

Coin selection (UtxoSpendability.IsSpendable) refuses to spend a UTXO
until its Merkle proof is actually checked, regardless of confirmation
count, so a server that fabricates a confirmed balance can get it
displayed early but never spent before the forgery is caught. The disk
cache only ever persists the fully-verified end state of a sync.

UI surfaces the new PendingVerificationSats/SpendableSats split with a
"verifying..." badge, and the sync save now runs off the UI thread to
avoid freezing on slower hardware.
2026-07-17 19:43:18 +02:00
davide 6f4ae679e5 docs: document fuzzing infrastructure and its security guarantees
Sync AGENTS.md/CLAUDE.md with the fuzzing workflow, add a README section
pointing to tests/PalladiumWallet.Fuzz, and record in SECURITY.md the two
guarantees the fuzz suite enforces: a bounded PBKDF2 iteration count on read
and a typed InvalidDataException for any malformed encrypted container.
2026-07-07 22:06:45 +02:00
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
davide b304996ff5 docs(security): correct PBKDF2 iteration count and salt size
SECURITY.md still documented the pre-hardening parameters (100,000
iterations, 32-byte salt); the code has used 600,000 iterations and a
16-byte salt (EncryptedFile.DefaultIterations) since the encryption
upgrade, with the count itself stored in the file container for
forward compatibility.
2026-07-07 14:24:43 +02:00
davide c75e3921aa docs: sync AGENTS.md with CLAUDE.md and fix stale references
AGENTS.md had drifted from CLAUDE.md (ASCII dashes instead of em-dashes,
missing recent updates); both now carry identical content except for the
header, with an explicit rule to keep them in sync on future edits. Also
documents update-version.sh as the release workflow, the per-feature
partial-class split of MainWindowViewModel, UpdateChecker, and fixes a
reference to a nonexistent Core/Spv/MerkleVerifier.cs (the real file is
MerkleProof.cs) in SECURITY.md.
2026-07-02 23:45:53 +02:00
davide 50d8e7f21a docs(security): disclose AI-assisted testing methodology
Documents the concrete techniques used (adversarial fake-server simulation
of a lying indexing server, property-based fuzzing, targeted security code
review) rather than a generic "AI-reviewed" claim, and states explicitly
that this complements rather than replaces independent security review.
2026-07-02 23:38:25 +02:00
davide a8d48bedad docs: add SECURITY.md with threat model and SPV trust assumptions
Covers: what the wallet protects against (AES-GCM at rest, Merkle SPV
verification, TLS TOFU pinning) and what it does not (compromised OS,
eclipse attacks, traffic analysis). Documents key/seed management,
encryption parameters, TLS pinning behaviour, backup guidance, and
known v1 limitations (no Tor, no coin control, no hardware wallet).
2026-06-13 21:15:41 +02:00