Compare commits

...

5 Commits

Author SHA1 Message Date
Gavin Andresen
1c15f88653 Only remove database log files on shutdown after wallet encryption/rewrite 2011-11-17 14:21:32 -05:00
Gavin Andresen
37971fcc76 Create new keypool for newly encrypted wallets. 2011-11-17 14:01:25 -05:00
Gavin Andresen
1b93ea0e31 Merge pull request #636 from gavinandresen/master
Fix crash-on-wallet-upgrade bug on OSX
2011-11-15 13:48:12 -08:00
Gavin Andresen
c4de918478 Tweak handling of boost filesystem versions 2011-11-15 14:30:24 -05:00
Gavin Andresen
8d0923109d Fix crash-on-osx-on-shutdown bug. And cleanup CDB handling in Rewrite. 2011-11-15 14:30:24 -05:00
6 changed files with 63 additions and 17 deletions

View File

@@ -256,7 +256,7 @@ windows:RC_FILE = src/qt/res/bitcoin-qt.rc
macx:HEADERS += src/qt/macdockiconhandler.h
macx:OBJECTIVE_SOURCES += src/qt/macdockiconhandler.mm
macx:LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0 BOOST_FILESYSTEM_VERSION=3
macx:DEFINES += MAC_OSX MSG_NOSIGNAL=0
macx:ICON = src/qt/res/icons/bitcoin.icns
macx:TARGET = "Bitcoin-Qt"

View File

@@ -28,13 +28,25 @@ DbEnv dbenv(0);
static map<string, int> mapFileUseCount;
static map<string, Db*> mapDb;
static void EnvShutdown(bool fRemoveLogFiles)
static bool fRemoveLogFiles = false;
void RemoveLogFilesOnShutdown(bool fIn)
{
fRemoveLogFiles = fIn;
}
static void EnvShutdown()
{
if (!fDbEnvInit)
return;
fDbEnvInit = false;
dbenv.close(0);
try
{
dbenv.close(0);
}
catch (const DbException& e)
{
printf("EnvShutdown exception: %s (%d)\n", e.what(), e.get_errno());
}
DbEnv(0).remove(GetDataDir().c_str(), 0);
if (fRemoveLogFiles)
@@ -44,7 +56,7 @@ static void EnvShutdown(bool fRemoveLogFiles)
while (it != filesystem::directory_iterator())
{
const filesystem::path& p = it->path();
#if BOOST_FILESYSTEM_VERSION == 3
#if BOOST_FILESYSTEM_VERSION >= 3
std::string f = p.filename().generic_string();
#else
std::string f = p.filename();
@@ -64,7 +76,7 @@ public:
}
~CDBInit()
{
EnvShutdown(false);
EnvShutdown();
}
}
instance_of_cdbinit;
@@ -229,7 +241,10 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
CDataStream ssValue;
int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT);
if (ret == DB_NOTFOUND)
{
pcursor->close();
break;
}
else if (ret != 0)
{
pcursor->close();
@@ -253,14 +268,11 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
}
if (fSuccess)
{
Db* pdb = mapDb[strFile];
if (pdb->close(0))
fSuccess = false;
db.Close();
CloseDb(strFile);
if (pdbCopy->close(0))
fSuccess = false;
delete pdb;
delete pdbCopy;
mapDb[strFile] = NULL;
}
if (fSuccess)
{
@@ -282,7 +294,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
}
void DBFlush(bool fShutdown, bool fRemoveLogFiles)
void DBFlush(bool fShutdown)
{
// Flush log data to the actual data file
// on all files that are not in use
@@ -315,7 +327,7 @@ void DBFlush(bool fShutdown, bool fRemoveLogFiles)
if (mapFileUseCount.empty())
{
dbenv.log_archive(&listp, DB_ARCH_REMOVE);
EnvShutdown(fRemoveLogFiles);
EnvShutdown();
}
}
}

View File

@@ -29,7 +29,8 @@ extern unsigned int nWalletDBUpdated;
extern DbEnv dbenv;
extern void DBFlush(bool fShutdown, bool fRemoveLogFiles);
extern void RemoveLogFilesOnShutdown(bool fRemoveLogFiles);
extern void DBFlush(bool fShutdown);
void ThreadFlushWalletDB(void* parg);
bool BackupWallet(const CWallet& wallet, const std::string& strDest);

View File

@@ -55,9 +55,9 @@ void Shutdown(void* parg)
{
fShutdown = true;
nTransactionsUpdated++;
DBFlush(false, false);
DBFlush(false);
StopNode();
DBFlush(true, true);
DBFlush(true);
boost::filesystem::remove(GetPidFile());
UnregisterWallet(pwalletMain);
delete pwalletMain;

View File

@@ -186,12 +186,15 @@ bool CWallet::EncryptWallet(const string& strWalletPassphrase)
pwalletdbEncryption = NULL;
}
Lock();
Unlock(strWalletPassphrase);
NewKeyPool();
Lock();
// Need to completely rewrite the wallet file; if we don't, bdb might keep
// bits of the unencrypted private key in slack space in the database file.
setKeyPool.clear();
CDB::Rewrite(strWalletFile, "\x04pool");
if (CDB::Rewrite(strWalletFile))
RemoveLogFilesOnShutdown(true);
}
return true;
@@ -1151,6 +1154,7 @@ int CWallet::LoadWallet(bool& fFirstRunRet)
{
if (CDB::Rewrite(strWalletFile, "\x04pool"))
{
RemoveLogFilesOnShutdown(true);
setKeyPool.clear();
// Note: can't top-up keypool here, because wallet is locked.
// User will be prompted to unlock wallet the next operation
@@ -1244,6 +1248,34 @@ bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
return true;
}
//
// Mark old keypool keys as used,
// and generate all new keys
//
bool CWallet::NewKeyPool()
{
CRITICAL_BLOCK(cs_wallet)
{
CWalletDB walletdb(strWalletFile);
BOOST_FOREACH(int64 nIndex, setKeyPool)
walletdb.ErasePool(nIndex);
setKeyPool.clear();
if (IsLocked())
return false;
int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
for (int i = 0; i < nKeys; i++)
{
int64 nIndex = i+1;
walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
setKeyPool.insert(nIndex);
}
printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
}
return true;
}
bool CWallet::TopUpKeyPool()
{
CRITICAL_BLOCK(cs_wallet)

View File

@@ -90,6 +90,7 @@ public:
std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
std::string SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
bool NewKeyPool();
bool TopUpKeyPool();
void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
void KeepKey(int64 nIndex);