aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bitcoinrpc.cpp26
-rw-r--r--src/db.cpp133
-rw-r--r--src/db.h5
-rw-r--r--src/init.cpp10
-rw-r--r--src/qt/askpassphrasedialog.cpp3
-rw-r--r--src/qt/bitcoingui.cpp6
-rw-r--r--src/qt/overviewpage.cpp2
-rw-r--r--src/qt/res/icons/address-book.pngbin1211 -> 1851 bytes
-rw-r--r--src/qt/res/icons/export.pngbin1339 -> 2148 bytes
-rw-r--r--src/qt/res/icons/history.pngbin746 -> 1432 bytes
-rw-r--r--src/qt/res/icons/key.pngbin1239 -> 1727 bytes
-rw-r--r--src/qt/res/icons/lock_closed.pngbin1237 -> 1679 bytes
-rw-r--r--src/qt/res/icons/lock_open.pngbin1442 -> 1644 bytes
-rw-r--r--src/qt/res/icons/overview.pngbin7015 -> 7936 bytes
-rw-r--r--src/qt/res/icons/receive.pngbin1815 -> 1437 bytes
-rw-r--r--src/qt/res/icons/send.pngbin1806 -> 1487 bytes
-rw-r--r--src/qt/res/icons/synced.pngbin698 -> 781 bytes
-rw-r--r--src/serialize.h2
-rw-r--r--src/wallet.cpp47
-rw-r--r--src/wallet.h1
20 files changed, 210 insertions, 25 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 6e2eac5a7e..2857b7575e 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -126,6 +126,7 @@ Value help(const Array& params, bool fHelp)
// We already filter duplicates, but these deprecated screw up the sort order
if (strMethod == "getamountreceived" ||
strMethod == "getallreceived" ||
+ strMethod == "getblocknumber" || // deprecated
(strMethod.find("label") != string::npos))
continue;
if (strCommand != "" && strMethod != strCommand)
@@ -160,10 +161,13 @@ Value stop(const Array& params, bool fHelp)
throw runtime_error(
"stop\n"
"Stop bitcoin server.");
-
+#ifndef QT_GUI
// Shutdown will take long enough that the response should get back
CreateThread(Shutdown, NULL);
return "bitcoin server stopping";
+#else
+ throw runtime_error("NYI: cannot shut down GUI with RPC command");
+#endif
}
@@ -178,12 +182,13 @@ Value getblockcount(const Array& params, bool fHelp)
}
+// deprecated
Value getblocknumber(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"getblocknumber\n"
- "Returns the block number of the latest block in the longest block chain.");
+ "Deprecated. Use getblockcount.");
return nBestHeight;
}
@@ -1554,6 +1559,11 @@ Value encryptwallet(const Array& params, bool fHelp)
if (pwalletMain->IsCrypted())
throw JSONRPCError(-15, "Error: running with an encrypted wallet, but encryptwallet was called.");
+#ifdef QT_GUI
+ // shutting down via RPC while the GUI is running does not work (yet):
+ throw runtime_error("Not Yet Implemented: use GUI to encrypt wallet, not RPC command");
+#endif
+
string strWalletPass;
strWalletPass.reserve(100);
mlock(&strWalletPass[0], strWalletPass.capacity());
@@ -1573,7 +1583,11 @@ Value encryptwallet(const Array& params, bool fHelp)
fill(strWalletPass.begin(), strWalletPass.end(), '\0');
munlock(&strWalletPass[0], strWalletPass.capacity());
- return Value::null;
+ // BDB seems to have a bad habit of writing old data into
+ // slack space in .dat files; that is bad if the old data is
+ // unencrypted private keys. So:
+ CreateThread(Shutdown, NULL);
+ return "wallet encrypted; bitcoin server stopping, restart to run with encrypted wallet";
}
@@ -1858,7 +1872,7 @@ string pAllowInSafeMode[] =
"help",
"stop",
"getblockcount",
- "getblocknumber",
+ "getblocknumber", // deprecated
"getconnectioncount",
"getdifficulty",
"getgenerate",
@@ -2175,11 +2189,13 @@ void ThreadRPCServer2(void* parg)
else if (mapArgs.count("-daemon"))
strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
PrintConsole(
- _("Warning: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
+ _("Error: %s, you must set rpcpassword=<password>\nin the configuration file: %s\n"
"If the file does not exist, create it with owner-readable-only file permissions.\n"),
strWhatAmI.c_str(),
GetConfigFile().c_str());
+#ifndef QT_GUI
CreateThread(Shutdown, NULL);
+#endif
return;
}
diff --git a/src/db.cpp b/src/db.cpp
index 7de1f8df9a..9ac93b3506 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -28,6 +28,23 @@ DbEnv dbenv(0);
static map<string, int> mapFileUseCount;
static map<string, Db*> mapDb;
+static void EnvShutdown()
+{
+ if (!fDbEnvInit)
+ return;
+
+ fDbEnvInit = false;
+ 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);
+}
+
class CDBInit
{
public:
@@ -36,11 +53,7 @@ public:
}
~CDBInit()
{
- if (fDbEnvInit)
- {
- dbenv.close(0);
- fDbEnvInit = false;
- }
+ EnvShutdown();
}
}
instance_of_cdbinit;
@@ -165,6 +178,101 @@ void static CloseDb(const string& strFile)
}
}
+bool CDB::Rewrite(const string& strFile, const char* pszSkip)
+{
+ while (!fShutdown)
+ {
+ CRITICAL_BLOCK(cs_db)
+ {
+ if (!mapFileUseCount.count(strFile) || mapFileUseCount[strFile] == 0)
+ {
+ // Flush log data to the dat file
+ CloseDb(strFile);
+ dbenv.txn_checkpoint(0, 0, 0);
+ dbenv.lsn_reset(strFile.c_str(), 0);
+ mapFileUseCount.erase(strFile);
+
+ bool fSuccess = true;
+ printf("Rewriting %s...\n", strFile.c_str());
+ string strFileRes = strFile + ".rewrite";
+ { // surround usage of db with extra {}
+ CDB db(strFile.c_str(), "r");
+ Db* pdbCopy = new Db(&dbenv, 0);
+
+ int ret = pdbCopy->open(NULL, // Txn pointer
+ strFileRes.c_str(), // Filename
+ "main", // Logical db name
+ DB_BTREE, // Database type
+ DB_CREATE, // Flags
+ 0);
+ if (ret > 0)
+ {
+ printf("Cannot create database file %s\n", strFileRes.c_str());
+ fSuccess = false;
+ }
+
+ Dbc* pcursor = db.GetCursor();
+ if (pcursor)
+ while (fSuccess)
+ {
+ CDataStream ssKey;
+ CDataStream ssValue;
+ int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT);
+ if (ret == DB_NOTFOUND)
+ {
+ pcursor->close();
+ break;
+ }
+ else if (ret != 0)
+ {
+ pcursor->close();
+ fSuccess = false;
+ break;
+ }
+ if (pszSkip &&
+ strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0)
+ continue;
+ if (strncmp(&ssKey[0], "\x07version", 8) == 0)
+ {
+ // Update version:
+ ssValue.clear();
+ ssValue << VERSION;
+ }
+ Dbt datKey(&ssKey[0], ssKey.size());
+ Dbt datValue(&ssValue[0], ssValue.size());
+ int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE);
+ if (ret2 > 0)
+ fSuccess = false;
+ }
+ if (fSuccess)
+ {
+ db.Close();
+ CloseDb(strFile);
+ if (pdbCopy->close(0))
+ fSuccess = false;
+ delete pdbCopy;
+ }
+ }
+ if (fSuccess)
+ {
+ Db dbA(&dbenv, 0);
+ if (dbA.remove(strFile.c_str(), NULL, 0))
+ fSuccess = false;
+ Db dbB(&dbenv, 0);
+ if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0))
+ fSuccess = false;
+ }
+ if (!fSuccess)
+ printf("Rewriting of %s FAILED!\n", strFileRes.c_str());
+ return fSuccess;
+ }
+ }
+ Sleep(100);
+ }
+ return false;
+}
+
+
void DBFlush(bool fShutdown)
{
// Flush log data to the actual data file
@@ -196,9 +304,10 @@ void DBFlush(bool fShutdown)
{
char** listp;
if (mapFileUseCount.empty())
+ {
dbenv.log_archive(&listp, DB_ARCH_REMOVE);
- dbenv.close(0);
- fDbEnvInit = false;
+ EnvShutdown();
+ }
}
}
}
@@ -656,6 +765,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
pwallet->vchDefaultKey.clear();
int nFileVersion = 0;
vector<uint256> vWalletUpgrade;
+ bool fIsEncrypted = false;
// Modify defaults
#ifndef WIN32
@@ -781,6 +891,7 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
ssValue >> vchPrivKey;
if (!pwallet->LoadCryptedKey(vchPubKey, vchPrivKey))
return DB_CORRUPT;
+ fIsEncrypted = true;
}
else if (strType == "defaultkey")
{
@@ -841,8 +952,11 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
printf("fUseUPnP = %d\n", fUseUPnP);
- // Upgrade
- if (nFileVersion < VERSION)
+ // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc:
+ if (fIsEncrypted && (nFileVersion == 40000 || nFileVersion == 50000))
+ return DB_NEED_REWRITE;
+
+ if (nFileVersion < VERSION) // Update
{
// Get rid of old debug.log file in current directory
if (nFileVersion <= 105 && !pszSetDataDir[0])
@@ -851,7 +965,6 @@ int CWalletDB::LoadWallet(CWallet* pwallet)
WriteVersion(VERSION);
}
-
return DB_LOAD_OK;
}
diff --git a/src/db.h b/src/db.h
index 73ea1902cc..15bfb29c8e 100644
--- a/src/db.h
+++ b/src/db.h
@@ -28,14 +28,12 @@ class CBlockLocator;
extern unsigned int nWalletDBUpdated;
extern DbEnv dbenv;
-
extern void DBFlush(bool fShutdown);
void ThreadFlushWalletDB(void* parg);
bool BackupWallet(const CWallet& wallet, const std::string& strDest);
-
class CDB
{
protected:
@@ -257,6 +255,8 @@ public:
{
return Write(std::string("version"), nVersion);
}
+
+ bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
};
@@ -349,6 +349,7 @@ enum DBErrors
DB_CORRUPT,
DB_TOO_NEW,
DB_LOAD_FAIL,
+ DB_NEED_REWRITE
};
class CWalletDB : public CDB
diff --git a/src/init.cpp b/src/init.cpp
index d6e153285e..a6d0ab56e3 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -44,8 +44,8 @@ void Shutdown(void* parg)
{
static CCriticalSection cs_Shutdown;
static bool fTaken;
- bool fFirstThread;
- CRITICAL_BLOCK(cs_Shutdown)
+ bool fFirstThread = false;
+ TRY_CRITICAL_BLOCK(cs_Shutdown)
{
fFirstThread = !fTaken;
fTaken = true;
@@ -362,6 +362,12 @@ bool AppInit2(int argc, char* argv[])
strErrors += _("Error loading wallet.dat: Wallet corrupted \n");
else if (nLoadWalletRet == DB_TOO_NEW)
strErrors += _("Error loading wallet.dat: Wallet requires newer version of Bitcoin \n");
+ else if (nLoadWalletRet == DB_NEED_REWRITE)
+ {
+ strErrors += _("Wallet needed to be rewritten: restart Bitcoin to complete \n");
+ wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR);
+ return false;
+ }
else
strErrors += _("Error loading wallet.dat \n");
}
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index 89cdf43ba4..a574ef925b 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -101,7 +101,8 @@ void AskPassphraseDialog::accept()
if(model->setWalletEncrypted(true, newpass1))
{
QMessageBox::warning(this, tr("Wallet encrypted"),
- tr("Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."));
+ tr("Bitcoin will close now to finish the encryption process. Remember that encrypting your wallet cannot fully protect your bitcoins from being stolen by malware infecting your computer."));
+ QApplication::quit();
}
else
{
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 5ae3ce33e8..8641c723b0 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -478,11 +478,11 @@ void BitcoinGUI::error(const QString &title, const QString &message)
void BitcoinGUI::changeEvent(QEvent *e)
{
#ifndef Q_WS_MAC // Ignored on Mac
- if (e->type() == QEvent::WindowStateChange)
+ if(e->type() == QEvent::WindowStateChange)
{
- if (clientModel->getOptionsModel()->getMinimizeToTray())
+ if(clientModel && clientModel->getOptionsModel()->getMinimizeToTray())
{
- if (isMinimized())
+ if(isMinimized())
{
hide();
e->ignore();
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index fe0987178c..5b5a8f5271 100644
--- a/src/qt/overviewpage.cpp
+++ b/src/qt/overviewpage.cpp
@@ -111,7 +111,7 @@ OverviewPage::OverviewPage(QWidget *parent) :
ui->labelNumTransactions->setToolTip(tr("Total number of transactions in wallet"));
// Recent transactions
- ui->listTransactions->setStyleSheet("background:transparent");
+ ui->listTransactions->setStyleSheet("QListView { background:transparent }");
ui->listTransactions->setItemDelegate(txdelegate);
ui->listTransactions->setIconSize(QSize(DECORATION_SIZE, DECORATION_SIZE));
ui->listTransactions->setSelectionMode(QAbstractItemView::NoSelection);
diff --git a/src/qt/res/icons/address-book.png b/src/qt/res/icons/address-book.png
index 1086fbeb63..dbfc28ab3d 100644
--- a/src/qt/res/icons/address-book.png
+++ b/src/qt/res/icons/address-book.png
Binary files differ
diff --git a/src/qt/res/icons/export.png b/src/qt/res/icons/export.png
index 69d59a38d2..1df9c2398d 100644
--- a/src/qt/res/icons/export.png
+++ b/src/qt/res/icons/export.png
Binary files differ
diff --git a/src/qt/res/icons/history.png b/src/qt/res/icons/history.png
index 60f1351783..10ac0e1592 100644
--- a/src/qt/res/icons/history.png
+++ b/src/qt/res/icons/history.png
Binary files differ
diff --git a/src/qt/res/icons/key.png b/src/qt/res/icons/key.png
index 757cad47ed..ece0164f77 100644
--- a/src/qt/res/icons/key.png
+++ b/src/qt/res/icons/key.png
Binary files differ
diff --git a/src/qt/res/icons/lock_closed.png b/src/qt/res/icons/lock_closed.png
index ce8da0bec7..c566510c40 100644
--- a/src/qt/res/icons/lock_closed.png
+++ b/src/qt/res/icons/lock_closed.png
Binary files differ
diff --git a/src/qt/res/icons/lock_open.png b/src/qt/res/icons/lock_open.png
index 6a3a8edb23..c98ca8663b 100644
--- a/src/qt/res/icons/lock_open.png
+++ b/src/qt/res/icons/lock_open.png
Binary files differ
diff --git a/src/qt/res/icons/overview.png b/src/qt/res/icons/overview.png
index 6b94b43a2c..3b90fe5569 100644
--- a/src/qt/res/icons/overview.png
+++ b/src/qt/res/icons/overview.png
Binary files differ
diff --git a/src/qt/res/icons/receive.png b/src/qt/res/icons/receive.png
index e8f418a4f8..53ad1d1565 100644
--- a/src/qt/res/icons/receive.png
+++ b/src/qt/res/icons/receive.png
Binary files differ
diff --git a/src/qt/res/icons/send.png b/src/qt/res/icons/send.png
index 55ce550b4f..ceb91ea66d 100644
--- a/src/qt/res/icons/send.png
+++ b/src/qt/res/icons/send.png
Binary files differ
diff --git a/src/qt/res/icons/synced.png b/src/qt/res/icons/synced.png
index 8e428b6a70..4d7e0e8821 100644
--- a/src/qt/res/icons/synced.png
+++ b/src/qt/res/icons/synced.png
Binary files differ
diff --git a/src/serialize.h b/src/serialize.h
index beb87f1d04..78cff43d53 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -60,7 +60,7 @@ class CDataStream;
class CAutoFile;
static const unsigned int MAX_SIZE = 0x02000000;
-static const int VERSION = 50000;
+static const int VERSION = 50100;
static const char* pszSubVer = "";
static const bool VERSION_IS_BETA = true;
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 64ee5c3b8c..af80cc16d5 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -187,6 +187,13 @@ bool CWallet::EncryptWallet(const string& strWalletPassphrase)
}
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.
+ CDB::Rewrite(strWalletFile);
}
return true;
@@ -1142,6 +1149,18 @@ int CWallet::LoadWallet(bool& fFirstRunRet)
return false;
fFirstRunRet = false;
int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
+ if (nLoadWalletRet == DB_NEED_REWRITE)
+ {
+ if (CDB::Rewrite(strWalletFile, "\x04pool"))
+ {
+ setKeyPool.clear();
+ // Note: can't top-up keypool here, because wallet is locked.
+ // User will be prompted to unlock wallet the next operation
+ // the requires a new key.
+ }
+ nLoadWalletRet = DB_NEED_REWRITE;
+ }
+
if (nLoadWalletRet != DB_LOAD_OK)
return nLoadWalletRet;
fFirstRunRet = vchDefaultKey.empty();
@@ -1227,6 +1246,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)
diff --git a/src/wallet.h b/src/wallet.h
index 03c4703fc0..19de803390 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -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);