aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2012-03-25 19:44:52 -0700
committerPieter Wuille <pieter.wuille@gmail.com>2012-03-25 19:44:52 -0700
commit01a196e08db49d83cf6c5abd8a799c56dcfef503 (patch)
tree6bedf33565483961f16bd7741d21549c22656485
parent59e659fcc08b622da08448018e507c2472ca2f1f (diff)
parent439e1497e130914c2b78eff20c38046d6b1b6d49 (diff)
downloadbitcoin-01a196e08db49d83cf6c5abd8a799c56dcfef503.tar.xz
Merge pull request #974 from sipa/walletupgrade
Introduce explicit -walletupgrade option
-rw-r--r--src/bitcoinrpc.cpp1
-rw-r--r--src/init.cpp31
-rw-r--r--src/wallet.cpp39
-rw-r--r--src/wallet.h36
4 files changed, 85 insertions, 22 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 874d19f69c..d8b9782e3e 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -336,6 +336,7 @@ Value getinfo(const Array& params, bool fHelp)
Object obj;
obj.push_back(Pair("version", (int)CLIENT_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("blocks", (int)nBestHeight));
obj.push_back(Pair("connections", (int)vNodes.size()));
diff --git a/src/init.cpp b/src/init.cpp
index 603022e1e0..4078b7e0cb 100644
--- a/src/init.cpp
+++ b/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" +
" -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" +
+ " -upgradewallet \t " + _("Upgrade wallet to latest format") + "\n" +
" -keypool=<n> \t " + _("Set key pool size to <n> (default: 100)") + "\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" +
@@ -380,6 +381,36 @@ bool AppInit2(int argc, char* argv[])
else
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(" wallet %15"PRI64d"ms\n", GetTimeMillis() - nStart);
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 30590c80e6..27ed7228df 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -17,7 +17,7 @@ using namespace std;
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();
CKey key;
@@ -25,7 +25,7 @@ std::vector<unsigned char> CWallet::GenerateNewKey()
// Compressed public keys were introduced in version 0.6.0
if (fCompressed)
- SetMinVersion(59900);
+ SetMinVersion(FEATURE_COMPRPUBKEY);
if (!AddKey(key))
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)
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;
+ if (nVersion > nWalletMaxVersion)
+ nWalletMaxVersion = nVersion;
+
if (fFileBacked)
{
CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
@@ -174,6 +181,17 @@ bool CWallet::SetMinVersion(int nVersion, CWalletDB* pwalletdbIn)
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)
{
if (IsCrypted())
@@ -228,7 +246,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
}
// Encryption was introduced in version 0.4.0
- SetMinVersion(40000, pwalletdbEncryption);
+ SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
if (fFileBacked)
{
@@ -1253,19 +1271,6 @@ int CWallet::LoadWallet(bool& fFirstRunRet)
return nLoadWalletRet;
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);
return DB_LOAD_OK;
}
diff --git a/src/wallet.h b/src/wallet.h
index fea3297788..6a6ee0c4ab 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -14,6 +14,16 @@ class CWalletTx;
class CReserveKey;
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
// transactions and balances, and provides the ability to create new
// transactions
@@ -25,8 +35,12 @@ private:
CWalletDB *pwalletdbEncryption;
+ // the current wallet version: clients below this version are not able to load the wallet
int nWalletVersion;
+ // the maxmimum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
+ int nWalletMaxVersion;
+
public:
mutable CCriticalSection cs_wallet;
@@ -42,14 +56,16 @@ public:
CWallet()
{
- nWalletVersion = 0;
+ nWalletVersion = FEATURE_BASE;
+ nWalletMaxVersion = FEATURE_BASE;
fFileBacked = false;
nMasterKeyMaxID = 0;
pwalletdbEncryption = NULL;
}
CWallet(std::string strWalletFileIn)
{
- nWalletVersion = 0;
+ nWalletVersion = FEATURE_BASE;
+ nWalletMaxVersion = FEATURE_BASE;
strWalletFile = strWalletFileIn;
fFileBacked = true;
nMasterKeyMaxID = 0;
@@ -65,6 +81,9 @@ public:
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
// Generate a new key
std::vector<unsigned char> GenerateNewKey();
@@ -73,12 +92,12 @@ public:
// Adds a key to the store, without saving it to disk (used by LoadWallet)
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.
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)
- 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 LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); }
@@ -216,7 +235,14 @@ public:
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; }
};