mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 18:53:23 -03:00
Merge pull request #974 from sipa/walletupgrade
Introduce explicit -walletupgrade option
This commit is contained in:
commit
01a196e08d
4 changed files with 85 additions and 22 deletions
|
@ -336,6 +336,7 @@ Value getinfo(const Array& params, bool fHelp)
|
||||||
Object obj;
|
Object obj;
|
||||||
obj.push_back(Pair("version", (int)CLIENT_VERSION));
|
obj.push_back(Pair("version", (int)CLIENT_VERSION));
|
||||||
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
|
obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
|
||||||
|
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
|
||||||
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
|
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
|
||||||
obj.push_back(Pair("blocks", (int)nBestHeight));
|
obj.push_back(Pair("blocks", (int)nBestHeight));
|
||||||
obj.push_back(Pair("connections", (int)vNodes.size()));
|
obj.push_back(Pair("connections", (int)vNodes.size()));
|
||||||
|
|
31
src/init.cpp
31
src/init.cpp
|
@ -222,6 +222,7 @@ bool AppInit2(int argc, char* argv[])
|
||||||
" -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address") + "\n" +
|
" -rpcallowip=<ip> \t\t " + _("Allow JSON-RPC connections from specified IP address") + "\n" +
|
||||||
" -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" +
|
" -rpcconnect=<ip> \t " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" +
|
||||||
" -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" +
|
" -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" +
|
||||||
|
" -upgradewallet \t " + _("Upgrade wallet to latest format") + "\n" +
|
||||||
" -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)") + "\n" +
|
" -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)") + "\n" +
|
||||||
" -rescan \t " + _("Rescan the block chain for missing wallet transactions") + "\n" +
|
" -rescan \t " + _("Rescan the block chain for missing wallet transactions") + "\n" +
|
||||||
" -checkblocks=<n> \t\t " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" +
|
" -checkblocks=<n> \t\t " + _("How many blocks to check at startup (default: 2500, 0 = all)") + "\n" +
|
||||||
|
@ -380,6 +381,36 @@ bool AppInit2(int argc, char* argv[])
|
||||||
else
|
else
|
||||||
strErrors << _("Error loading wallet.dat") << "\n";
|
strErrors << _("Error loading wallet.dat") << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GetBoolArg("-upgradewallet", fFirstRun))
|
||||||
|
{
|
||||||
|
int nMaxVersion = GetArg("-upgradewallet", 0);
|
||||||
|
if (nMaxVersion == 0) // the -walletupgrade without argument case
|
||||||
|
{
|
||||||
|
printf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
|
||||||
|
nMaxVersion = CLIENT_VERSION;
|
||||||
|
pwalletMain->SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("Allowing wallet upgrade up to %i\n", nMaxVersion);
|
||||||
|
if (nMaxVersion < pwalletMain->GetVersion())
|
||||||
|
strErrors << _("Cannot downgrade wallet") << "\n";
|
||||||
|
pwalletMain->SetMaxVersion(nMaxVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fFirstRun)
|
||||||
|
{
|
||||||
|
// Create new keyUser and set as default key
|
||||||
|
RandAddSeedPerfmon();
|
||||||
|
|
||||||
|
std::vector<unsigned char> newDefaultKey;
|
||||||
|
if (!pwalletMain->GetKeyFromPool(newDefaultKey, false))
|
||||||
|
strErrors << _("Cannot initialize keypool") << "\n";
|
||||||
|
pwalletMain->SetDefaultKey(newDefaultKey);
|
||||||
|
if (!pwalletMain->SetAddressBookName(CBitcoinAddress(pwalletMain->vchDefaultKey), ""))
|
||||||
|
strErrors << _("Cannot write default address") << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
printf("%s", strErrors.str().c_str());
|
printf("%s", strErrors.str().c_str());
|
||||||
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
printf(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ using namespace std;
|
||||||
|
|
||||||
std::vector<unsigned char> CWallet::GenerateNewKey()
|
std::vector<unsigned char> CWallet::GenerateNewKey()
|
||||||
{
|
{
|
||||||
bool fCompressed = true; // default to compressed public keys
|
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
|
||||||
|
|
||||||
RandAddSeedPerfmon();
|
RandAddSeedPerfmon();
|
||||||
CKey key;
|
CKey key;
|
||||||
|
@ -25,7 +25,7 @@ std::vector<unsigned char> CWallet::GenerateNewKey()
|
||||||
|
|
||||||
// Compressed public keys were introduced in version 0.6.0
|
// Compressed public keys were introduced in version 0.6.0
|
||||||
if (fCompressed)
|
if (fCompressed)
|
||||||
SetMinVersion(59900);
|
SetMinVersion(FEATURE_COMPRPUBKEY);
|
||||||
|
|
||||||
if (!AddKey(key))
|
if (!AddKey(key))
|
||||||
throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
|
throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
|
||||||
|
@ -148,13 +148,20 @@ public:
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
bool CWallet::SetMinVersion(int nVersion, CWalletDB* pwalletdbIn)
|
bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
|
||||||
{
|
{
|
||||||
if (nWalletVersion >= nVersion)
|
if (nWalletVersion >= nVersion)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
|
||||||
|
if (fExplicit && nVersion > nWalletMaxVersion)
|
||||||
|
nVersion = FEATURE_LATEST;
|
||||||
|
|
||||||
nWalletVersion = nVersion;
|
nWalletVersion = nVersion;
|
||||||
|
|
||||||
|
if (nVersion > nWalletMaxVersion)
|
||||||
|
nWalletMaxVersion = nVersion;
|
||||||
|
|
||||||
if (fFileBacked)
|
if (fFileBacked)
|
||||||
{
|
{
|
||||||
CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
|
CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
|
||||||
|
@ -174,6 +181,17 @@ bool CWallet::SetMinVersion(int nVersion, CWalletDB* pwalletdbIn)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CWallet::SetMaxVersion(int nVersion)
|
||||||
|
{
|
||||||
|
// cannot downgrade below current version
|
||||||
|
if (nWalletVersion > nVersion)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nWalletMaxVersion = nVersion;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||||
{
|
{
|
||||||
if (IsCrypted())
|
if (IsCrypted())
|
||||||
|
@ -228,7 +246,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encryption was introduced in version 0.4.0
|
// Encryption was introduced in version 0.4.0
|
||||||
SetMinVersion(40000, pwalletdbEncryption);
|
SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
|
||||||
|
|
||||||
if (fFileBacked)
|
if (fFileBacked)
|
||||||
{
|
{
|
||||||
|
@ -1253,19 +1271,6 @@ int CWallet::LoadWallet(bool& fFirstRunRet)
|
||||||
return nLoadWalletRet;
|
return nLoadWalletRet;
|
||||||
fFirstRunRet = vchDefaultKey.empty();
|
fFirstRunRet = vchDefaultKey.empty();
|
||||||
|
|
||||||
if (!HaveKey(Hash160(vchDefaultKey)))
|
|
||||||
{
|
|
||||||
// Create new keyUser and set as default key
|
|
||||||
RandAddSeedPerfmon();
|
|
||||||
|
|
||||||
std::vector<unsigned char> newDefaultKey;
|
|
||||||
if (!GetKeyFromPool(newDefaultKey, false))
|
|
||||||
return DB_LOAD_FAIL;
|
|
||||||
SetDefaultKey(newDefaultKey);
|
|
||||||
if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
|
|
||||||
return DB_LOAD_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateThread(ThreadFlushWalletDB, &strWalletFile);
|
CreateThread(ThreadFlushWalletDB, &strWalletFile);
|
||||||
return DB_LOAD_OK;
|
return DB_LOAD_OK;
|
||||||
}
|
}
|
||||||
|
|
36
src/wallet.h
36
src/wallet.h
|
@ -14,6 +14,16 @@ class CWalletTx;
|
||||||
class CReserveKey;
|
class CReserveKey;
|
||||||
class CWalletDB;
|
class CWalletDB;
|
||||||
|
|
||||||
|
enum WalletFeature
|
||||||
|
{
|
||||||
|
FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output)
|
||||||
|
|
||||||
|
FEATURE_WALLETCRYPT = 40000, // wallet encryption
|
||||||
|
FEATURE_COMPRPUBKEY = 60000, // compressed public keys
|
||||||
|
|
||||||
|
FEATURE_LATEST = 60000
|
||||||
|
};
|
||||||
|
|
||||||
// A CWallet is an extension of a keystore, which also maintains a set of
|
// A CWallet is an extension of a keystore, which also maintains a set of
|
||||||
// transactions and balances, and provides the ability to create new
|
// transactions and balances, and provides the ability to create new
|
||||||
// transactions
|
// transactions
|
||||||
|
@ -25,8 +35,12 @@ private:
|
||||||
|
|
||||||
CWalletDB *pwalletdbEncryption;
|
CWalletDB *pwalletdbEncryption;
|
||||||
|
|
||||||
|
// the current wallet version: clients below this version are not able to load the wallet
|
||||||
int nWalletVersion;
|
int nWalletVersion;
|
||||||
|
|
||||||
|
// the maxmimum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
|
||||||
|
int nWalletMaxVersion;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mutable CCriticalSection cs_wallet;
|
mutable CCriticalSection cs_wallet;
|
||||||
|
|
||||||
|
@ -42,14 +56,16 @@ public:
|
||||||
|
|
||||||
CWallet()
|
CWallet()
|
||||||
{
|
{
|
||||||
nWalletVersion = 0;
|
nWalletVersion = FEATURE_BASE;
|
||||||
|
nWalletMaxVersion = FEATURE_BASE;
|
||||||
fFileBacked = false;
|
fFileBacked = false;
|
||||||
nMasterKeyMaxID = 0;
|
nMasterKeyMaxID = 0;
|
||||||
pwalletdbEncryption = NULL;
|
pwalletdbEncryption = NULL;
|
||||||
}
|
}
|
||||||
CWallet(std::string strWalletFileIn)
|
CWallet(std::string strWalletFileIn)
|
||||||
{
|
{
|
||||||
nWalletVersion = 0;
|
nWalletVersion = FEATURE_BASE;
|
||||||
|
nWalletMaxVersion = FEATURE_BASE;
|
||||||
strWalletFile = strWalletFileIn;
|
strWalletFile = strWalletFileIn;
|
||||||
fFileBacked = true;
|
fFileBacked = true;
|
||||||
nMasterKeyMaxID = 0;
|
nMasterKeyMaxID = 0;
|
||||||
|
@ -65,6 +81,9 @@ public:
|
||||||
|
|
||||||
std::vector<unsigned char> vchDefaultKey;
|
std::vector<unsigned char> vchDefaultKey;
|
||||||
|
|
||||||
|
// check whether we are allowed to upgrade (or already support) to the named feature
|
||||||
|
bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; }
|
||||||
|
|
||||||
// keystore implementation
|
// keystore implementation
|
||||||
// Generate a new key
|
// Generate a new key
|
||||||
std::vector<unsigned char> GenerateNewKey();
|
std::vector<unsigned char> GenerateNewKey();
|
||||||
|
@ -73,12 +92,12 @@ public:
|
||||||
// Adds a key to the store, without saving it to disk (used by LoadWallet)
|
// Adds a key to the store, without saving it to disk (used by LoadWallet)
|
||||||
bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
|
bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
|
||||||
|
|
||||||
bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; return true; }
|
bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
|
||||||
|
|
||||||
// Adds an encrypted key to the store, and saves it to disk.
|
// Adds an encrypted key to the store, and saves it to disk.
|
||||||
bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
|
||||||
// Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
|
// Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
|
||||||
bool LoadCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
|
bool LoadCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { SetMinVersion(FEATURE_WALLETCRYPT); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
|
||||||
bool AddCScript(const CScript& redeemScript);
|
bool AddCScript(const CScript& redeemScript);
|
||||||
bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); }
|
bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); }
|
||||||
|
|
||||||
|
@ -216,7 +235,14 @@ public:
|
||||||
|
|
||||||
bool SetDefaultKey(const std::vector<unsigned char> &vchPubKey);
|
bool SetDefaultKey(const std::vector<unsigned char> &vchPubKey);
|
||||||
|
|
||||||
bool SetMinVersion(int nVersion, CWalletDB* pwalletdbIn = NULL);
|
// signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
|
||||||
|
bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);
|
||||||
|
|
||||||
|
// change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
|
||||||
|
bool SetMaxVersion(int nVersion);
|
||||||
|
|
||||||
|
// get the current wallet format (the oldest client version guaranteed to understand this wallet)
|
||||||
|
int GetVersion() { return nWalletVersion; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue