CWallet::ChangeWalletPassphrase ignores the return value of WalletBatch::WriteMasterKey. If the database write fails (e.g. disk full, I/O error), the RPC reports success while the wallet file on disk still requires the old passphrase. A user who discards the old passphrase after such a silent failure is locked out of their wallet after a restart.
This PR:
- Re-encrypts into a copy of the
CMasterKeyand only commits it tomapMasterKeysafter the database write succeeds, so in-memory state never diverges from disk in any failure path. (Previously a failingEncryptMasterKeycould also leave a mutatednDeriveIterationsin the map entry.) - Checks the
WriteMasterKeyreturn value and returnsfalseon failure. - Logs the write failure and restores the previous lock state before returning, so a failed call leaves the wallet exactly as it was.
The disk-before-memory commit ordering mirrors the intent of EncryptWallet, which already treats memory/disk divergence of key material as unacceptable.
Tested with wallet_tests/wallet_crypto_tests unit tests and the wallet_encryption.py functional test.
🤖 Generated with Claude Code