aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bitcoin-qt.pro4
-rw-r--r--contrib/debian/changelog12
-rw-r--r--contrib/debian/copyright68
-rwxr-xr-xcontrib/qt_translations.py22
-rw-r--r--doc/assets-attribution.txt47
-rw-r--r--doc/release-process.txt106
-rw-r--r--share/setup.nsi6
-rw-r--r--src/bitcoinrpc.cpp20
-rw-r--r--src/db.cpp133
-rw-r--r--src/db.h5
-rw-r--r--src/init.cpp10
-rw-r--r--src/qt/aboutdialog.cpp5
-rw-r--r--src/qt/addressbookpage.cpp25
-rw-r--r--src/qt/addressbookpage.h2
-rw-r--r--src/qt/askpassphrasedialog.cpp5
-rw-r--r--src/qt/bitcoingui.cpp101
-rw-r--r--src/qt/csvmodelwriter.cpp6
-rw-r--r--src/qt/editaddressdialog.cpp4
-rw-r--r--src/qt/overviewpage.cpp38
-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/qt/sendcoinsdialog.cpp15
-rw-r--r--src/qt/sendcoinsentry.cpp6
-rw-r--r--src/qt/transactionview.cpp73
-rw-r--r--src/serialize.h2
-rw-r--r--src/wallet.cpp47
-rw-r--r--src/wallet.h1
35 files changed, 497 insertions, 266 deletions
diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro
index a8f6b2d86c..7444ff4ac1 100644
--- a/bitcoin-qt.pro
+++ b/bitcoin-qt.pro
@@ -1,6 +1,6 @@
TEMPLATE = app
TARGET =
-VERSION = 0.5.0
+VERSION = 0.5.1
INCLUDEPATH += src src/json src/qt
DEFINES += QT_GUI BOOST_THREAD_USE_LIB
CONFIG += no_include_pwd
@@ -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"
diff --git a/contrib/debian/changelog b/contrib/debian/changelog
index ccde9776d8..6355141036 100644
--- a/contrib/debian/changelog
+++ b/contrib/debian/changelog
@@ -1,3 +1,15 @@
+bitcoin (0.5.0-natty0) natty; urgency=low
+
+ * New upstream release.
+
+ -- Matt Corallo <matt@bluematt.me> Mon, 21 Nov 2011 11:32:00 -0500
+
+bitcoin (0.5.0~rc7-natty0) natty; urgency=low
+
+ * New upstream release candidate.
+
+ -- Matt Corallo <matt@bluematt.me> Sun, 20 Nov 2011 17:08:00 -0500
+
bitcoin (0.5.0~rc3-natty0) natty; urgency=low
* New upstream release candidate.
diff --git a/contrib/debian/copyright b/contrib/debian/copyright
index 546ffc6e1f..5db418df3a 100644
--- a/contrib/debian/copyright
+++ b/contrib/debian/copyright
@@ -31,21 +31,23 @@ License: GPL-3+
Files: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png,
src/qt/res/src/*.svg
Copyright: Wladimir van der Laan
-License: CC-BY-3
-
-Files: src/qt/res/icons/send.png
-Copyright: Icons Land
-License: Freeware Non-commercial
-Comment: Icon Pack: Vista Style Arrow
- Site: http://findicons.com/icon/231371/right3green
+License: Expat
-Files: src/qt/res/icons/address-book.png
-Copyright: FatCow Web Hosting
-License: CC-BY-3
-Comment: Icon Pack: Farm-Fresh Web
- Site: http://findicons.com/icon/163938/book_open
+Files: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png,
+ src/qt/res/icons/history.png, src/qt/res/icons/key.png,
+ src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png,
+ src/qt/res/icons/receive.png, src/qt/res/icons/send.png,
+ src/qt/res/icons/synced.png
+Copyright: David Vignoni (david@icon-king.com)
+ ICON KING - www.icon-king.com
+License: LGPL
+Comment: NUVOLA ICON THEME for KDE 3.x
+ Original icons: kaddressbook, klipper_dock, view-list-text,
+ key-password, encrypted/decrypted, go-home, go-down,
+ go-next, dialog-ok
+ Site: http://www.icon-king.com/projects/nuvola/
-Files: src/qt/res/icons/connect*.png, src/qt/res/icons/synced.png, src/qt/res/icons/lock_*.png
+Files: src/qt/res/icons/connect*.png
Copyright: schollidesign
License: GPL-3+
Comment: Icon Pack: Human-O2
@@ -65,24 +67,11 @@ Copyright: http://www.everaldo.com
License: LGPL
Comment: Icon Pack: Crystal SVG
-Files: src/qt/res/icons/receive.png, src/qt/res/icons/history.png,
- src/qt/res/icons/export.png
-Copyright: Oxygen team
-License: CC-BY-SA-3
-Comment: Icon Pack: Oxygen
- Site: http://www.oxygen-icons.org/
-
Files: src/qt/res/icons/bitcoin.png, src/qt/res/icons/toolbar.png
Copyright: Bitboy (optimized for 16x16 by Wladimir van der Laan)
License: PUB-DOM
Comment: Site: http://forum.bitcoin.org/?topic=1756.0
-Files: src/qt/res/icons/overview.png
-Copyright: Jack Cai
-License: CC-BY-ND-3
-Comment: Icon Pack: Primo
- Site: http://findicons.com/icon/175944/home?id=176221#
-
Files: scripts/img/reload.xcf, src/qt/res/movies/update_spinner.mng
Copyright: Everaldo (Everaldo Coelho)
License: GPL-3+
@@ -94,12 +83,6 @@ License: PUB-DOM
Copyright: Crobbo (forum)
Comment: Site: https://bitcointalk.org/index.php?topic=32273.0
-Files: src/qt/res/icons/key.png
-Copyright: VisualPharm (Ivan Boyko)
-License: CC-BY-3
-Comment: Icon Pack: Must Have
- Site: http://findicons.com/icon/51009/key?id=51009
-
License: Expat
Permission is hereby granted, free of charge, to any person obtaining a
@@ -163,27 +146,6 @@ Comment:
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
-License: CC-BY-3
- This work is licensed under a Creative Commons Attribution 3.0 Unported
- License.
-Comment:
- You can get a full copy of the license at
- <http://creativecommons.org/licenses/by/3.0/>.
-
-License: CC-BY-ND-3
- This work is licensed under a Creative Commons Attribution-NoDerivs 3.0
- Unported License.
-Comment:
- You can get a full copy of the license at
- <http://creativecommons.org/licenses/by-nd/3.0/>.
-
-License: CC-BY-ND-3
- This work is licensed under a Creative Commons Attribution-ShareAlike
- 3.0 Unported License.
-Comment:
- You can get a full copy of the license at
- <http://creativecommons.org/licenses/by-sa/3.0/>.
-
License: LGPL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/contrib/qt_translations.py b/contrib/qt_translations.py
new file mode 100755
index 0000000000..fd8a8b7129
--- /dev/null
+++ b/contrib/qt_translations.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+# Helpful little script that spits out a comma-separated list of
+# language codes for Qt icons that should be included
+# in binary bitcoin distributions
+
+import glob
+import os
+import re
+import sys
+
+if len(sys.argv) != 3:
+ sys.exit("Usage: %s $QTDIR/translations $BITCOINDIR/src/qt/locale"%sys.argv[0])
+
+d1 = sys.argv[1]
+d2 = sys.argv[2]
+
+l1 = set([ re.search(r'qt_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d1, 'qt_*.qm')) ])
+l2 = set([ re.search(r'bitcoin_(.*).qm', f).group(1) for f in glob.glob(os.path.join(d2, 'bitcoin_*.qm')) ])
+
+print ",".join(sorted(l1.intersection(l2)))
+
diff --git a/doc/assets-attribution.txt b/doc/assets-attribution.txt
index 91d2e65804..5cf0a734bf 100644
--- a/doc/assets-attribution.txt
+++ b/doc/assets-attribution.txt
@@ -1,21 +1,20 @@
Icon: src/qt/res/icons/clock*.png, src/qt/res/icons/tx*.png,
src/qt/res/src/*.svg
Designer: Wladimir van der Laan
-License: Creative Commons Attribution
-
-Icon: src/qt/res/icons/send.png
-Icon Pack: Vista Style Arrow
-Designer: Icons Land
-License: Freeware Non-commercial
-Site: http://findicons.com/icon/231371/right3green
-
-Icon: src/qt/res/icons/address-book.png
-Icon Pack: Farm-Fresh Web
-Designer: FatCow Web Hosting
-License: Creative Commons Attribution (by)
-Site: http://findicons.com/icon/163938/book_open
+License: MIT
+
+Icon: src/qt/res/icons/address-book.png, src/qt/res/icons/export.png,
+ src/qt/res/icons/history.png, src/qt/res/icons/key.png,
+ src/qt/res/icons/lock_*.png, src/qt/res/icons/overview.png,
+ src/qt/res/icons/receive.png, src/qt/res/icons/send.png,
+ src/qt/res/icons/synced.png
+Icon Pack: NUVOLA ICON THEME for KDE 3.x
+Designer: David Vignoni (david@icon-king.com)
+ ICON KING - www.icon-king.com
+License: LGPL
+Site: http://www.icon-king.com/projects/nuvola/
-Icon: src/qt/res/icons/connect*.png, src/qt/res/icons/synced.png, src/qt/res/icons/lock_*.png
+Icon: src/qt/res/icons/connect*.png
Icon Pack: Human-O2
Designer: schollidesign
License: GNU/GPL
@@ -35,24 +34,11 @@ Designer: http://www.everaldo.com
Icon Pack: Crystal SVG
License: LGPL
-Icon: src/qt/res/icons/receive.png, src/qt/res/icons/history.png,
- src/qt/res/icons/export.png
-Designer: Oxygen team
-Icon Pack: Oxygen
-License: Creative Common Attribution-ShareAlike 3.0 License or LGPL
-Site: http://www.oxygen-icons.org/
-
Icon: src/qt/res/icons/bitcoin.png, src/qt/res/icons/toolbar.png
Designer: Bitboy (optimized for 16x16 by Wladimir van der Laan)
License: Public Domain
Site: http://forum.bitcoin.org/?topic=1756.0
-Icon: src/qt/res/icons/overview.png
-Icon Pack: Primo
-Designer: Jack Cai
-License: Creative Commons Attribution No Derivatives (by-nd)
-Site: http://findicons.com/icon/175944/home?id=176221#
-
Icon: scripts/img/reload.xcf (modified),src/qt/res/movies/update_spinner.mng
Icon Pack: Kids
Designer: Everaldo (Everaldo Coelho)
@@ -64,10 +50,3 @@ Designer: Crobbo (forum)
Site: https://bitcointalk.org/index.php?topic=32273.0
License: Public domain
-Icon: src/qt/res/icons/key.png
-Designer: VisualPharm (Ivan Boyko)
-Icon Pack: Must Have
-Site: http://findicons.com/icon/51009/key?id=51009
-License: Creative Commons Attribution (by)
-
-
diff --git a/doc/release-process.txt b/doc/release-process.txt
index 27e2cf5b93..ac388847c2 100644
--- a/doc/release-process.txt
+++ b/doc/release-process.txt
@@ -1,31 +1,21 @@
* update (commit) version in sources
+ bitcoin-qt.pro
src/serialize.h
share/setup.nsi
-* update (commit) version in OSX app bundle
- contrib/Bitcoin.app/Contents/Info.plist
-
- * CFBundleShortVersionString should have value like 0.5.0
- * CFBundleVersion should have value like 500
-
* tag version in git
- git tag -a v0.5.0
+ git tag -a v0.5.1
* write release notes. git shortlog helps a lot:
- git shortlog --no-merges v0.4.0..
-
-* create source-only archive
-
- git archive --format=tar --prefix=bitcoin-0.5.0/ HEAD | \
- gzip -9c > ~/tmp/bitcoin-0.5.0-src.tar.gz
+ git shortlog --no-merges v0.5.0..
* perform gitian builds
* From a directory containing the bitcoin source, gitian-builder and gitian.sigs
export SIGNER=(your gitian key, ie bluematt, sipa, etc)
- export VERSION=0.5.0
+ export VERSION=0.5.1
cd ./gitian-builder
* Fetch and build inputs:
@@ -42,36 +32,36 @@
cp build/out/qt-win32-4.7.4-gitian.zip inputs/
* Build bitcoind and bitcoin-qt on Linux32, Linux64, and Win32:
- ./bin/gbuild --commit bitcoin=v$VERSION ../bitcoin/contrib/gitian-descriptors/gitian.yml
- ./bin/gsign --signer $SIGNER --release $VERSION --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian.yml
+ ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian.yml
+ ./bin/gsign --signer $SIGNER --release ${VERSION} --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian.yml
pushd build/out
- zip -r bitcoin-$VERSION-linux-gitian.zip *
- mv bitcoin-$VERSION-linux-gitian.zip ../../
+ zip -r bitcoin-${VERSION}-linux-gitian.zip *
+ mv bitcoin-${VERSION}-linux-gitian.zip ../../
popd
- ./bin/gbuild --commit bitcoin=v$VERSION ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
- ./bin/gsign --signer $SIGNER --release $VERSION-win32 --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
+ ./bin/gbuild --commit bitcoin=v${VERSION} ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
+ ./bin/gsign --signer $SIGNER --release ${VERSION}-win32 --destination ../gitian.sigs/ ../bitcoin/contrib/gitian-descriptors/gitian-win32.yml
pushd build/out
- zip -r bitcoin-$VERSION-win32-gitian.zip *
- mv bitcoin-$VERSION-win32-gitian.zip ../../
+ zip -r bitcoin-${VERSION}-win32-gitian.zip *
+ mv bitcoin-${VERSION}-win32-gitian.zip ../../
popd
Build output expected:
- 1. linux 32-bit and 64-bit binaries + source (bitcoin-$VERSION-linux-gitian.zip)
- 2. windows 32-bit binary, installer + source (bitcoin-$VERSION-win32-gitian.zip)
- 3. Gitian signatures (in gitian.sigs/$VERSION[-win32]/(your gitian key)/
+ 1. linux 32-bit and 64-bit binaries + source (bitcoin-${VERSION}-linux-gitian.zip)
+ 2. windows 32-bit binary, installer + source (bitcoin-${VERSION}-win32-gitian.zip)
+ 3. Gitian signatures (in gitian.sigs/${VERSION}[-win32]/(your gitian key)/
* repackage gitian builds for release as stand-alone zip/tar/installer exe
* Linux .tar.gz:
- unzip bitcoin-$VERSION-linux-gitian.zip -d bitcoin-$VERSION-linux
- tar czvf bitcoin-$VERSION-linux.tar.gz bitcoin-$VERSION-linux
- rm -rf bitcoin-$VERSION-linux
+ unzip bitcoin-${VERSION}-linux-gitian.zip -d bitcoin-${VERSION}-linux
+ tar czvf bitcoin-${VERSION}-linux.tar.gz bitcoin-${VERSION}-linux
+ rm -rf bitcoin-${VERSION}-linux
* Windows .zip and setup.exe:
- unzip bitcoin-$VERSION-win32-gitian.zip -d bitcoin-$VERSION-win32
- mv bitcoin-$VERSION-win32/bitcoin-*-setup.exe .
- zip -r bitcoin-$VERSION-win32.zip bitcoin-$VERSION-win32
- rm -rf bitcoin-$VERSION-win32
+ unzip bitcoin-${VERSION}-win32-gitian.zip -d bitcoin-${VERSION}-win32
+ mv bitcoin-${VERSION}-win32/bitcoin-*-setup.exe .
+ zip -r bitcoin-${VERSION}-win32.zip bitcoin-${VERSION}-win32
+ rm -rf bitcoin-${VERSION}-win32
* perform Mac build
See this blog post for how Gavin set up his build environment and
@@ -80,7 +70,8 @@
qmake USE_SSL=1 USE_UPNP=1 bitcoin-qt.pro
make
export QTDIR=/opt/local/share/qt4 # needed to find translations/qt_*.qm files
- contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr de,es,ru -dmg -fancy contrib/macdeploy/fancy.plist
+ T=$(contrib/qt_translations.py $QTDIR/translations src/qt/locale)
+ contrib/macdeploy/macdeployqtplus Bitcoin-Qt.app -add-qt-tr $T -dmg -fancy contrib/macdeploy/fancy.plist
Build output expected:
Bitcoin-Qt.dmg
@@ -93,36 +84,45 @@
* update forum version
-* update wiki
-
* update wiki download links
-* release gitian-signed gitian archives
+* Commit your signature to gitian.sigs:
+ pushd gitian.sigs
+ git add ${VERSION}/${SIGNER}
+ git add ${VERSION}-win32/${SIGNER}
+ git commit -a
+ git push # Assuming you can push to the gitian.sigs tree
+ popd
- * Collect enough gitian signatures to meet minimum_weight (see contrib/gitian-downloader/*-download-config)
+-------------------------------------------------------------------------
+
+* After 3 or more people have gitian-built, repackage gitian-signed zips:
* From a directory containing bitcoin source, gitian.sigs and gitian zips
- export VERSION=0.5.0
- mkdir bitcoin-$VERSION-linux-gitian; cd bitcoin-$VERSION-linux-gitian
- unzip ../bitcoin-$VERSION-linux-gitian.zip
+ export VERSION=0.5.1
+ mkdir bitcoin-${VERSION}-linux-gitian
+ pushd bitcoin-${VERSION}-linux-gitian
+ unzip ../bitcoin-${VERSION}-linux-gitian.zip
mkdir gitian
cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/
- for file in `ls ../gitian.sigs/$VERSION/`; do
- cp ../gitian.sigs/$VERSION/$file/bitcoin-build.assert ./gitian/$file-build.assert
- cp ../gitian.sigs/$VERSION/$file/bitcoin-build.assert.sig ./gitian/$file-build.assert.sig
+ for signer in $(ls ../gitian.sigs/${VERSION}/); do
+ cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert
+ cp ../gitian.sigs/${VERSION}/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig
done
- zip -r bitcoin-$VERSION-linux-gitian.zip *
- cp bitcoin-$VERSION-linux-gitian.zip ../
- cd ..
- mkdir bitcoin-$VERSION-linux-gitian; cd bitcoin-$VERSION-linux-gitian
- unzip ../bitcoin-$VERSION-linux-gitian.zip
+ zip -r bitcoin-${VERSION}-linux-gitian.zip *
+ cp bitcoin-${VERSION}-linux-gitian.zip ../
+ popd
+ mkdir bitcoin-${VERSION}-win32-gitian
+ pushd bitcoin-${VERSION}-win32-gitian
+ unzip ../bitcoin-${VERSION}-win32-gitian.zip
mkdir gitian
cp ../bitcoin/contrib/gitian-downloader/*.pgp ./gitian/
- for file in `ls ../gitian.sigs/$VERSION/`; do
- cp ../gitian.sigs/$VERSION/$file/bitcoin-build.assert ./gitian/$file-build.assert
- cp ../gitian.sigs/$VERSION/$file/bitcoin-build.assert.sig ./gitian/$file-build.assert.sig
+ for signer in $(ls ../gitian.sigs/${VERSION}-win32/); do
+ cp ../gitian.sigs/${VERSION}-win32/${signer}/bitcoin-build.assert ./gitian/${signer}-build.assert
+ cp ../gitian.sigs/${VERSION}-win32/${signer}/bitcoin-build.assert.sig ./gitian/${signer}-build.assert.sig
done
- zip -r bitcoin-$VERSION-linux-gitian.zip *
- cp bitcoin-$VERSION-linux-gitian.zip ../
+ zip -r bitcoin-${VERSION}-win32-gitian.zip *
+ cp bitcoin-${VERSION}-win32-gitian.zip ../
+ popd
* Upload gitian zips to SourceForge
diff --git a/share/setup.nsi b/share/setup.nsi
index 19f5a5329b..0c0fa048af 100644
--- a/share/setup.nsi
+++ b/share/setup.nsi
@@ -5,7 +5,7 @@ SetCompressor /SOLID lzma
# General Symbol Definitions
!define REGKEY "SOFTWARE\$(^Name)"
-!define VERSION 0.5.0
+!define VERSION 0.5.1
!define COMPANY "Bitcoin project"
!define URL http://www.bitcoin.org/
@@ -45,13 +45,13 @@ Var StartMenuGroup
!insertmacro MUI_LANGUAGE English
# Installer attributes
-OutFile bitcoin-0.5.0-win32-setup.exe
+OutFile bitcoin-0.5.1-win32-setup.exe
InstallDir $PROGRAMFILES\Bitcoin
CRCCheck on
XPStyle on
BrandingText " "
ShowInstDetails show
-VIProductVersion 0.5.0.0
+VIProductVersion 0.5.1.0
VIAddVersionKey ProductName Bitcoin
VIAddVersionKey ProductVersion "${VERSION}"
VIAddVersionKey CompanyName "${COMPANY}"
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index a7ffe14e0c..2857b7575e 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -161,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
}
@@ -1556,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());
@@ -1575,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";
}
@@ -2177,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/aboutdialog.cpp b/src/qt/aboutdialog.cpp
index 13d263b75c..a3aa6de841 100644
--- a/src/qt/aboutdialog.cpp
+++ b/src/qt/aboutdialog.cpp
@@ -12,7 +12,10 @@ AboutDialog::AboutDialog(QWidget *parent) :
void AboutDialog::setModel(ClientModel *model)
{
- ui->versionLabel->setText(model->formatFullVersion());
+ if(model)
+ {
+ ui->versionLabel->setText(model->formatFullVersion());
+ }
}
AboutDialog::~AboutDialog()
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index 6be59a082f..0a147c9e10 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -57,6 +57,8 @@ AddressBookPage::~AddressBookPage()
void AddressBookPage::setModel(AddressTableModel *model)
{
this->model = model;
+ if(!model)
+ return;
// Refresh list from core
model->updateList();
@@ -96,16 +98,13 @@ void AddressBookPage::setModel(AddressTableModel *model)
selectionChanged();
}
-QTableView *AddressBookPage::getCurrentTable()
-{
- return ui->tableView;
-}
-
void AddressBookPage::on_copyToClipboard_clicked()
{
// Copy currently selected address to clipboard
// (or nothing, if nothing selected)
- QTableView *table = getCurrentTable();
+ QTableView *table = ui->tableView;
+ if(!table->selectionModel())
+ return;
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
foreach (QModelIndex index, indexes)
@@ -117,6 +116,8 @@ void AddressBookPage::on_copyToClipboard_clicked()
void AddressBookPage::on_newAddressButton_clicked()
{
+ if(!model)
+ return;
EditAddressDialog dlg(
tab == SendingTab ?
EditAddressDialog::NewSendingAddress :
@@ -139,7 +140,9 @@ void AddressBookPage::on_newAddressButton_clicked()
void AddressBookPage::on_deleteButton_clicked()
{
- QTableView *table = getCurrentTable();
+ QTableView *table = ui->tableView;
+ if(!table->selectionModel())
+ return;
QModelIndexList indexes = table->selectionModel()->selectedRows();
if(!indexes.isEmpty())
{
@@ -150,7 +153,9 @@ void AddressBookPage::on_deleteButton_clicked()
void AddressBookPage::selectionChanged()
{
// Set button states based on selected tab and selection
- QTableView *table = getCurrentTable();
+ QTableView *table = ui->tableView;
+ if(!table->selectionModel())
+ return;
if(table->selectionModel()->hasSelection())
{
@@ -174,12 +179,14 @@ void AddressBookPage::selectionChanged()
void AddressBookPage::done(int retval)
{
+ QTableView *table = ui->tableView;
+ if(!table->selectionModel() || !table->model())
+ return;
// When this is a tab/widget and not a model dialog, ignore "done"
if(mode == ForEditing)
return;
// Figure out which address was selected, and return it
- QTableView *table = getCurrentTable();
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
foreach (QModelIndex index, indexes)
diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h
index 53c7728c8c..ef64d17539 100644
--- a/src/qt/addressbookpage.h
+++ b/src/qt/addressbookpage.h
@@ -47,8 +47,6 @@ private:
QString returnValue;
QSortFilterProxyModel *proxyModel;
- QTableView *getCurrentTable();
-
private slots:
void on_deleteButton_clicked();
void on_newAddressButton_clicked();
diff --git a/src/qt/askpassphrasedialog.cpp b/src/qt/askpassphrasedialog.cpp
index a297513a62..a574ef925b 100644
--- a/src/qt/askpassphrasedialog.cpp
+++ b/src/qt/askpassphrasedialog.cpp
@@ -72,6 +72,8 @@ void AskPassphraseDialog::setModel(WalletModel *model)
void AskPassphraseDialog::accept()
{
std::string oldpass, newpass1, newpass2;
+ if(!model)
+ return;
// TODO: mlock memory / munlock on return so they will not be swapped out, really need "mlockedstring" wrapper class to do this safely
oldpass.reserve(MAX_PASSPHRASE_SIZE);
newpass1.reserve(MAX_PASSPHRASE_SIZE);
@@ -99,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 b9995fdd62..8641c723b0 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -267,58 +267,62 @@ void BitcoinGUI::createToolBars()
void BitcoinGUI::setClientModel(ClientModel *clientModel)
{
this->clientModel = clientModel;
-
- if(clientModel->isTestNet())
+ if(clientModel)
{
- QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]");
- setWindowTitle(title_testnet);
+ if(clientModel->isTestNet())
+ {
+ QString title_testnet = windowTitle() + QString(" ") + tr("[testnet]");
+ setWindowTitle(title_testnet);
#ifndef Q_WS_MAC
- setWindowIcon(QIcon(":icons/bitcoin_testnet"));
+ setWindowIcon(QIcon(":icons/bitcoin_testnet"));
#else
- MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
+ MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
#endif
- if(trayIcon)
- {
- trayIcon->setToolTip(title_testnet);
- trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
+ if(trayIcon)
+ {
+ trayIcon->setToolTip(title_testnet);
+ trayIcon->setIcon(QIcon(":/icons/toolbar_testnet"));
+ }
}
- }
- // Keep up to date with client
- setNumConnections(clientModel->getNumConnections());
- connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
+ // Keep up to date with client
+ setNumConnections(clientModel->getNumConnections());
+ connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
- setNumBlocks(clientModel->getNumBlocks());
- connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));
+ setNumBlocks(clientModel->getNumBlocks());
+ connect(clientModel, SIGNAL(numBlocksChanged(int)), this, SLOT(setNumBlocks(int)));
- // Report errors from network/worker thread
- connect(clientModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
+ // Report errors from network/worker thread
+ connect(clientModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
+ }
}
void BitcoinGUI::setWalletModel(WalletModel *walletModel)
{
this->walletModel = walletModel;
+ if(walletModel)
+ {
+ // Report errors from wallet thread
+ connect(walletModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
- // Report errors from wallet thread
- connect(walletModel, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
-
- // Put transaction list in tabs
- transactionView->setModel(walletModel);
+ // Put transaction list in tabs
+ transactionView->setModel(walletModel);
- overviewPage->setModel(walletModel);
- addressBookPage->setModel(walletModel->getAddressTableModel());
- receiveCoinsPage->setModel(walletModel->getAddressTableModel());
- sendCoinsPage->setModel(walletModel);
+ overviewPage->setModel(walletModel);
+ addressBookPage->setModel(walletModel->getAddressTableModel());
+ receiveCoinsPage->setModel(walletModel->getAddressTableModel());
+ sendCoinsPage->setModel(walletModel);
- setEncryptionStatus(walletModel->getEncryptionStatus());
- connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int)));
+ setEncryptionStatus(walletModel->getEncryptionStatus());
+ connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int)));
- // Balloon popup for new transaction
- connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(incomingTransaction(QModelIndex,int,int)));
+ // Balloon popup for new transaction
+ connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(incomingTransaction(QModelIndex,int,int)));
- // Ask for passphrase if needed
- connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));
+ // Ask for passphrase if needed
+ connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));
+ }
}
void BitcoinGUI::createTrayIcon()
@@ -369,6 +373,8 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
void BitcoinGUI::optionsClicked()
{
+ if(!clientModel || !clientModel->getOptionsModel())
+ return;
OptionsDialog dlg;
dlg.setModel(clientModel->getOptionsModel());
dlg.exec();
@@ -398,6 +404,8 @@ void BitcoinGUI::setNumConnections(int count)
void BitcoinGUI::setNumBlocks(int count)
{
+ if(!clientModel)
+ return;
int initTotal = clientModel->getNumBlocksAtStartup();
int total = clientModel->getNumBlocksOfPeers();
QString tooltip;
@@ -470,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();
@@ -492,13 +500,16 @@ void BitcoinGUI::changeEvent(QEvent *e)
void BitcoinGUI::closeEvent(QCloseEvent *event)
{
-#ifndef Q_WS_MAC // Ignored on Mac
- if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
- !clientModel->getOptionsModel()->getMinimizeOnClose())
+ if(clientModel)
{
- qApp->quit();
- }
+#ifndef Q_WS_MAC // Ignored on Mac
+ if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
+ !clientModel->getOptionsModel()->getMinimizeOnClose())
+ {
+ qApp->quit();
+ }
#endif
+ }
QMainWindow::closeEvent(event);
}
@@ -517,6 +528,8 @@ void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee)
void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int end)
{
+ if(!walletModel || !clientModel)
+ return;
TransactionTableModel *ttm = walletModel->getTransactionTableModel();
qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
.data(Qt::EditRole).toULongLong();
@@ -654,6 +667,8 @@ void BitcoinGUI::setEncryptionStatus(int status)
void BitcoinGUI::encryptWallet(bool status)
{
+ if(!walletModel)
+ return;
AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt:
AskPassphraseDialog::Decrypt, this);
dlg.setModel(walletModel);
@@ -671,6 +686,8 @@ void BitcoinGUI::changePassphrase()
void BitcoinGUI::unlockWallet()
{
+ if(!walletModel)
+ return;
// Unlock wallet when requested by wallet model
if(walletModel->getEncryptionStatus() == WalletModel::Locked)
{
diff --git a/src/qt/csvmodelwriter.cpp b/src/qt/csvmodelwriter.cpp
index 62c0b949aa..4b21b8c4be 100644
--- a/src/qt/csvmodelwriter.cpp
+++ b/src/qt/csvmodelwriter.cpp
@@ -48,7 +48,11 @@ bool CSVModelWriter::write()
return false;
QTextStream out(&file);
- int numRows = model->rowCount();
+ int numRows = 0;
+ if(model)
+ {
+ numRows = model->rowCount();
+ }
// Header row
for(int i=0; i<columns.size(); ++i)
diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp
index 457e8cf0dc..8cc3c85d7a 100644
--- a/src/qt/editaddressdialog.cpp
+++ b/src/qt/editaddressdialog.cpp
@@ -56,6 +56,8 @@ void EditAddressDialog::loadRow(int row)
bool EditAddressDialog::saveCurrentRow()
{
+ if(!model)
+ return false;
switch(mode)
{
case NewReceivingAddress:
@@ -78,6 +80,8 @@ bool EditAddressDialog::saveCurrentRow()
void EditAddressDialog::accept()
{
+ if(!model)
+ return;
if(!saveCurrentRow())
{
switch(model->getEditStatus())
diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp
index 6dedde0272..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);
@@ -143,30 +143,34 @@ void OverviewPage::setNumTransactions(int count)
void OverviewPage::setModel(WalletModel *model)
{
this->model = model;
+ if(model)
+ {
+ // Set up transaction list
+ TransactionFilterProxy *filter = new TransactionFilterProxy();
+ filter->setSourceModel(model->getTransactionTableModel());
+ filter->setLimit(NUM_ITEMS);
+ filter->setDynamicSortFilter(true);
+ filter->setSortRole(Qt::EditRole);
+ filter->sort(TransactionTableModel::Status, Qt::DescendingOrder);
- // Set up transaction list
- TransactionFilterProxy *filter = new TransactionFilterProxy();
- filter->setSourceModel(model->getTransactionTableModel());
- filter->setLimit(NUM_ITEMS);
- filter->setDynamicSortFilter(true);
- filter->setSortRole(Qt::EditRole);
- filter->sort(TransactionTableModel::Status, Qt::DescendingOrder);
-
- ui->listTransactions->setModel(filter);
- ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
+ ui->listTransactions->setModel(filter);
+ ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress);
- // Keep up to date with wallet
- setBalance(model->getBalance(), model->getUnconfirmedBalance());
- connect(model, SIGNAL(balanceChanged(qint64, qint64)), this, SLOT(setBalance(qint64, qint64)));
+ // Keep up to date with wallet
+ setBalance(model->getBalance(), model->getUnconfirmedBalance());
+ connect(model, SIGNAL(balanceChanged(qint64, qint64)), this, SLOT(setBalance(qint64, qint64)));
- setNumTransactions(model->getNumTransactions());
- connect(model, SIGNAL(numTransactionsChanged(int)), this, SLOT(setNumTransactions(int)));
+ setNumTransactions(model->getNumTransactions());
+ connect(model, SIGNAL(numTransactionsChanged(int)), this, SLOT(setNumTransactions(int)));
- connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(displayUnitChanged()));
+ connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(displayUnitChanged()));
+ }
}
void OverviewPage::displayUnitChanged()
{
+ if(!model || !model->getOptionsModel())
+ return;
if(currentBalance != -1)
setBalance(currentBalance, currentUnconfirmedBalance);
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/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 719cc51880..762f27dfa6 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -43,9 +43,11 @@ void SendCoinsDialog::setModel(WalletModel *model)
entry->setModel(model);
}
}
-
- setBalance(model->getBalance(), model->getUnconfirmedBalance());
- connect(model, SIGNAL(balanceChanged(qint64, qint64)), this, SLOT(setBalance(qint64, qint64)));
+ if(model)
+ {
+ setBalance(model->getBalance(), model->getUnconfirmedBalance());
+ connect(model, SIGNAL(balanceChanged(qint64, qint64)), this, SLOT(setBalance(qint64, qint64)));
+ }
}
SendCoinsDialog::~SendCoinsDialog()
@@ -57,6 +59,10 @@ void SendCoinsDialog::on_sendButton_clicked()
{
QList<SendCoinsRecipient> recipients;
bool valid = true;
+
+ if(!model)
+ return;
+
for(int i = 0; i < ui->entries->count(); ++i)
{
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
@@ -255,6 +261,9 @@ void SendCoinsDialog::handleURL(const QUrl *url)
void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance)
{
Q_UNUSED(unconfirmedBalance);
+ if(!model || !model->getOptionsModel())
+ return;
+
int unit = model->getOptionsModel()->getDisplayUnit();
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
}
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index 1802095b3a..23b11ccdde 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -44,6 +44,8 @@ void SendCoinsEntry::on_pasteButton_clicked()
void SendCoinsEntry::on_addressBookButton_clicked()
{
+ if(!model)
+ return;
AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
dlg.setModel(model->getAddressTableModel());
if(dlg.exec())
@@ -55,6 +57,8 @@ void SendCoinsEntry::on_addressBookButton_clicked()
void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
+ if(!model)
+ return;
ui->addAsLabel->setText(model->getAddressTableModel()->labelForAddress(address));
}
@@ -74,7 +78,7 @@ void SendCoinsEntry::clear()
ui->addAsLabel->clear();
ui->payAmount->clear();
ui->payTo->setFocus();
- if(model)
+ if(model && model->getOptionsModel())
{
ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
}
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index d39227c81f..2dcbf1ea8a 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -155,36 +155,39 @@ TransactionView::TransactionView(QWidget *parent) :
void TransactionView::setModel(WalletModel *model)
{
this->model = model;
-
- transactionProxyModel = new TransactionFilterProxy(this);
- transactionProxyModel->setSourceModel(model->getTransactionTableModel());
- transactionProxyModel->setDynamicSortFilter(true);
-
- transactionProxyModel->setSortRole(Qt::EditRole);
-
- transactionView->setModel(transactionProxyModel);
- transactionView->setAlternatingRowColors(true);
- transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
- transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
- transactionView->setSortingEnabled(true);
- transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
- transactionView->verticalHeader()->hide();
-
- transactionView->horizontalHeader()->resizeSection(
- TransactionTableModel::Status, 23);
- transactionView->horizontalHeader()->resizeSection(
- TransactionTableModel::Date, 120);
- transactionView->horizontalHeader()->resizeSection(
- TransactionTableModel::Type, 120);
- transactionView->horizontalHeader()->setResizeMode(
- TransactionTableModel::ToAddress, QHeaderView::Stretch);
- transactionView->horizontalHeader()->resizeSection(
- TransactionTableModel::Amount, 100);
-
+ if(model)
+ {
+ transactionProxyModel = new TransactionFilterProxy(this);
+ transactionProxyModel->setSourceModel(model->getTransactionTableModel());
+ transactionProxyModel->setDynamicSortFilter(true);
+
+ transactionProxyModel->setSortRole(Qt::EditRole);
+
+ transactionView->setModel(transactionProxyModel);
+ transactionView->setAlternatingRowColors(true);
+ transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
+ transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ transactionView->setSortingEnabled(true);
+ transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
+ transactionView->verticalHeader()->hide();
+
+ transactionView->horizontalHeader()->resizeSection(
+ TransactionTableModel::Status, 23);
+ transactionView->horizontalHeader()->resizeSection(
+ TransactionTableModel::Date, 120);
+ transactionView->horizontalHeader()->resizeSection(
+ TransactionTableModel::Type, 120);
+ transactionView->horizontalHeader()->setResizeMode(
+ TransactionTableModel::ToAddress, QHeaderView::Stretch);
+ transactionView->horizontalHeader()->resizeSection(
+ TransactionTableModel::Amount, 100);
+ }
}
void TransactionView::chooseDate(int idx)
{
+ if(!transactionProxyModel)
+ return;
QDate current = QDate::currentDate();
dateRangeWidget->setVisible(false);
switch(dateWidget->itemData(idx).toInt())
@@ -231,17 +234,23 @@ void TransactionView::chooseDate(int idx)
void TransactionView::chooseType(int idx)
{
+ if(!transactionProxyModel)
+ return;
transactionProxyModel->setTypeFilter(
typeWidget->itemData(idx).toInt());
}
void TransactionView::changedPrefix(const QString &prefix)
{
+ if(!transactionProxyModel)
+ return;
transactionProxyModel->setAddressPrefix(prefix);
}
void TransactionView::changedAmount(const QString &amount)
{
+ if(!transactionProxyModel)
+ return;
qint64 amount_parsed = 0;
if(BitcoinUnits::parse(model->getOptionsModel()->getDisplayUnit(), amount, &amount_parsed))
{
@@ -294,6 +303,8 @@ void TransactionView::contextualMenu(const QPoint &point)
void TransactionView::copyAddress()
{
+ if(!transactionView->selectionModel())
+ return;
QModelIndexList selection = transactionView->selectionModel()->selectedRows();
if(!selection.isEmpty())
{
@@ -303,6 +314,8 @@ void TransactionView::copyAddress()
void TransactionView::copyLabel()
{
+ if(!transactionView->selectionModel())
+ return;
QModelIndexList selection = transactionView->selectionModel()->selectedRows();
if(!selection.isEmpty())
{
@@ -312,10 +325,14 @@ void TransactionView::copyLabel()
void TransactionView::editLabel()
{
+ if(!transactionView->selectionModel() ||!model)
+ return;
QModelIndexList selection = transactionView->selectionModel()->selectedRows();
if(!selection.isEmpty())
{
AddressTableModel *addressBook = model->getAddressTableModel();
+ if(!addressBook)
+ return;
QString address = selection.at(0).data(TransactionTableModel::AddressRole).toString();
if(address.isEmpty())
{
@@ -354,6 +371,8 @@ void TransactionView::editLabel()
void TransactionView::showDetails()
{
+ if(!transactionView->selectionModel())
+ return;
QModelIndexList selection = transactionView->selectionModel()->selectedRows();
if(!selection.isEmpty())
{
@@ -400,6 +419,8 @@ QWidget *TransactionView::createDateRangeWidget()
void TransactionView::dateRangeChanged()
{
+ if(!transactionProxyModel)
+ return;
transactionProxyModel->setDateRange(
QDateTime(dateFrom->date()),
QDateTime(dateTo->date()).addDays(1));
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);