This PR cleans up the wallet upgrade mechanism a bit, fixes some probably bugs, and adds more test cases.
The nWalletMaxVersion
member variable has been removed as it made CanSupportFeature
unintuitive and was causing a couple of bugs. The reason this was introduced originally was to allow a wallet upgrade to only occur when the new feature is first used. While this makes sense for the old -upgradewallet
option, for an RPC, this does not quite make sense. It’s more intuitive for an upgrade to occur if possible if the upgradewallet
RPC is used as that’s an explicit request to upgrade a particular wallet to a newer version. nWalletMaxVersion
was only relevant for upgrades to FEATURE_WALLETCRYPT
and FEATURE_COMPRPUBKEY
both of which are incredibly old features. So for such wallets, the behavior of upgradewallet
will be that the feature is enabled immediately without the wallet needing to be encrypted at that time (note that FEATURE_WALLETCRYPT
indicates support for encryption, not that the wallet is encrypted) or for a new key to be generated.
CanSupportFeature
would previously indicate whether we could upgrade to nWalletMaxVersion
not just whether the current wallet version supported a feature. While this property was being used to determine whether we should upgrade to HD and HD chain split, it was also causing a few bugs. Determining whether we should upgrade to HD or HD chain split is resolved by passing into ScriptPubKeyMan::Upgrade
the version we are upgrading to and checking against that. By removing nWalletMaxVersion
we also fix a bug where you could upgrade to HD chain split without the pre-split keypool.
nWalletMaxVersion
was also the version that was being reported by getwalletinfo
which meant that the version reported was not always consistent across restarts as it depended on whether upgradewallet
was used. Additionally to make the wallet versions consistent with actually supported versions, instead of just setting the wallet version to whatever is given to upgradewallet
, we normalize the version number to the closest supported version number. For example, if given 150000, we would store and report 139900.
Another bug where CHDChain was not being upgraded to the version supporting HD chain split is also fixed by this PR.
Lastly several more tests have been added. Some refactoring to the test was made to make these tests easier. These tests check specific upgrading scenarios, such as from non-HD (version 60000) to HD to pre-split keypool. Although not specifically related to upgradewallet
, UpgradeKeyMetadata
is now being tested too.
Part of the new tests is checking that the wallet files are identical before and after failed upgrades. To facilitate this, a utility function sha256sum_file
has been added. Another part of the tests is to examine the wallet file itself to ensure that the records in the wallet.dat file have been correctly modified. So a new bdb.py
module has been added to deserialize the BDB db of the wallet.dat file. This format isn’t explicitly documented anywhere, but the code and comments in BDB’s source code in file dbinc/db_page.h
describe it. This module just dumps all of the fields into a dict.