8 Commits

Author SHA1 Message Date
davide 65c2f5e6cd temp 2026-07-17 16:24:38 +02:00
davide db5b65ca0d test(spv): cover checkpoint-anchoring memoization and the non-generic retry path
Two branches of WalletSynchronizer had no coverage: the early-return in
AnchorToCheckpointAsync when a range is already memoized (a second sync
with a tx below the previously-anchored height must not re-walk the
header chain), and the void RetryOnBusyAsync overload used by the
transaction-download tasks (only the generic <T> overload, exercised by
get_history, had a test).
2026-07-07 16:24:11 +02:00
davide 45f7b1401e test(spv): cover the PoW-checked branch of BlockHeaderInfo.IsValidChild
Every configured ChainProfile sets SkipPowValidation=true, so the
hash<=target branch (taken only when a future profile disables the
skip) had never run in the suite. Added a genesis-hash-satisfies-target
case and a tampered-bits case that pushes the target below the hash.
2026-07-07 16:23:58 +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 448f7dc65d test: cover network/SPV layer end to end (was previously untested)
ElectrumClient, WalletSynchronizer, TransactionInspector, CertificatePinStore
and peer discovery went from 0% coverage to close to full coverage, all
against the fake ElectrumX server:

- ElectrumClient: request/response correlation under load, server errors,
  notifications, disconnection, cancellation, SSL handshake with TOFU pinning.
- WalletSynchronizer: gap-limit scanning, UTXO/history reconstruction,
  unconfirmed/immature balances, busy-retry, disk-cache reuse, and the
  security-critical path where a lying server fails Merkle verification and
  the sync must abort.
- TransactionInspector: fee calculation from resolved inputs, mine/theirs
  attribution, RBF flag, coinbase handling, degraded paths when a previous
  transaction can't be resolved.
- CertificatePinStore: TOFU pin/match/mismatch/reset, corrupted-file fallback.
- ServerRegistry: peer discovery and persistence via DiscoverAsync.
- UpdateChecker: release-tag parsing and semver comparison.
2026-07-02 23:21:01 +02:00
davide 3d5a226a5a docs: translate all code comments to English (language policy)
Translate every Italian /// XML doc comment, <!-- --> XAML comment, and
// inline comment to English across all source files (Core, App, tests).
Add the language policy to CLAUDE.md (conversation Italian; all code
and docs English). Update one test assertion that checked an Italian
exception message that was also translated.
2026-06-16 14:40:11 +02:00
davide ee0b73dd52 test: expand coverage to 209 tests across all core modules
Added tests for CoinAmount (all units, comma decimal, sub-satoshi rejection,
overflow, unknown unit ArgumentException, roundtrip), Storage (nonce/salt
uniqueness per encrypt, atomic write, WalletLock acquire/release/stale-file),
WalletLoader (NewFromMnemonic, passphrase isolation, watch-only, invalid
inputs, ProfileOf), SPV/Merkle (single tx, odd/even counts, altered proof,
empty list), and Chain (unknown NetKind, distinct profiles, port constants).
2026-06-13 21:59:51 +02:00
davide 34c588c6f4 test: unit tests for all core modules 2026-06-11 10:48:27 +02:00