aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md12
-rwxr-xr-xautogen.sh6
-rw-r--r--configure.ac41
-rw-r--r--contrib/spendfrom/README.md4
-rw-r--r--doc/README.md2
-rw-r--r--doc/README_windows.txt2
-rw-r--r--doc/build-osx.md6
-rw-r--r--doc/build-unix.md27
-rw-r--r--doc/release-process.md11
-rw-r--r--doc/unit-tests.md2
-rw-r--r--share/qt/Info.plist.in13
-rw-r--r--src/Makefile.am45
-rw-r--r--src/Makefile.include1
-rw-r--r--src/bitcoind.cpp2
-rw-r--r--src/crypter.cpp157
-rw-r--r--src/crypter.h83
-rw-r--r--src/db.cpp110
-rw-r--r--src/db.h18
-rw-r--r--src/init.cpp80
-rw-r--r--src/keystore.cpp152
-rw-r--r--src/keystore.h83
-rw-r--r--src/leveldb/AUTHORS1
-rw-r--r--src/leveldb/Makefile10
-rwxr-xr-xsrc/leveldb/build_detect_platform10
-rw-r--r--src/leveldb/db/corruption_test.cc26
-rw-r--r--src/leveldb/db/db_bench.cc8
-rw-r--r--src/leveldb/db/db_impl.cc99
-rw-r--r--src/leveldb/db/db_impl.h9
-rw-r--r--src/leveldb/db/db_iter.cc9
-rw-r--r--src/leveldb/db/db_test.cc142
-rw-r--r--src/leveldb/db/filename.cc9
-rw-r--r--src/leveldb/db/filename.h5
-rw-r--r--src/leveldb/db/filename_test.cc1
-rw-r--r--src/leveldb/db/repair.cc159
-rw-r--r--src/leveldb/db/table_cache.cc6
-rw-r--r--src/leveldb/db/version_set.cc33
-rw-r--r--src/leveldb/db/version_set.h2
-rw-r--r--src/leveldb/doc/impl.html2
-rw-r--r--src/leveldb/include/leveldb/db.h2
-rw-r--r--src/leveldb/include/leveldb/env.h2
-rw-r--r--src/leveldb/issues/issue200_test.cc59
-rw-r--r--src/leveldb/port/atomic_pointer.h14
-rw-r--r--src/leveldb/table/filter_block_test.cc2
-rw-r--r--src/leveldb/util/arena.cc2
-rw-r--r--src/leveldb/util/arena.h2
-rw-r--r--src/leveldb/util/arena_test.cc6
-rw-r--r--src/leveldb/util/bloom_test.cc3
-rw-r--r--src/leveldb/util/coding_test.cc8
-rw-r--r--src/leveldb/util/env_posix.cc176
-rw-r--r--src/leveldb/util/testharness.cc2
-rw-r--r--src/leveldb/util/testutil.cc2
-rw-r--r--src/leveldb/util/testutil.h2
-rw-r--r--src/m4/ax_boost_base.m48
-rw-r--r--src/main.cpp105
-rw-r--r--src/main.h20
-rw-r--r--src/miner.cpp107
-rw-r--r--src/net.cpp139
-rw-r--r--src/net.h37
-rw-r--r--src/noui.cpp6
-rw-r--r--src/qt/Makefile.am5
-rw-r--r--src/qt/addresstablemodel.cpp2
-rw-r--r--src/qt/bitcoin.cpp46
-rw-r--r--src/qt/bitcoinamountfield.cpp6
-rw-r--r--src/qt/bitcoingui.cpp46
-rw-r--r--src/qt/bitcoingui.h10
-rw-r--r--src/qt/bitcoinstrings.cpp29
-rw-r--r--src/qt/clientmodel.cpp7
-rw-r--r--src/qt/clientmodel.h6
-rw-r--r--src/qt/coincontroldialog.cpp3
-rw-r--r--src/qt/editaddressdialog.cpp5
-rw-r--r--src/qt/forms/aboutdialog.ui6
-rw-r--r--src/qt/forms/intro.ui6
-rw-r--r--src/qt/forms/receivecoinsdialog.ui214
-rw-r--r--src/qt/forms/receiverequestdialog.ui7
-rw-r--r--src/qt/forms/rpcconsole.ui28
-rw-r--r--src/qt/guiutil.cpp5
-rw-r--r--src/qt/locale/bitcoin_en.ts1201
-rw-r--r--src/qt/macdockiconhandler.mm8
-rw-r--r--src/qt/macnotificationhandler.mm4
-rw-r--r--src/qt/notificator.cpp5
-rw-r--r--src/qt/notificator.h2
-rw-r--r--src/qt/optionsmodel.cpp1
-rw-r--r--src/qt/receivecoinsdialog.cpp59
-rw-r--r--src/qt/receivecoinsdialog.h7
-rw-r--r--src/qt/receiverequestdialog.cpp2
-rw-r--r--src/qt/recentrequeststablemodel.cpp129
-rw-r--r--src/qt/recentrequeststablemodel.h61
-rw-r--r--src/qt/res/bitcoin-qt-res.rc4
-rw-r--r--src/qt/rpcconsole.cpp2
-rw-r--r--src/qt/sendcoinsdialog.cpp13
-rw-r--r--src/qt/splashscreen.cpp11
-rw-r--r--src/qt/splashscreen.h2
-rw-r--r--src/qt/test/Makefile.am2
-rw-r--r--src/qt/walletmodel.cpp8
-rw-r--r--src/qt/walletmodel.h8
-rw-r--r--src/qt/walletmodeltransaction.h3
-rw-r--r--src/qt/walletview.cpp4
-rw-r--r--src/qt/walletview.h1
-rw-r--r--src/rpcblockchain.cpp24
-rw-r--r--src/rpcclient.cpp2
-rw-r--r--src/rpcmining.cpp29
-rw-r--r--src/rpcmisc.cpp326
-rw-r--r--src/rpcnet.cpp13
-rw-r--r--src/rpcrawtransaction.cpp15
-rw-r--r--src/rpcserver.cpp77
-rw-r--r--src/rpcwallet.cpp337
-rw-r--r--src/test/DoS_tests.cpp26
-rw-r--r--src/test/Makefile.am15
-rw-r--r--src/test/data/tx_invalid.json7
-rw-r--r--src/test/data/tx_valid.json7
-rw-r--r--src/test/miner_tests.cpp26
-rw-r--r--src/test/rpc_tests.cpp71
-rw-r--r--src/test/rpc_wallet_tests.cpp82
-rw-r--r--src/test/serialize_tests.cpp9
-rw-r--r--src/test/test_bitcoin.cpp14
-rw-r--r--src/ui_interface.h6
-rw-r--r--src/util.cpp55
-rw-r--r--src/wallet.cpp11
-rw-r--r--src/wallet.h7
119 files changed, 3299 insertions, 1920 deletions
diff --git a/README.md b/README.md
index 2534a62b08..e55526bf3f 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
-Bitcoin integration/staging tree
-================================
+Bitcoin Core integration/staging tree
+=====================================
http://www.bitcoin.org
-Copyright (c) 2009-2013 Bitcoin Developers
+Copyright (c) 2009-2013 Bitcoin Core Developers
What is Bitcoin?
----------------
@@ -11,16 +11,16 @@ What is Bitcoin?
Bitcoin is an experimental new digital currency that enables instant payments to
anyone, anywhere in the world. Bitcoin uses peer-to-peer technology to operate
with no central authority: managing transactions and issuing money are carried
-out collectively by the network. Bitcoin is also the name of the open source
+out collectively by the network. Bitcoin Core is the name of open source
software which enables the use of this currency.
For more information, as well as an immediately useable, binary version of
-the Bitcoin client software, see http://www.bitcoin.org.
+the Bitcoin Core software, see http://www.bitcoin.org/en/download.
License
-------
-Bitcoin is released under the terms of the MIT license. See [COPYING](COPYING) for more
+Bitcoin Core is released under the terms of the MIT license. See [COPYING](COPYING) for more
information or see http://opensource.org/licenses/MIT.
Development process
diff --git a/autogen.sh b/autogen.sh
index 4e7011a596..5b883a6a4c 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1 +1,5 @@
-autoreconf -vif
+#!/bin/sh
+set -e
+srcdir="$(dirname $0)"
+cd "$srcdir"
+autoreconf --install --force
diff --git a/configure.ac b/configure.ac
index df94438954..af230c355d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -37,6 +37,13 @@ AM_MAINTAINER_MODE([enable])
dnl make the compilation flags quiet unless V=1 is used
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+# Enable wallet
+AC_ARG_ENABLE([wallet],
+ [AS_HELP_STRING([--enable-wallet],
+ [enable wallet (default is yes)])],
+ [enable_wallet=$enableval],
+ [enable_wallet=yes])
+
AC_ARG_WITH([miniupnpc],
[AS_HELP_STRING([--with-miniupnpc],
[enable UPNP (default is yes if libminiupnpc is found)])],
@@ -362,12 +369,18 @@ AC_TRY_COMPILE([#include <sys/socket.h>],
[ AC_MSG_RESULT(no)]
)
-dnl Check for libdb_cxx
-BITCOIN_FIND_BDB48
+if test x$enable_wallet != xno; then
+ dnl Check for libdb_cxx only if wallet enabled
+ BITCOIN_FIND_BDB48
+fi
dnl Check for libminiupnpc (optional)
if test x$use_upnp != xno; then
- AC_CHECK_LIB([miniupnpc], [main],, [have_miniupnpc=no])
+ AC_CHECK_HEADERS(
+ [miniupnpc/miniwget.h miniupnpc/miniupnpc.h miniupnpc/upnpcommands.h miniupnpc/upnperrors.h],
+ [AC_CHECK_LIB([miniupnpc], [main],, [have_miniupnpc=no])],
+ [have_miniupnpc=no]
+ )
fi
dnl Check for boost libs
@@ -518,10 +531,9 @@ else
CPPFLAGS="$CPPFLAGS $QT_INCLUDES"
fi
])
-
- BITCOIN_QT_CHECK(AC_CHECK_HEADER([QtPlugin],,BITCOIN_QT_FAIL(QtCore headers missing),))
- BITCOIN_QT_CHECK(AC_CHECK_HEADER([QApplication],, BITCOIN_QT_FAIL(QtGui headers missing),))
- BITCOIN_QT_CHECK(AC_CHECK_HEADER([QLocalSocket],, BITCOIN_QT_FAIL(QtNetwork headers missing),))
+ BITCOIN_QT_CHECK([AC_CHECK_HEADER([QtPlugin],,BITCOIN_QT_FAIL(QtCore headers missing))])
+ BITCOIN_QT_CHECK([AC_CHECK_HEADER([QApplication],, BITCOIN_QT_FAIL(QtGui headers missing))])
+ BITCOIN_QT_CHECK([AC_CHECK_HEADER([QLocalSocket],, BITCOIN_QT_FAIL(QtNetwork headers missing))])
BITCOIN_QT_CHECK([
if test x$use_tests = xyes; then
@@ -593,6 +605,20 @@ if test "x$use_ccache" != "xno"; then
AC_MSG_RESULT($use_ccache)
fi
+dnl enable wallet
+AC_MSG_CHECKING([if wallet should be enabled])
+if test x$enable_wallet != xno; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED([ENABLE_WALLET],[1],[Define to 1 to enable wallet functions])
+
+else
+ AC_MSG_RESULT(no)
+
+ if test "x$use_qt" != "xno"; then
+ AC_MSG_ERROR([Cannot currently build Qt GUI with wallet disabled. Use --without-qt.])
+ fi
+fi
+
dnl enable ipv6 support
AC_MSG_CHECKING([if ipv6 should be enabled])
if test x$have_ipv6 = xno; then
@@ -705,6 +731,7 @@ fi
AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin])
AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
+AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet == xyes])
AM_CONDITIONAL([USE_QRCODE], [test x$use_qr = xyes])
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov == xyes])
AM_CONDITIONAL([USE_COMPARISON_TOOL],[test x$use_comparison_tool != xno])
diff --git a/contrib/spendfrom/README.md b/contrib/spendfrom/README.md
index 809540b7b1..c0a9c9ccf9 100644
--- a/contrib/spendfrom/README.md
+++ b/contrib/spendfrom/README.md
@@ -15,7 +15,7 @@ With arguments, sends coins received by the `FROMADDRESS` addresses to the `TOAD
### Notes ###
-- You may explictly specify how much fee to pay (a fee more than 1% of the amount
+- You may explicitly specify how much fee to pay (a fee more than 1% of the amount
will fail, though, to prevent bitcoin-losing accidents). Spendfrom may fail if
it thinks the transaction would never be confirmed (if the amount being sent is
too small, or if the transaction is too many bytes for the fee).
@@ -25,7 +25,7 @@ too small, or if the transaction is too many bytes for the fee).
- If `--datadir` is not specified, the default datadir is used.
-- The `--dry_run` option will just create and sign the the transaction and print
+- The `--dry_run` option will just create and sign the transaction and print
the transaction data (as hexadecimal), instead of broadcasting it.
- If the transaction is created and broadcast successfully, a transaction id
diff --git a/doc/README.md b/doc/README.md
index 4ac2e87c3f..c23d4a484e 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -6,7 +6,7 @@ Copyright (c) 2009-2013 Bitcoin Developers
Setup
---------------------
-[Bitcoin-Qt](http://bitcoin.org/en/download) is the original Bitcoin client and it builds the backbone of the network. However, it downloads and stores the entire history of Bitcoin transactions (which is currently several GBs); depending on the speed of your computer and network connection, the synchronization process can take anywhere from a few hours to a day or more. Thankfully you only have to do this once. If you would like the process to go faster you can [download the blockchain directly](https://bitcointalk.org/index.php?topic=145386.0).
+[Bitcoin Core](http://bitcoin.org/en/download) is the original Bitcoin client and it builds the backbone of the network. However, it downloads and stores the entire history of Bitcoin transactions (which is currently several GBs); depending on the speed of your computer and network connection, the synchronization process can take anywhere from a few hours to a day or more. Thankfully you only have to do this once. If you would like the process to go faster you can [download the blockchain directly](https://bitcointalk.org/index.php?topic=145386.0).
Running
---------------------
diff --git a/doc/README_windows.txt b/doc/README_windows.txt
index b26fab3be8..f120b8eb2f 100644
--- a/doc/README_windows.txt
+++ b/doc/README_windows.txt
@@ -20,7 +20,7 @@ Setup
-----
Unpack the files into a directory and run bitcoin-qt.exe.
-Bitcoin-Qt is the original Bitcoin client and it builds the backbone of the network.
+Bitcoin Core is the original Bitcoin client and it builds the backbone of the network.
However, it downloads and stores the entire history of Bitcoin transactions;
depending on the speed of your computer and network connection, the synchronization
process can take anywhere from a few hours to a day or more.
diff --git a/doc/build-osx.md b/doc/build-osx.md
index f70da685e9..6268a440a8 100644
--- a/doc/build-osx.md
+++ b/doc/build-osx.md
@@ -62,7 +62,7 @@ Installing the dependencies using MacPorts is very straightforward.
3. It is a good idea to build and run the unit tests, too:
- make test
+ make check
Instructions: HomeBrew
----------------------
@@ -87,7 +87,7 @@ Rerunning "openssl version" should now return the correct version.
1. Clone the github tree to get the source code and go into the directory.
- git clone git@github.com:bitcoin/bitcoin.git bitcoin
+ git clone https://github.com/bitcoin/bitcoin.git
cd bitcoin
2. Build bitcoind:
@@ -98,7 +98,7 @@ Rerunning "openssl version" should now return the correct version.
3. It is a good idea to build and run the unit tests, too:
- make test
+ make check
Creating a release build
------------------------
diff --git a/doc/build-unix.md b/doc/build-unix.md
index 27228cdc1b..b88186a70e 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -11,18 +11,13 @@ To Build
This will build bitcoin-qt as well if the dependencies are met.
-**Note:** on Ubuntu 13.10 (Saucy Salamander) the boost configuration script doesn't look in the
-correct directory and an error about boost-system will appear. For now you need to do
-
- ./configure --with-boost-libdir=/usr/lib/x86_64-linux-gnu
-
Dependencies
---------------------
Library Purpose Description
------- ------- -----------
libssl SSL Support Secure communications
- libdb4.8 Berkeley DB Blockchain & wallet storage
+ libdb4.8 Berkeley DB Wallet storage
libboost Boost C++ Library
miniupnpc UPnP Support Optional firewall-jumping support
qt GUI GUI toolkit
@@ -93,7 +88,7 @@ are installed. Qt 4 is currently necessary to build the GUI.
To build with Qt 4 you need the following:
- apt-get install libqt4-dev libprotobuf-dev
+ apt-get install libqt4-dev libprotobuf-dev protobuf-compiler
libqrencode (optional) can be installed with:
@@ -140,7 +135,10 @@ To help make your bitcoin installation more secure by making certain attacks imp
exploit even if a vulnerability is found, binaries are hardened by default.
This can be disabled with:
-./configure --enable-hardening
+Hardening Flags:
+
+ ./configure --enable-hardening
+ ./configure --disable-hardening
Hardening enables the following features:
@@ -178,3 +176,16 @@ Hardening enables the following features:
RW- R-- RW-
The STK RW- means that the stack is readable and writeable but not executable.
+
+Disable-wallet mode
+--------------------
+When the intention is to run only a P2P node without a wallet, bitcoin may be compiled in
+disable-wallet mode with:
+
+ ./configure --disable-wallet
+
+In this case there is no dependency on Berkeley DB 4.8.
+
+Mining is also possible in disable-wallet mode, but only using the `getblocktemplate` RPC
+call not `getwork`.
+
diff --git a/doc/release-process.md b/doc/release-process.md
index 3d5c577f86..2c0e2a3677 100644
--- a/doc/release-process.md
+++ b/doc/release-process.md
@@ -172,4 +172,15 @@ From a directory containing bitcoin source, gitian.sigs and gitian zips
popd
- Upload gitian zips to SourceForge
+
+- Announce the release:
+
+ - Add the release to bitcoin.org: https://github.com/bitcoin/bitcoin.org/tree/master/_releases
+
+ - Release sticky on bitcointalk: https://bitcointalk.org/index.php?board=1.0
+
+ - Bitcoin-development mailing list
+
+ - Optionally reddit /r/Bitcoin, ...
+
- Celebrate
diff --git a/doc/unit-tests.md b/doc/unit-tests.md
index 2c991eb03a..f1d3a8bc50 100644
--- a/doc/unit-tests.md
+++ b/doc/unit-tests.md
@@ -12,7 +12,7 @@ To add more bitcoind tests, add `BOOST_AUTO_TEST_CASE` functions to the existing
.cpp files in the test/ directory or add new .cpp files that
implement new BOOST_AUTO_TEST_SUITE sections.
-To run the bitcoin-qt tests manualy, launch src/qt/test/bitcoin-qt_test
+To run the bitcoin-qt tests manually, launch src/qt/test/bitcoin-qt_test
To add more bitcoin-qt tests, add them to the `src/qt/test/` directory and
the `src/qt/test/test_main.cpp` file.
diff --git a/share/qt/Info.plist.in b/share/qt/Info.plist.in
index d0dd796561..54ced278f2 100644
--- a/share/qt/Info.plist.in
+++ b/share/qt/Info.plist.in
@@ -4,18 +4,25 @@
<dict>
<key>CFBundleIconFile</key>
<string>bitcoin.icns</string>
+
<key>CFBundlePackageType</key>
<string>APPL</string>
+
<key>CFBundleGetInfoString</key>
<string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@, Copyright © 2009-@COPYRIGHT_YEAR@ The Bitcoin developers</string>
+
<key>CFBundleShortVersionString</key>
<string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@</string>
+
<key>CFBundleVersion</key>
<string>@CLIENT_VERSION_MAJOR@.@CLIENT_VERSION_MINOR@</string>
+
<key>CFBundleSignature</key>
<string>????</string>
+
<key>CFBundleExecutable</key>
<string>Bitcoin-Qt</string>
+
<key>CFBundleIdentifier</key>
<string>org.bitcoinfoundation.Bitcoin-Qt</string>
@@ -69,7 +76,11 @@
<string>Owner</string>
</dict>
</array>
+
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+
<key>NSHighResolutionCapable</key>
- <true/>
+ <string>True</string>
</dict>
</plist>
diff --git a/src/Makefile.am b/src/Makefile.am
index 9d3365fd60..5ce1c8e1b6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,6 +4,9 @@ AM_CPPFLAGS += -I$(top_srcdir)/src/leveldb/helpers/memenv \
-I$(builddir)
noinst_LIBRARIES = libbitcoin_server.a libbitcoin_common.a libbitcoin_cli.a
+if ENABLE_WALLET
+noinst_LIBRARIES += libbitcoin_wallet.a
+endif
bin_PROGRAMS = bitcoind bitcoin-cli
@@ -33,14 +36,38 @@ obj/build.h: FORCE
$(abs_top_srcdir)
version.o: obj/build.h
-libbitcoin_server_a_SOURCES = addrman.cpp alert.cpp \
+libbitcoin_server_a_SOURCES = \
+ addrman.cpp \
+ alert.cpp \
rpcserver.cpp \
bloom.cpp \
- chainparams.cpp checkpoints.cpp coins.cpp crypter.cpp db.cpp \
- init.cpp keystore.cpp leveldbwrapper.cpp main.cpp miner.cpp \
- net.cpp noui.cpp rpcblockchain.cpp rpcdump.cpp \
- rpcmining.cpp rpcnet.cpp rpcrawtransaction.cpp rpcwallet.cpp \
- txdb.cpp txmempool.cpp wallet.cpp walletdb.cpp $(JSON_H) \
+ chainparams.cpp \
+ checkpoints.cpp \
+ coins.cpp \
+ init.cpp \
+ keystore.cpp \
+ leveldbwrapper.cpp \
+ main.cpp \
+ miner.cpp \
+ net.cpp \
+ noui.cpp \
+ rpcblockchain.cpp \
+ rpcmining.cpp \
+ rpcmisc.cpp \
+ rpcnet.cpp \
+ rpcrawtransaction.cpp \
+ txdb.cpp \
+ txmempool.cpp \
+ $(JSON_H) \
+ $(BITCOIN_CORE_H)
+
+libbitcoin_wallet_a_SOURCES = \
+ db.cpp \
+ crypter.cpp \
+ rpcdump.cpp \
+ rpcwallet.cpp \
+ wallet.cpp \
+ walletdb.cpp \
$(BITCOIN_CORE_H)
libbitcoin_common_a_SOURCES = \
@@ -68,6 +95,9 @@ nodist_libbitcoin_common_a_SOURCES = $(top_srcdir)/src/obj/build.h
# bitcoind binary #
bitcoind_LDADD = libbitcoin_server.a libbitcoin_cli.a libbitcoin_common.a leveldb/libleveldb.a leveldb/libmemenv.a \
$(BOOST_LIBS)
+if ENABLE_WALLET
+bitcoind_LDADD += libbitcoin_wallet.a
+endif
bitcoind_SOURCES = bitcoind.cpp
#
@@ -106,5 +136,4 @@ EXTRA_DIST = leveldb Makefile.include
clean-local:
-$(MAKE) -C leveldb clean
- rm -f leveldb/port/*.gcno leveldb/db/*.gcno leveldb/table/*.gcno leveldb/helpers/*.gcno
- rm -f leveldb/util/*.gcno leveldb/helpers/memenv/*.gcno
+ rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
diff --git a/src/Makefile.include b/src/Makefile.include
index 2e96a6b7dc..13cffd29bc 100644
--- a/src/Makefile.include
+++ b/src/Makefile.include
@@ -6,6 +6,7 @@ AM_CPPFLAGS = $(INCLUDES) \
AM_LDFLAGS = $(PTHREAD_CFLAGS)
LIBBITCOIN_SERVER=$(top_builddir)/src/libbitcoin_server.a
+LIBBITCOIN_WALLET=$(top_builddir)/src/libbitcoin_wallet.a
LIBBITCOIN_COMMON=$(top_builddir)/src/libbitcoin_common.a
LIBBITCOIN_CLI=$(top_builddir)/src/libbitcoin_cli.a
LIBLEVELDB=$(top_builddir)/src/leveldb/libleveldb.a
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index e13d688158..de71fde9bc 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -78,7 +78,7 @@ bool AppInit(int argc, char* argv[])
if (mapArgs.count("-?") || mapArgs.count("--help"))
{
// First part of help message is specific to bitcoind / RPC client
- std::string strUsage = _("Bitcoin version") + " " + FormatFullVersion() + "\n\n" +
+ std::string strUsage = _("Bitcoin Core Daemon") + " " + _("version") + " " + FormatFullVersion() + "\n\n" +
_("Usage:") + "\n" +
" bitcoind [options] " + _("Start Bitcoin server") + "\n" +
_("Usage (deprecated, use bitcoin-cli):") + "\n" +
diff --git a/src/crypter.cpp b/src/crypter.cpp
index 10a34ae24a..4c43e3a798 100644
--- a/src/crypter.cpp
+++ b/src/crypter.cpp
@@ -4,9 +4,11 @@
#include "crypter.h"
+#include "script.h"
+
#include <string>
#include <vector>
-
+#include <boost/foreach.hpp>
#include <openssl/aes.h>
#include <openssl/evp.h>
@@ -117,3 +119,156 @@ bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned
return false;
return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext));
}
+
+bool CCryptoKeyStore::SetCrypted()
+{
+ LOCK(cs_KeyStore);
+ if (fUseCrypto)
+ return true;
+ if (!mapKeys.empty())
+ return false;
+ fUseCrypto = true;
+ return true;
+}
+
+bool CCryptoKeyStore::Lock()
+{
+ if (!SetCrypted())
+ return false;
+
+ {
+ LOCK(cs_KeyStore);
+ vMasterKey.clear();
+ }
+
+ NotifyStatusChanged(this);
+ return true;
+}
+
+bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
+{
+ {
+ LOCK(cs_KeyStore);
+ if (!SetCrypted())
+ return false;
+
+ CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
+ for (; mi != mapCryptedKeys.end(); ++mi)
+ {
+ const CPubKey &vchPubKey = (*mi).second.first;
+ const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
+ CKeyingMaterial vchSecret;
+ if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
+ return false;
+ if (vchSecret.size() != 32)
+ return false;
+ CKey key;
+ key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
+ if (key.GetPubKey() == vchPubKey)
+ break;
+ return false;
+ }
+ vMasterKey = vMasterKeyIn;
+ }
+ NotifyStatusChanged(this);
+ return true;
+}
+
+bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
+{
+ {
+ LOCK(cs_KeyStore);
+ if (!IsCrypted())
+ return CBasicKeyStore::AddKeyPubKey(key, pubkey);
+
+ if (IsLocked())
+ return false;
+
+ std::vector<unsigned char> vchCryptedSecret;
+ CKeyingMaterial vchSecret(key.begin(), key.end());
+ if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret))
+ return false;
+
+ if (!AddCryptedKey(pubkey, vchCryptedSecret))
+ return false;
+ }
+ return true;
+}
+
+
+bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
+{
+ {
+ LOCK(cs_KeyStore);
+ if (!SetCrypted())
+ return false;
+
+ mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
+ }
+ return true;
+}
+
+bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
+{
+ {
+ LOCK(cs_KeyStore);
+ if (!IsCrypted())
+ return CBasicKeyStore::GetKey(address, keyOut);
+
+ CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
+ if (mi != mapCryptedKeys.end())
+ {
+ const CPubKey &vchPubKey = (*mi).second.first;
+ const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
+ CKeyingMaterial vchSecret;
+ if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
+ return false;
+ if (vchSecret.size() != 32)
+ return false;
+ keyOut.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
+{
+ {
+ LOCK(cs_KeyStore);
+ if (!IsCrypted())
+ return CKeyStore::GetPubKey(address, vchPubKeyOut);
+
+ CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
+ if (mi != mapCryptedKeys.end())
+ {
+ vchPubKeyOut = (*mi).second.first;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
+{
+ {
+ LOCK(cs_KeyStore);
+ if (!mapCryptedKeys.empty() || IsCrypted())
+ return false;
+
+ fUseCrypto = true;
+ BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
+ {
+ const CKey &key = mKey.second;
+ CPubKey vchPubKey = key.GetPubKey();
+ CKeyingMaterial vchSecret(key.begin(), key.end());
+ std::vector<unsigned char> vchCryptedSecret;
+ if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
+ return false;
+ if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
+ return false;
+ }
+ mapKeys.clear();
+ }
+ return true;
+}
diff --git a/src/crypter.h b/src/crypter.h
index 861c4f9441..4791428b48 100644
--- a/src/crypter.h
+++ b/src/crypter.h
@@ -7,6 +7,7 @@
#include "allocators.h"
#include "serialize.h"
+#include "keystore.h"
class uint256;
@@ -106,4 +107,86 @@ public:
bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext);
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext);
+/** Keystore which keeps the private keys encrypted.
+ * It derives from the basic key store, which is used if no encryption is active.
+ */
+class CCryptoKeyStore : public CBasicKeyStore
+{
+private:
+ CryptedKeyMap mapCryptedKeys;
+
+ CKeyingMaterial vMasterKey;
+
+ // if fUseCrypto is true, mapKeys must be empty
+ // if fUseCrypto is false, vMasterKey must be empty
+ bool fUseCrypto;
+
+protected:
+ bool SetCrypted();
+
+ // will encrypt previously unencrypted keys
+ bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
+
+ bool Unlock(const CKeyingMaterial& vMasterKeyIn);
+
+public:
+ CCryptoKeyStore() : fUseCrypto(false)
+ {
+ }
+
+ bool IsCrypted() const
+ {
+ return fUseCrypto;
+ }
+
+ bool IsLocked() const
+ {
+ if (!IsCrypted())
+ return false;
+ bool result;
+ {
+ LOCK(cs_KeyStore);
+ result = vMasterKey.empty();
+ }
+ return result;
+ }
+
+ bool Lock();
+
+ virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
+ bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
+ bool HaveKey(const CKeyID &address) const
+ {
+ {
+ LOCK(cs_KeyStore);
+ if (!IsCrypted())
+ return CBasicKeyStore::HaveKey(address);
+ return mapCryptedKeys.count(address) > 0;
+ }
+ return false;
+ }
+ bool GetKey(const CKeyID &address, CKey& keyOut) const;
+ bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
+ void GetKeys(std::set<CKeyID> &setAddress) const
+ {
+ if (!IsCrypted())
+ {
+ CBasicKeyStore::GetKeys(setAddress);
+ return;
+ }
+ setAddress.clear();
+ CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
+ while (mi != mapCryptedKeys.end())
+ {
+ setAddress.insert((*mi).first);
+ mi++;
+ }
+ }
+
+ /* Wallet status (encrypted, locked) changed.
+ * Note: Called without locks held.
+ */
+ boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
+};
+
#endif
diff --git a/src/db.cpp b/src/db.cpp
index a286d9f726..1f2ee1c554 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -479,113 +479,3 @@ void CDBEnv::Flush(bool fShutdown)
}
}
-
-
-
-
-
-
-
-
-
-
-//
-// CAddrDB
-//
-
-CAddrDB::CAddrDB()
-{
- pathAddr = GetDataDir() / "peers.dat";
-}
-
-bool CAddrDB::Write(const CAddrMan& addr)
-{
- // Generate random temporary filename
- unsigned short randv = 0;
- RAND_bytes((unsigned char *)&randv, sizeof(randv));
- std::string tmpfn = strprintf("peers.dat.%04x", randv);
-
- // serialize addresses, checksum data up to that point, then append csum
- CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
- ssPeers << FLATDATA(Params().MessageStart());
- ssPeers << addr;
- uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
- ssPeers << hash;
-
- // open temp output file, and associate with CAutoFile
- boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
- FILE *file = fopen(pathTmp.string().c_str(), "wb");
- CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION);
- if (!fileout)
- return error("CAddrman::Write() : open failed");
-
- // Write and commit header, data
- try {
- fileout << ssPeers;
- }
- catch (std::exception &e) {
- return error("CAddrman::Write() : I/O error");
- }
- FileCommit(fileout);
- fileout.fclose();
-
- // replace existing peers.dat, if any, with new peers.dat.XXXX
- if (!RenameOver(pathTmp, pathAddr))
- return error("CAddrman::Write() : Rename-into-place failed");
-
- return true;
-}
-
-bool CAddrDB::Read(CAddrMan& addr)
-{
- // open input file, and associate with CAutoFile
- FILE *file = fopen(pathAddr.string().c_str(), "rb");
- CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION);
- if (!filein)
- return error("CAddrman::Read() : open failed");
-
- // use file size to size memory buffer
- int fileSize = GetFilesize(filein);
- int dataSize = fileSize - sizeof(uint256);
- //Don't try to resize to a negative number if file is small
- if ( dataSize < 0 ) dataSize = 0;
- vector<unsigned char> vchData;
- vchData.resize(dataSize);
- uint256 hashIn;
-
- // read data and checksum from file
- try {
- filein.read((char *)&vchData[0], dataSize);
- filein >> hashIn;
- }
- catch (std::exception &e) {
- return error("CAddrman::Read() 2 : I/O error or stream data corrupted");
- }
- filein.fclose();
-
- CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
-
- // verify stored checksum matches input data
- uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
- if (hashIn != hashTmp)
- return error("CAddrman::Read() : checksum mismatch; data corrupted");
-
- unsigned char pchMsgTmp[4];
- try {
- // de-serialize file header (network specific magic number) and ..
- ssPeers >> FLATDATA(pchMsgTmp);
-
- // ... verify the network matches ours
- if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
- return error("CAddrman::Read() : invalid network magic number");
-
- // de-serialize address data into one CAddrMan object
- ssPeers >> addr;
- }
- catch (std::exception &e) {
- return error("CAddrman::Read() : I/O error or stream data corrupted");
- }
-
- return true;
-}
-
diff --git a/src/db.h b/src/db.h
index e041a59300..66d7f31917 100644
--- a/src/db.h
+++ b/src/db.h
@@ -305,22 +305,4 @@ public:
bool static Rewrite(const std::string& strFile, const char* pszSkip = NULL);
};
-
-
-
-
-
-
-
-/** Access to the (IP) address database (peers.dat) */
-class CAddrDB
-{
-private:
- boost::filesystem::path pathAddr;
-public:
- CAddrDB();
- bool Write(const CAddrMan& addr);
- bool Read(CAddrMan& addr);
-};
-
#endif // BITCOIN_DB_H
diff --git a/src/init.cpp b/src/init.cpp
index 54722743e6..28f6e08f9a 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -10,15 +10,19 @@
#include "init.h"
#include "addrman.h"
-#include "rpcserver.h"
#include "checkpoints.h"
+#include "main.h"
#include "miner.h"
#include "net.h"
+#include "rpcserver.h"
#include "txdb.h"
#include "ui_interface.h"
#include "util.h"
+#ifdef ENABLE_WALLET
+#include "db.h"
#include "wallet.h"
#include "walletdb.h"
+#endif
#include <inttypes.h>
#include <stdint.h>
@@ -35,8 +39,10 @@
using namespace std;
using namespace boost;
+#ifdef ENABLE_WALLET
std::string strWalletFile;
CWallet* pwalletMain;
+#endif
#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
@@ -109,14 +115,19 @@ void Shutdown()
mempool.AddTransactionsUpdated(1);
StopRPCThreads();
ShutdownRPCMining();
+#ifdef ENABLE_WALLET
if (pwalletMain)
bitdb.Flush(false);
GenerateBitcoins(false, NULL, 0);
+#endif
StopNode();
+ UnregisterNodeSignals(GetNodeSignals());
{
LOCK(cs_main);
+#ifdef ENABLE_WALLET
if (pwalletMain)
pwalletMain->SetBestChain(chainActive.GetLocator());
+#endif
if (pblocktree)
pblocktree->Flush();
if (pcoinsTip)
@@ -125,12 +136,16 @@ void Shutdown()
delete pcoinsdbview; pcoinsdbview = NULL;
delete pblocktree; pblocktree = NULL;
}
+#ifdef ENABLE_WALLET
if (pwalletMain)
bitdb.Flush(true);
+#endif
boost::filesystem::remove(GetPidFile());
UnregisterAllWallets();
+#ifdef ENABLE_WALLET
if (pwalletMain)
delete pwalletMain;
+#endif
LogPrintf("Shutdown : done\n");
}
@@ -179,15 +194,13 @@ std::string HelpMessage(HelpMessageMode hmm)
strUsage += " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n";
strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n";
strUsage += " -testnet " + _("Use the test network") + "\n";
-
strUsage += " -pid=<file> " + _("Specify pid file (default: bitcoind.pid)") + "\n";
strUsage += " -gen " + _("Generate coins (default: 0)") + "\n";
- strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + "\n";
strUsage += " -dbcache=<n> " + _("Set database cache size in megabytes (default: 25)") + "\n";
strUsage += " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n";
- strUsage += " -proxy=<ip:port> " + _("Connect through socks proxy") + "\n";
- strUsage += " -socks=<n> " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n";
- strUsage += " -onion=<ip:port> " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n";
+ strUsage += " -proxy=<ip:port> " + _("Connect through SOCKS proxy") + "\n";
+ strUsage += " -socks=<n> " + _("Select SOCKS version for -proxy (4 or 5, default: 5)") + "\n";
+ strUsage += " -onion=<ip:port> " + _("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)") + "\n";
strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n";
strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n";
strUsage += " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n";
@@ -212,7 +225,6 @@ std::string HelpMessage(HelpMessageMode hmm)
strUsage += " -upnp " + _("Use UPnP to map the listening port (default: 0)") + "\n";
#endif
#endif
- strUsage += " -paytxfee=<amt> " + _("Fee per KB to add to transactions you send") + "\n";
strUsage += " -debug=<category> " + _("Output debugging information (default: 0, supplying <category> is optional)") + "\n";
strUsage += _("If <category> is not supplied, output all debugging information.") + "\n";
strUsage += _("<category> can be:");
@@ -229,7 +241,7 @@ std::string HelpMessage(HelpMessageMode hmm)
strUsage += " -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n";
strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n";
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be "
- "solved instantly. This is intended for regression testing tools and app development.") + "\n";
+ "solved instantly. This is intended for regression testing tools and app development.") + "\n";
#ifdef WIN32
strUsage += " -printtodebugger " + _("Send trace/debug info to debugger") + "\n";
#endif
@@ -249,27 +261,31 @@ std::string HelpMessage(HelpMessageMode hmm)
strUsage += " -rpcuser=<user> " + _("Username for JSON-RPC connections") + "\n";
strUsage += " -rpcpassword=<pw> " + _("Password for JSON-RPC connections") + "\n";
strUsage += " -rpcport=<port> " + _("Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332)") + "\n";
-
strUsage += " -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified IP address") + "\n";
strUsage += " -rpcthreads=<n> " + _("Set the number of threads to service RPC calls (default: 4)") + "\n";
strUsage += " -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n";
- strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n";
strUsage += " -alertnotify=<cmd> " + _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)") + "\n";
- strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + "\n";
strUsage += " -keypool=<n> " + _("Set key pool size to <n> (default: 100)") + "\n";
- strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + "\n";
- strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + "\n";
strUsage += " -checkblocks=<n> " + _("How many blocks to check at startup (default: 288, 0 = all)") + "\n";
strUsage += " -checklevel=<n> " + _("How thorough the block verification is (0-4, default: 3)") + "\n";
strUsage += " -txindex " + _("Maintain a full transaction index (default: 0)") + "\n";
strUsage += " -loadblock=<file> " + _("Imports blocks from external blk000??.dat file") + "\n";
strUsage += " -reindex " + _("Rebuild block chain index from current blk000??.dat files") + "\n";
strUsage += " -par=<n> " + _("Set the number of script verification threads (up to 16, 0 = auto, <0 = leave that many cores free, default: 0)") + "\n";
-
+#ifdef ENABLE_WALLET
+ strUsage += "\n" + _("Wallet options:") + "\n";
+ strUsage += " -disablewallet " + _("Do not load the wallet and disable wallet RPC calls") + "\n";
+ strUsage += " -paytxfee=<amt> " + _("Fee per kB to add to transactions you send") + "\n";
+ strUsage += " -rescan " + _("Rescan the block chain for missing wallet transactions") + "\n";
+ strUsage += " -salvagewallet " + _("Attempt to recover private keys from a corrupt wallet.dat") + "\n";
+ strUsage += " -upgradewallet " + _("Upgrade wallet to latest format") + "\n";
+ strUsage += " -wallet=<file> " + _("Specify wallet file (within data directory)") + "\n";
+ strUsage += " -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n";
+#endif
strUsage += "\n" + _("Block creation options:") + "\n";
- strUsage += " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n";
- strUsage += " -blockmaxsize=<n> " + _("Set maximum block size in bytes (default: 250000)") + "\n";
- strUsage += " -blockprioritysize=<n> " + _("Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)") + "\n";
+ strUsage += " -blockminsize=<n> " + _("Set minimum block size in bytes (default: 0)") + "\n";
+ strUsage += " -blockmaxsize=<n> " + strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE) + "\n";
+ strUsage += " -blockprioritysize=<n> " + strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE) + "\n";
strUsage += "\n" + _("SSL options: (see the Bitcoin Wiki for SSL setup instructions)") + "\n";
strUsage += " -rpcssl " + _("Use OpenSSL (https) for JSON-RPC connections") + "\n";
@@ -479,7 +495,9 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
fPrintToConsole = GetBoolArg("-printtoconsole", false);
fPrintToDebugger = GetBoolArg("-printtodebugger", false);
fLogTimestamps = GetBoolArg("-logtimestamps", true);
+#ifdef ENABLE_WALLET
bool fDisableWallet = GetBoolArg("-disablewallet", false);
+#endif
if (mapArgs.count("-timeout"))
{
@@ -517,6 +535,7 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
return InitError(strprintf(_("Invalid amount for -minrelaytxfee=<amount>: '%s'"), mapArgs["-minrelaytxfee"].c_str()));
}
+#ifdef ENABLE_WALLET
if (mapArgs.count("-paytxfee"))
{
if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
@@ -526,15 +545,15 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
}
strWalletFile = GetArg("-wallet", "wallet.dat");
-
+#endif
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
std::string strDataDir = GetDataDir().string();
-
+#ifdef ENABLE_WALLET
// Wallet file must be a plain filename without a directory
if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile))
return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile.c_str(), strDataDir.c_str()));
-
+#endif
// Make sure only a single Bitcoin process is using the data directory.
boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
@@ -567,7 +586,7 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
int64_t nStart;
// ********************************************************* Step 5: verify wallet database integrity
-
+#ifdef ENABLE_WALLET
if (!fDisableWallet) {
uiInterface.InitMessage(_("Verifying wallet..."));
@@ -613,7 +632,7 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
return InitError(_("wallet.dat corrupt, salvage failed"));
}
} // (!fDisableWallet)
-
+#endif // ENABLE_WALLET
// ********************************************************* Step 6: network initialization
RegisterNodeSignals(GetNodeSignals());
@@ -840,8 +859,8 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
}
}
- // as LoadBlockIndex can take several minutes, it's possible the user
- // requested to kill bitcoin-qt during the last operation. If so, exit.
+ // As LoadBlockIndex can take several minutes, it's possible the user
+ // requested to kill the GUI during the last operation. If so, exit.
// As the program has not fully started yet, Shutdown() is possibly overkill.
if (fRequestShutdown)
{
@@ -880,7 +899,7 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
}
// ********************************************************* Step 8: load wallet
-
+#ifdef ENABLE_WALLET
if (fDisableWallet) {
pwalletMain = NULL;
LogPrintf("Wallet disabled!\n");
@@ -972,7 +991,9 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
nWalletDBUpdated++;
}
} // (!fDisableWallet)
-
+#else // ENABLE_WALLET
+ LogPrintf("No wallet compiled in!\n");
+#endif // !ENABLE_WALLET
// ********************************************************* Step 9: import blocks
// scan for better chains in the block chain database, that are not yet connected in the active best chain
@@ -1016,25 +1037,29 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
//// debug print
LogPrintf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size());
LogPrintf("nBestHeight = %d\n", chainActive.Height());
+#ifdef ENABLE_WALLET
LogPrintf("setKeyPool.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0);
LogPrintf("mapWallet.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapWallet.size() : 0);
LogPrintf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
+#endif
StartNode(threadGroup);
-
// InitRPCMining is needed here so getwork/getblocktemplate in the GUI debug console works properly.
InitRPCMining();
if (fServer)
StartRPCThreads();
+#ifdef ENABLE_WALLET
// Generate coins in the background
if (pwalletMain)
GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", -1));
+#endif
// ********************************************************* Step 12: finished
uiInterface.InitMessage(_("Done loading"));
+#ifdef ENABLE_WALLET
if (pwalletMain) {
// Add wallet transactions that aren't already in a block to mapTransactions
pwalletMain->ReacceptWalletTransactions();
@@ -1042,6 +1067,7 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer)
// Run a thread to flush wallet periodically
threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile)));
}
+#endif
return !fRequestShutdown;
}
diff --git a/src/keystore.cpp b/src/keystore.cpp
index 05427291e0..46402ea25b 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -56,155 +56,3 @@ bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut)
return false;
}
-bool CCryptoKeyStore::SetCrypted()
-{
- LOCK(cs_KeyStore);
- if (fUseCrypto)
- return true;
- if (!mapKeys.empty())
- return false;
- fUseCrypto = true;
- return true;
-}
-
-bool CCryptoKeyStore::Lock()
-{
- if (!SetCrypted())
- return false;
-
- {
- LOCK(cs_KeyStore);
- vMasterKey.clear();
- }
-
- NotifyStatusChanged(this);
- return true;
-}
-
-bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
-{
- {
- LOCK(cs_KeyStore);
- if (!SetCrypted())
- return false;
-
- CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
- for (; mi != mapCryptedKeys.end(); ++mi)
- {
- const CPubKey &vchPubKey = (*mi).second.first;
- const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
- CKeyingMaterial vchSecret;
- if(!DecryptSecret(vMasterKeyIn, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
- return false;
- if (vchSecret.size() != 32)
- return false;
- CKey key;
- key.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
- if (key.GetPubKey() == vchPubKey)
- break;
- return false;
- }
- vMasterKey = vMasterKeyIn;
- }
- NotifyStatusChanged(this);
- return true;
-}
-
-bool CCryptoKeyStore::AddKeyPubKey(const CKey& key, const CPubKey &pubkey)
-{
- {
- LOCK(cs_KeyStore);
- if (!IsCrypted())
- return CBasicKeyStore::AddKeyPubKey(key, pubkey);
-
- if (IsLocked())
- return false;
-
- std::vector<unsigned char> vchCryptedSecret;
- CKeyingMaterial vchSecret(key.begin(), key.end());
- if (!EncryptSecret(vMasterKey, vchSecret, pubkey.GetHash(), vchCryptedSecret))
- return false;
-
- if (!AddCryptedKey(pubkey, vchCryptedSecret))
- return false;
- }
- return true;
-}
-
-
-bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
-{
- {
- LOCK(cs_KeyStore);
- if (!SetCrypted())
- return false;
-
- mapCryptedKeys[vchPubKey.GetID()] = make_pair(vchPubKey, vchCryptedSecret);
- }
- return true;
-}
-
-bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
-{
- {
- LOCK(cs_KeyStore);
- if (!IsCrypted())
- return CBasicKeyStore::GetKey(address, keyOut);
-
- CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
- if (mi != mapCryptedKeys.end())
- {
- const CPubKey &vchPubKey = (*mi).second.first;
- const std::vector<unsigned char> &vchCryptedSecret = (*mi).second.second;
- CKeyingMaterial vchSecret;
- if (!DecryptSecret(vMasterKey, vchCryptedSecret, vchPubKey.GetHash(), vchSecret))
- return false;
- if (vchSecret.size() != 32)
- return false;
- keyOut.Set(vchSecret.begin(), vchSecret.end(), vchPubKey.IsCompressed());
- return true;
- }
- }
- return false;
-}
-
-bool CCryptoKeyStore::GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const
-{
- {
- LOCK(cs_KeyStore);
- if (!IsCrypted())
- return CKeyStore::GetPubKey(address, vchPubKeyOut);
-
- CryptedKeyMap::const_iterator mi = mapCryptedKeys.find(address);
- if (mi != mapCryptedKeys.end())
- {
- vchPubKeyOut = (*mi).second.first;
- return true;
- }
- }
- return false;
-}
-
-bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
-{
- {
- LOCK(cs_KeyStore);
- if (!mapCryptedKeys.empty() || IsCrypted())
- return false;
-
- fUseCrypto = true;
- BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
- {
- const CKey &key = mKey.second;
- CPubKey vchPubKey = key.GetPubKey();
- CKeyingMaterial vchSecret(key.begin(), key.end());
- std::vector<unsigned char> vchCryptedSecret;
- if (!EncryptSecret(vMasterKeyIn, vchSecret, vchPubKey.GetHash(), vchCryptedSecret))
- return false;
- if (!AddCryptedKey(vchPubKey, vchCryptedSecret))
- return false;
- }
- mapKeys.clear();
- }
- return true;
-}
diff --git a/src/keystore.h b/src/keystore.h
index 8d936bcab7..0d55e6c81e 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -93,87 +93,4 @@ public:
typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap;
-
-/** Keystore which keeps the private keys encrypted.
- * It derives from the basic key store, which is used if no encryption is active.
- */
-class CCryptoKeyStore : public CBasicKeyStore
-{
-private:
- CryptedKeyMap mapCryptedKeys;
-
- CKeyingMaterial vMasterKey;
-
- // if fUseCrypto is true, mapKeys must be empty
- // if fUseCrypto is false, vMasterKey must be empty
- bool fUseCrypto;
-
-protected:
- bool SetCrypted();
-
- // will encrypt previously unencrypted keys
- bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
-
- bool Unlock(const CKeyingMaterial& vMasterKeyIn);
-
-public:
- CCryptoKeyStore() : fUseCrypto(false)
- {
- }
-
- bool IsCrypted() const
- {
- return fUseCrypto;
- }
-
- bool IsLocked() const
- {
- if (!IsCrypted())
- return false;
- bool result;
- {
- LOCK(cs_KeyStore);
- result = vMasterKey.empty();
- }
- return result;
- }
-
- bool Lock();
-
- virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
- bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
- bool HaveKey(const CKeyID &address) const
- {
- {
- LOCK(cs_KeyStore);
- if (!IsCrypted())
- return CBasicKeyStore::HaveKey(address);
- return mapCryptedKeys.count(address) > 0;
- }
- return false;
- }
- bool GetKey(const CKeyID &address, CKey& keyOut) const;
- bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
- void GetKeys(std::set<CKeyID> &setAddress) const
- {
- if (!IsCrypted())
- {
- CBasicKeyStore::GetKeys(setAddress);
- return;
- }
- setAddress.clear();
- CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
- while (mi != mapCryptedKeys.end())
- {
- setAddress.insert((*mi).first);
- mi++;
- }
- }
-
- /* Wallet status (encrypted, locked) changed.
- * Note: Called without locks held.
- */
- boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
-};
-
#endif
diff --git a/src/leveldb/AUTHORS b/src/leveldb/AUTHORS
index fc40194ab9..2439d7a452 100644
--- a/src/leveldb/AUTHORS
+++ b/src/leveldb/AUTHORS
@@ -9,3 +9,4 @@ Sanjay Ghemawat <sanjay@google.com>
# Partial list of contributors:
Kevin Regan <kevin.d.regan@gmail.com>
+Johan Bilien <jobi@litl.com>
diff --git a/src/leveldb/Makefile b/src/leveldb/Makefile
index 20c9c4f287..344ff2972a 100644
--- a/src/leveldb/Makefile
+++ b/src/leveldb/Makefile
@@ -44,6 +44,7 @@ TESTS = \
filename_test \
filter_block_test \
issue178_test \
+ issue200_test \
log_test \
memenv_test \
skiplist_test \
@@ -71,7 +72,7 @@ SHARED = $(SHARED1)
else
# Update db.h if you change these.
SHARED_MAJOR = 1
-SHARED_MINOR = 13
+SHARED_MINOR = 15
SHARED1 = libleveldb.$(PLATFORM_SHARED_EXT)
SHARED2 = $(SHARED1).$(SHARED_MAJOR)
SHARED3 = $(SHARED1).$(SHARED_MAJOR).$(SHARED_MINOR)
@@ -154,6 +155,9 @@ filter_block_test: table/filter_block_test.o $(LIBOBJECTS) $(TESTHARNESS)
issue178_test: issues/issue178_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(CXX) $(LDFLAGS) issues/issue178_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
+issue200_test: issues/issue200_test.o $(LIBOBJECTS) $(TESTHARNESS)
+ $(CXX) $(LDFLAGS) issues/issue200_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
+
log_test: db/log_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(CXX) $(LDFLAGS) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@ $(LIBS)
@@ -191,14 +195,14 @@ IOSVERSION=$(shell defaults read $(PLATFORMSROOT)/iPhoneOS.platform/version CFBu
mkdir -p ios-x86/$(dir $@)
$(CXX) $(CXXFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@
mkdir -p ios-arm/$(dir $@)
- $(DEVICEROOT)/usr/bin/$(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@
+ xcrun -sdk iphoneos $(CXX) $(CXXFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@
lipo ios-x86/$@ ios-arm/$@ -create -output $@
.c.o:
mkdir -p ios-x86/$(dir $@)
$(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 -c $< -o ios-x86/$@
mkdir -p ios-arm/$(dir $@)
- $(DEVICEROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@
+ xcrun -sdk iphoneos $(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 -c $< -o ios-arm/$@
lipo ios-x86/$@ ios-arm/$@ -create -output $@
else
diff --git a/src/leveldb/build_detect_platform b/src/leveldb/build_detect_platform
index bdfd64172c..85b1ce0224 100755
--- a/src/leveldb/build_detect_platform
+++ b/src/leveldb/build_detect_platform
@@ -137,6 +137,16 @@ case "$TARGET_OS" in
# man ld: +h internal_name
PLATFORM_SHARED_LDFLAGS="-shared -Wl,+h -Wl,"
;;
+ IOS)
+ PLATFORM=IOS
+ COMMON_FLAGS="$MEMCMP_FLAG -DOS_MACOSX"
+ [ -z "$INSTALL_PATH" ] && INSTALL_PATH=`pwd`
+ PORT_FILE=port/port_posix.cc
+ PLATFORM_SHARED_EXT=
+ PLATFORM_SHARED_LDFLAGS=
+ PLATFORM_SHARED_CFLAGS=
+ PLATFORM_SHARED_VERSIONED=
+ ;;
OS_WINDOWS_CROSSCOMPILE | NATIVE_WINDOWS)
PLATFORM=OS_WINDOWS
COMMON_FLAGS="-fno-builtin-memcmp -D_REENTRANT -DOS_WINDOWS -DLEVELDB_PLATFORM_WINDOWS -DWINVER=0x0500 -D__USE_MINGW_ANSI_STDIO=1"
diff --git a/src/leveldb/db/corruption_test.cc b/src/leveldb/db/corruption_test.cc
index b37ffdfe64..96afc68913 100644
--- a/src/leveldb/db/corruption_test.cc
+++ b/src/leveldb/db/corruption_test.cc
@@ -75,7 +75,13 @@ class CorruptionTest {
Slice key = Key(i, &key_space);
batch.Clear();
batch.Put(key, Value(i, &value_space));
- ASSERT_OK(db_->Write(WriteOptions(), &batch));
+ WriteOptions options;
+ // Corrupt() doesn't work without this sync on windows; stat reports 0 for
+ // the file size.
+ if (i == n - 1) {
+ options.sync = true;
+ }
+ ASSERT_OK(db_->Write(options, &batch));
}
}
@@ -125,7 +131,7 @@ class CorruptionTest {
FileType type;
std::string fname;
int picked_number = -1;
- for (int i = 0; i < filenames.size(); i++) {
+ for (size_t i = 0; i < filenames.size(); i++) {
if (ParseFileName(filenames[i], &number, &type) &&
type == filetype &&
int(number) > picked_number) { // Pick latest file
@@ -238,6 +244,22 @@ TEST(CorruptionTest, TableFile) {
Check(90, 99);
}
+TEST(CorruptionTest, TableFileRepair) {
+ options_.block_size = 2 * kValueSize; // Limit scope of corruption
+ options_.paranoid_checks = true;
+ Reopen();
+ Build(100);
+ DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
+ dbi->TEST_CompactMemTable();
+ dbi->TEST_CompactRange(0, NULL, NULL);
+ dbi->TEST_CompactRange(1, NULL, NULL);
+
+ Corrupt(kTableFile, 100, 1);
+ RepairDB();
+ Reopen();
+ Check(95, 99);
+}
+
TEST(CorruptionTest, TableFileIndexData) {
Build(10000); // Enough to build multiple Tables
DBImpl* dbi = reinterpret_cast<DBImpl*>(db_);
diff --git a/src/leveldb/db/db_bench.cc b/src/leveldb/db/db_bench.cc
index 7abdf87587..fc46d89693 100644
--- a/src/leveldb/db/db_bench.cc
+++ b/src/leveldb/db/db_bench.cc
@@ -128,7 +128,7 @@ class RandomGenerator {
pos_ = 0;
}
- Slice Generate(int len) {
+ Slice Generate(size_t len) {
if (pos_ + len > data_.size()) {
pos_ = 0;
assert(len < data_.size());
@@ -139,11 +139,11 @@ class RandomGenerator {
};
static Slice TrimSpace(Slice s) {
- int start = 0;
+ size_t start = 0;
while (start < s.size() && isspace(s[start])) {
start++;
}
- int limit = s.size();
+ size_t limit = s.size();
while (limit > start && isspace(s[limit-1])) {
limit--;
}
@@ -399,7 +399,7 @@ class Benchmark {
heap_counter_(0) {
std::vector<std::string> files;
Env::Default()->GetChildren(FLAGS_db, &files);
- for (int i = 0; i < files.size(); i++) {
+ for (size_t i = 0; i < files.size(); i++) {
if (Slice(files[i]).starts_with("heap-")) {
Env::Default()->DeleteFile(std::string(FLAGS_db) + "/" + files[i]);
}
diff --git a/src/leveldb/db/db_impl.cc b/src/leveldb/db/db_impl.cc
index fa1351038b..faf5e7d7ba 100644
--- a/src/leveldb/db/db_impl.cc
+++ b/src/leveldb/db/db_impl.cc
@@ -133,8 +133,7 @@ DBImpl::DBImpl(const Options& raw_options, const std::string& dbname)
seed_(0),
tmp_batch_(new WriteBatch),
bg_compaction_scheduled_(false),
- manual_compaction_(NULL),
- consecutive_compaction_errors_(0) {
+ manual_compaction_(NULL) {
mem_->Ref();
has_imm_.Release_Store(NULL);
@@ -217,6 +216,12 @@ void DBImpl::MaybeIgnoreError(Status* s) const {
}
void DBImpl::DeleteObsoleteFiles() {
+ if (!bg_error_.ok()) {
+ // After a background error, we don't know whether a new version may
+ // or may not have been committed, so we cannot safely garbage collect.
+ return;
+ }
+
// Make a set of all of the live files
std::set<uint64_t> live = pending_outputs_;
versions_->AddLiveFiles(&live);
@@ -495,7 +500,7 @@ Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
return s;
}
-Status DBImpl::CompactMemTable() {
+void DBImpl::CompactMemTable() {
mutex_.AssertHeld();
assert(imm_ != NULL);
@@ -523,9 +528,9 @@ Status DBImpl::CompactMemTable() {
imm_ = NULL;
has_imm_.Release_Store(NULL);
DeleteObsoleteFiles();
+ } else {
+ RecordBackgroundError(s);
}
-
- return s;
}
void DBImpl::CompactRange(const Slice* begin, const Slice* end) {
@@ -568,16 +573,18 @@ void DBImpl::TEST_CompactRange(int level, const Slice* begin,const Slice* end) {
}
MutexLock l(&mutex_);
- while (!manual.done) {
- while (manual_compaction_ != NULL) {
- bg_cv_.Wait();
- }
- manual_compaction_ = &manual;
- MaybeScheduleCompaction();
- while (manual_compaction_ == &manual) {
+ while (!manual.done && !shutting_down_.Acquire_Load() && bg_error_.ok()) {
+ if (manual_compaction_ == NULL) { // Idle
+ manual_compaction_ = &manual;
+ MaybeScheduleCompaction();
+ } else { // Running either my compaction or another compaction.
bg_cv_.Wait();
}
}
+ if (manual_compaction_ == &manual) {
+ // Cancel my manual compaction since we aborted early for some reason.
+ manual_compaction_ = NULL;
+ }
}
Status DBImpl::TEST_CompactMemTable() {
@@ -596,12 +603,22 @@ Status DBImpl::TEST_CompactMemTable() {
return s;
}
+void DBImpl::RecordBackgroundError(const Status& s) {
+ mutex_.AssertHeld();
+ if (bg_error_.ok()) {
+ bg_error_ = s;
+ bg_cv_.SignalAll();
+ }
+}
+
void DBImpl::MaybeScheduleCompaction() {
mutex_.AssertHeld();
if (bg_compaction_scheduled_) {
// Already scheduled
} else if (shutting_down_.Acquire_Load()) {
// DB is being deleted; no more background compactions
+ } else if (!bg_error_.ok()) {
+ // Already got an error; no more changes
} else if (imm_ == NULL &&
manual_compaction_ == NULL &&
!versions_->NeedsCompaction()) {
@@ -619,30 +636,12 @@ void DBImpl::BGWork(void* db) {
void DBImpl::BackgroundCall() {
MutexLock l(&mutex_);
assert(bg_compaction_scheduled_);
- if (!shutting_down_.Acquire_Load()) {
- Status s = BackgroundCompaction();
- if (s.ok()) {
- // Success
- consecutive_compaction_errors_ = 0;
- } else if (shutting_down_.Acquire_Load()) {
- // Error most likely due to shutdown; do not wait
- } else {
- // Wait a little bit before retrying background compaction in
- // case this is an environmental problem and we do not want to
- // chew up resources for failed compactions for the duration of
- // the problem.
- bg_cv_.SignalAll(); // In case a waiter can proceed despite the error
- Log(options_.info_log, "Waiting after background compaction error: %s",
- s.ToString().c_str());
- mutex_.Unlock();
- ++consecutive_compaction_errors_;
- int seconds_to_sleep = 1;
- for (int i = 0; i < 3 && i < consecutive_compaction_errors_ - 1; ++i) {
- seconds_to_sleep *= 2;
- }
- env_->SleepForMicroseconds(seconds_to_sleep * 1000000);
- mutex_.Lock();
- }
+ if (shutting_down_.Acquire_Load()) {
+ // No more background work when shutting down.
+ } else if (!bg_error_.ok()) {
+ // No more background work after a background error.
+ } else {
+ BackgroundCompaction();
}
bg_compaction_scheduled_ = false;
@@ -653,11 +652,12 @@ void DBImpl::BackgroundCall() {
bg_cv_.SignalAll();
}
-Status DBImpl::BackgroundCompaction() {
+void DBImpl::BackgroundCompaction() {
mutex_.AssertHeld();
if (imm_ != NULL) {
- return CompactMemTable();
+ CompactMemTable();
+ return;
}
Compaction* c;
@@ -691,6 +691,9 @@ Status DBImpl::BackgroundCompaction() {
c->edit()->AddFile(c->level() + 1, f->number, f->file_size,
f->smallest, f->largest);
status = versions_->LogAndApply(c->edit(), &mutex_);
+ if (!status.ok()) {
+ RecordBackgroundError(status);
+ }
VersionSet::LevelSummaryStorage tmp;
Log(options_.info_log, "Moved #%lld to level-%d %lld bytes %s: %s\n",
static_cast<unsigned long long>(f->number),
@@ -701,6 +704,9 @@ Status DBImpl::BackgroundCompaction() {
} else {
CompactionState* compact = new CompactionState(c);
status = DoCompactionWork(compact);
+ if (!status.ok()) {
+ RecordBackgroundError(status);
+ }
CleanupCompaction(compact);
c->ReleaseInputs();
DeleteObsoleteFiles();
@@ -714,9 +720,6 @@ Status DBImpl::BackgroundCompaction() {
} else {
Log(options_.info_log,
"Compaction error: %s", status.ToString().c_str());
- if (options_.paranoid_checks && bg_error_.ok()) {
- bg_error_ = status;
- }
}
if (is_manual) {
@@ -732,7 +735,6 @@ Status DBImpl::BackgroundCompaction() {
}
manual_compaction_ = NULL;
}
- return status;
}
void DBImpl::CleanupCompaction(CompactionState* compact) {
@@ -1002,6 +1004,9 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
if (status.ok()) {
status = InstallCompactionResults(compact);
}
+ if (!status.ok()) {
+ RecordBackgroundError(status);
+ }
VersionSet::LevelSummaryStorage tmp;
Log(options_.info_log,
"compacted to: %s", versions_->LevelSummary(&tmp));
@@ -1185,13 +1190,23 @@ Status DBImpl::Write(const WriteOptions& options, WriteBatch* my_batch) {
{
mutex_.Unlock();
status = log_->AddRecord(WriteBatchInternal::Contents(updates));
+ bool sync_error = false;
if (status.ok() && options.sync) {
status = logfile_->Sync();
+ if (!status.ok()) {
+ sync_error = true;
+ }
}
if (status.ok()) {
status = WriteBatchInternal::InsertInto(updates, mem_);
}
mutex_.Lock();
+ if (sync_error) {
+ // The state of the log file is indeterminate: the log record we
+ // just added may or may not show up when the DB is re-opened.
+ // So we force the DB into a mode where all future writes fail.
+ RecordBackgroundError(status);
+ }
}
if (updates == tmp_batch_) tmp_batch_->Clear();
diff --git a/src/leveldb/db/db_impl.h b/src/leveldb/db/db_impl.h
index 75fd30abe9..cfc998164a 100644
--- a/src/leveldb/db/db_impl.h
+++ b/src/leveldb/db/db_impl.h
@@ -87,8 +87,8 @@ class DBImpl : public DB {
// Compact the in-memory write buffer to disk. Switches to a new
// log-file/memtable and writes a new descriptor iff successful.
- Status CompactMemTable()
- EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ // Errors are recorded in bg_error_.
+ void CompactMemTable() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Status RecoverLogFile(uint64_t log_number,
VersionEdit* edit,
@@ -102,10 +102,12 @@ class DBImpl : public DB {
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
WriteBatch* BuildBatchGroup(Writer** last_writer);
+ void RecordBackgroundError(const Status& s);
+
void MaybeScheduleCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
static void BGWork(void* db);
void BackgroundCall();
- Status BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ void BackgroundCompaction() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void CleanupCompaction(CompactionState* compact)
EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Status DoCompactionWork(CompactionState* compact)
@@ -170,7 +172,6 @@ class DBImpl : public DB {
// Have we encountered a background error in paranoid mode?
Status bg_error_;
- int consecutive_compaction_errors_;
// Per level compaction stats. stats_[level] stores the stats for
// compactions that produced data for the specified "level".
diff --git a/src/leveldb/db/db_iter.cc b/src/leveldb/db/db_iter.cc
index 071a54e3f4..3b2035e9e3 100644
--- a/src/leveldb/db/db_iter.cc
+++ b/src/leveldb/db/db_iter.cc
@@ -161,12 +161,13 @@ void DBIter::Next() {
saved_key_.clear();
return;
}
+ // saved_key_ already contains the key to skip past.
+ } else {
+ // Store in saved_key_ the current key so we skip it below.
+ SaveKey(ExtractUserKey(iter_->key()), &saved_key_);
}
- // Temporarily use saved_key_ as storage for key to skip.
- std::string* skip = &saved_key_;
- SaveKey(ExtractUserKey(iter_->key()), skip);
- FindNextUserEntry(true, skip);
+ FindNextUserEntry(true, &saved_key_);
}
void DBIter::FindNextUserEntry(bool skipping, std::string* skip) {
diff --git a/src/leveldb/db/db_test.cc b/src/leveldb/db/db_test.cc
index 49aae04dbd..280b01c14b 100644
--- a/src/leveldb/db/db_test.cc
+++ b/src/leveldb/db/db_test.cc
@@ -57,8 +57,11 @@ void DelayMilliseconds(int millis) {
// Special Env used to delay background operations
class SpecialEnv : public EnvWrapper {
public:
- // sstable Sync() calls are blocked while this pointer is non-NULL.
- port::AtomicPointer delay_sstable_sync_;
+ // sstable/log Sync() calls are blocked while this pointer is non-NULL.
+ port::AtomicPointer delay_data_sync_;
+
+ // sstable/log Sync() calls return an error.
+ port::AtomicPointer data_sync_error_;
// Simulate no-space errors while this pointer is non-NULL.
port::AtomicPointer no_space_;
@@ -75,11 +78,9 @@ class SpecialEnv : public EnvWrapper {
bool count_random_reads_;
AtomicCounter random_read_counter_;
- AtomicCounter sleep_counter_;
- AtomicCounter sleep_time_counter_;
-
explicit SpecialEnv(Env* base) : EnvWrapper(base) {
- delay_sstable_sync_.Release_Store(NULL);
+ delay_data_sync_.Release_Store(NULL);
+ data_sync_error_.Release_Store(NULL);
no_space_.Release_Store(NULL);
non_writable_.Release_Store(NULL);
count_random_reads_ = false;
@@ -88,17 +89,17 @@ class SpecialEnv : public EnvWrapper {
}
Status NewWritableFile(const std::string& f, WritableFile** r) {
- class SSTableFile : public WritableFile {
+ class DataFile : public WritableFile {
private:
SpecialEnv* env_;
WritableFile* base_;
public:
- SSTableFile(SpecialEnv* env, WritableFile* base)
+ DataFile(SpecialEnv* env, WritableFile* base)
: env_(env),
base_(base) {
}
- ~SSTableFile() { delete base_; }
+ ~DataFile() { delete base_; }
Status Append(const Slice& data) {
if (env_->no_space_.Acquire_Load() != NULL) {
// Drop writes on the floor
@@ -110,7 +111,10 @@ class SpecialEnv : public EnvWrapper {
Status Close() { return base_->Close(); }
Status Flush() { return base_->Flush(); }
Status Sync() {
- while (env_->delay_sstable_sync_.Acquire_Load() != NULL) {
+ if (env_->data_sync_error_.Acquire_Load() != NULL) {
+ return Status::IOError("simulated data sync error");
+ }
+ while (env_->delay_data_sync_.Acquire_Load() != NULL) {
DelayMilliseconds(100);
}
return base_->Sync();
@@ -147,8 +151,9 @@ class SpecialEnv : public EnvWrapper {
Status s = target()->NewWritableFile(f, r);
if (s.ok()) {
- if (strstr(f.c_str(), ".sst") != NULL) {
- *r = new SSTableFile(this, *r);
+ if (strstr(f.c_str(), ".ldb") != NULL ||
+ strstr(f.c_str(), ".log") != NULL) {
+ *r = new DataFile(this, *r);
} else if (strstr(f.c_str(), "MANIFEST") != NULL) {
*r = new ManifestFile(this, *r);
}
@@ -179,12 +184,6 @@ class SpecialEnv : public EnvWrapper {
}
return s;
}
-
- virtual void SleepForMicroseconds(int micros) {
- sleep_counter_.Increment();
- sleep_time_counter_.IncrementBy(micros);
- }
-
};
class DBTest {
@@ -322,7 +321,7 @@ class DBTest {
}
// Check reverse iteration results are the reverse of forward results
- int matched = 0;
+ size_t matched = 0;
for (iter->SeekToLast(); iter->Valid(); iter->Prev()) {
ASSERT_LT(matched, forward.size());
ASSERT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]);
@@ -484,6 +483,24 @@ class DBTest {
}
return false;
}
+
+ // Returns number of files renamed.
+ int RenameLDBToSST() {
+ std::vector<std::string> filenames;
+ ASSERT_OK(env_->GetChildren(dbname_, &filenames));
+ uint64_t number;
+ FileType type;
+ int files_renamed = 0;
+ for (size_t i = 0; i < filenames.size(); i++) {
+ if (ParseFileName(filenames[i], &number, &type) && type == kTableFile) {
+ const std::string from = TableFileName(dbname_, number);
+ const std::string to = SSTTableFileName(dbname_, number);
+ ASSERT_OK(env_->RenameFile(from, to));
+ files_renamed++;
+ }
+ }
+ return files_renamed;
+ }
};
TEST(DBTest, Empty) {
@@ -525,11 +542,11 @@ TEST(DBTest, GetFromImmutableLayer) {
ASSERT_OK(Put("foo", "v1"));
ASSERT_EQ("v1", Get("foo"));
- env_->delay_sstable_sync_.Release_Store(env_); // Block sync calls
+ env_->delay_data_sync_.Release_Store(env_); // Block sync calls
Put("k1", std::string(100000, 'x')); // Fill memtable
Put("k2", std::string(100000, 'y')); // Trigger compaction
ASSERT_EQ("v1", Get("foo"));
- env_->delay_sstable_sync_.Release_Store(NULL); // Release sync calls
+ env_->delay_data_sync_.Release_Store(NULL); // Release sync calls
} while (ChangeOptions());
}
@@ -1516,41 +1533,13 @@ TEST(DBTest, NoSpace) {
Compact("a", "z");
const int num_files = CountFiles();
env_->no_space_.Release_Store(env_); // Force out-of-space errors
- env_->sleep_counter_.Reset();
- for (int i = 0; i < 5; i++) {
+ for (int i = 0; i < 10; i++) {
for (int level = 0; level < config::kNumLevels-1; level++) {
dbfull()->TEST_CompactRange(level, NULL, NULL);
}
}
env_->no_space_.Release_Store(NULL);
ASSERT_LT(CountFiles(), num_files + 3);
-
- // Check that compaction attempts slept after errors
- ASSERT_GE(env_->sleep_counter_.Read(), 5);
-}
-
-TEST(DBTest, ExponentialBackoff) {
- Options options = CurrentOptions();
- options.env = env_;
- Reopen(&options);
-
- ASSERT_OK(Put("foo", "v1"));
- ASSERT_EQ("v1", Get("foo"));
- Compact("a", "z");
- env_->non_writable_.Release_Store(env_); // Force errors for new files
- env_->sleep_counter_.Reset();
- env_->sleep_time_counter_.Reset();
- for (int i = 0; i < 5; i++) {
- dbfull()->TEST_CompactRange(2, NULL, NULL);
- }
- env_->non_writable_.Release_Store(NULL);
-
- // Wait for compaction to finish
- DelayMilliseconds(1000);
-
- ASSERT_GE(env_->sleep_counter_.Read(), 5);
- ASSERT_LT(env_->sleep_counter_.Read(), 10);
- ASSERT_GE(env_->sleep_time_counter_.Read(), 10e6);
}
TEST(DBTest, NonWritableFileSystem) {
@@ -1573,6 +1562,37 @@ TEST(DBTest, NonWritableFileSystem) {
env_->non_writable_.Release_Store(NULL);
}
+TEST(DBTest, WriteSyncError) {
+ // Check that log sync errors cause the DB to disallow future writes.
+
+ // (a) Cause log sync calls to fail
+ Options options = CurrentOptions();
+ options.env = env_;
+ Reopen(&options);
+ env_->data_sync_error_.Release_Store(env_);
+
+ // (b) Normal write should succeed
+ WriteOptions w;
+ ASSERT_OK(db_->Put(w, "k1", "v1"));
+ ASSERT_EQ("v1", Get("k1"));
+
+ // (c) Do a sync write; should fail
+ w.sync = true;
+ ASSERT_TRUE(!db_->Put(w, "k2", "v2").ok());
+ ASSERT_EQ("v1", Get("k1"));
+ ASSERT_EQ("NOT_FOUND", Get("k2"));
+
+ // (d) make sync behave normally
+ env_->data_sync_error_.Release_Store(NULL);
+
+ // (e) Do a non-sync write; should fail
+ w.sync = false;
+ ASSERT_TRUE(!db_->Put(w, "k3", "v3").ok());
+ ASSERT_EQ("v1", Get("k1"));
+ ASSERT_EQ("NOT_FOUND", Get("k2"));
+ ASSERT_EQ("NOT_FOUND", Get("k3"));
+}
+
TEST(DBTest, ManifestWriteError) {
// Test for the following problem:
// (a) Compaction produces file F
@@ -1632,6 +1652,22 @@ TEST(DBTest, MissingSSTFile) {
<< s.ToString();
}
+TEST(DBTest, StillReadSST) {
+ ASSERT_OK(Put("foo", "bar"));
+ ASSERT_EQ("bar", Get("foo"));
+
+ // Dump the memtable to disk.
+ dbfull()->TEST_CompactMemTable();
+ ASSERT_EQ("bar", Get("foo"));
+ Close();
+ ASSERT_GT(RenameLDBToSST(), 0);
+ Options options = CurrentOptions();
+ options.paranoid_checks = true;
+ Status s = TryReopen(&options);
+ ASSERT_TRUE(s.ok());
+ ASSERT_EQ("bar", Get("foo"));
+}
+
TEST(DBTest, FilesDeletedAfterCompaction) {
ASSERT_OK(Put("foo", "v2"));
Compact("a", "z");
@@ -1663,7 +1699,7 @@ TEST(DBTest, BloomFilter) {
dbfull()->TEST_CompactMemTable();
// Prevent auto compactions triggered by seeks
- env_->delay_sstable_sync_.Release_Store(env_);
+ env_->delay_data_sync_.Release_Store(env_);
// Lookup present keys. Should rarely read from small sstable.
env_->random_read_counter_.Reset();
@@ -1684,7 +1720,7 @@ TEST(DBTest, BloomFilter) {
fprintf(stderr, "%d missing => %d reads\n", N, reads);
ASSERT_LE(reads, 3*N/100);
- env_->delay_sstable_sync_.Release_Store(NULL);
+ env_->delay_data_sync_.Release_Store(NULL);
Close();
delete options.block_cache;
delete options.filter_policy;
@@ -1744,7 +1780,7 @@ static void MTThreadBody(void* arg) {
ASSERT_EQ(k, key);
ASSERT_GE(w, 0);
ASSERT_LT(w, kNumThreads);
- ASSERT_LE(c, reinterpret_cast<uintptr_t>(
+ ASSERT_LE(static_cast<uintptr_t>(c), reinterpret_cast<uintptr_t>(
t->state->counter[w].Acquire_Load()));
}
}
diff --git a/src/leveldb/db/filename.cc b/src/leveldb/db/filename.cc
index 3c4d49f64e..da32946d99 100644
--- a/src/leveldb/db/filename.cc
+++ b/src/leveldb/db/filename.cc
@@ -31,6 +31,11 @@ std::string LogFileName(const std::string& name, uint64_t number) {
std::string TableFileName(const std::string& name, uint64_t number) {
assert(number > 0);
+ return MakeFileName(name, number, "ldb");
+}
+
+std::string SSTTableFileName(const std::string& name, uint64_t number) {
+ assert(number > 0);
return MakeFileName(name, number, "sst");
}
@@ -71,7 +76,7 @@ std::string OldInfoLogFileName(const std::string& dbname) {
// dbname/LOG
// dbname/LOG.old
// dbname/MANIFEST-[0-9]+
-// dbname/[0-9]+.(log|sst)
+// dbname/[0-9]+.(log|sst|ldb)
bool ParseFileName(const std::string& fname,
uint64_t* number,
FileType* type) {
@@ -106,7 +111,7 @@ bool ParseFileName(const std::string& fname,
Slice suffix = rest;
if (suffix == Slice(".log")) {
*type = kLogFile;
- } else if (suffix == Slice(".sst")) {
+ } else if (suffix == Slice(".sst") || suffix == Slice(".ldb")) {
*type = kTableFile;
} else if (suffix == Slice(".dbtmp")) {
*type = kTempFile;
diff --git a/src/leveldb/db/filename.h b/src/leveldb/db/filename.h
index d5d09b1146..87a752605d 100644
--- a/src/leveldb/db/filename.h
+++ b/src/leveldb/db/filename.h
@@ -37,6 +37,11 @@ extern std::string LogFileName(const std::string& dbname, uint64_t number);
// "dbname".
extern std::string TableFileName(const std::string& dbname, uint64_t number);
+// Return the legacy file name for an sstable with the specified number
+// in the db named by "dbname". The result will be prefixed with
+// "dbname".
+extern std::string SSTTableFileName(const std::string& dbname, uint64_t number);
+
// Return the name of the descriptor file for the db named by
// "dbname" and the specified incarnation number. The result will be
// prefixed with "dbname".
diff --git a/src/leveldb/db/filename_test.cc b/src/leveldb/db/filename_test.cc
index 5a26da4728..a32556deaf 100644
--- a/src/leveldb/db/filename_test.cc
+++ b/src/leveldb/db/filename_test.cc
@@ -27,6 +27,7 @@ TEST(FileNameTest, Parse) {
{ "100.log", 100, kLogFile },
{ "0.log", 0, kLogFile },
{ "0.sst", 0, kTableFile },
+ { "0.ldb", 0, kTableFile },
{ "CURRENT", 0, kCurrentFile },
{ "LOCK", 0, kDBLockFile },
{ "MANIFEST-2", 2, kDescriptorFile },
diff --git a/src/leveldb/db/repair.cc b/src/leveldb/db/repair.cc
index 022d52f3de..96c9b37af1 100644
--- a/src/leveldb/db/repair.cc
+++ b/src/leveldb/db/repair.cc
@@ -244,60 +244,133 @@ class Repairer {
void ExtractMetaData() {
std::vector<TableInfo> kept;
for (size_t i = 0; i < table_numbers_.size(); i++) {
- TableInfo t;
- t.meta.number = table_numbers_[i];
- Status status = ScanTable(&t);
- if (!status.ok()) {
- std::string fname = TableFileName(dbname_, table_numbers_[i]);
- Log(options_.info_log, "Table #%llu: ignoring %s",
- (unsigned long long) table_numbers_[i],
- status.ToString().c_str());
- ArchiveFile(fname);
- } else {
- tables_.push_back(t);
- }
+ ScanTable(table_numbers_[i]);
}
}
- Status ScanTable(TableInfo* t) {
- std::string fname = TableFileName(dbname_, t->meta.number);
+ Iterator* NewTableIterator(const FileMetaData& meta) {
+ // Same as compaction iterators: if paranoid_checks are on, turn
+ // on checksum verification.
+ ReadOptions r;
+ r.verify_checksums = options_.paranoid_checks;
+ return table_cache_->NewIterator(r, meta.number, meta.file_size);
+ }
+
+ void ScanTable(uint64_t number) {
+ TableInfo t;
+ t.meta.number = number;
+ std::string fname = TableFileName(dbname_, number);
+ Status status = env_->GetFileSize(fname, &t.meta.file_size);
+ if (!status.ok()) {
+ // Try alternate file name.
+ fname = SSTTableFileName(dbname_, number);
+ Status s2 = env_->GetFileSize(fname, &t.meta.file_size);
+ if (s2.ok()) {
+ status = Status::OK();
+ }
+ }
+ if (!status.ok()) {
+ ArchiveFile(TableFileName(dbname_, number));
+ ArchiveFile(SSTTableFileName(dbname_, number));
+ Log(options_.info_log, "Table #%llu: dropped: %s",
+ (unsigned long long) t.meta.number,
+ status.ToString().c_str());
+ return;
+ }
+
+ // Extract metadata by scanning through table.
int counter = 0;
- Status status = env_->GetFileSize(fname, &t->meta.file_size);
- if (status.ok()) {
- Iterator* iter = table_cache_->NewIterator(
- ReadOptions(), t->meta.number, t->meta.file_size);
- bool empty = true;
- ParsedInternalKey parsed;
- t->max_sequence = 0;
- for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
- Slice key = iter->key();
- if (!ParseInternalKey(key, &parsed)) {
- Log(options_.info_log, "Table #%llu: unparsable key %s",
- (unsigned long long) t->meta.number,
- EscapeString(key).c_str());
- continue;
- }
+ Iterator* iter = NewTableIterator(t.meta);
+ bool empty = true;
+ ParsedInternalKey parsed;
+ t.max_sequence = 0;
+ for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
+ Slice key = iter->key();
+ if (!ParseInternalKey(key, &parsed)) {
+ Log(options_.info_log, "Table #%llu: unparsable key %s",
+ (unsigned long long) t.meta.number,
+ EscapeString(key).c_str());
+ continue;
+ }
- counter++;
- if (empty) {
- empty = false;
- t->meta.smallest.DecodeFrom(key);
- }
- t->meta.largest.DecodeFrom(key);
- if (parsed.sequence > t->max_sequence) {
- t->max_sequence = parsed.sequence;
- }
+ counter++;
+ if (empty) {
+ empty = false;
+ t.meta.smallest.DecodeFrom(key);
}
- if (!iter->status().ok()) {
- status = iter->status();
+ t.meta.largest.DecodeFrom(key);
+ if (parsed.sequence > t.max_sequence) {
+ t.max_sequence = parsed.sequence;
}
- delete iter;
}
+ if (!iter->status().ok()) {
+ status = iter->status();
+ }
+ delete iter;
Log(options_.info_log, "Table #%llu: %d entries %s",
- (unsigned long long) t->meta.number,
+ (unsigned long long) t.meta.number,
counter,
status.ToString().c_str());
- return status;
+
+ if (status.ok()) {
+ tables_.push_back(t);
+ } else {
+ RepairTable(fname, t); // RepairTable archives input file.
+ }
+ }
+
+ void RepairTable(const std::string& src, TableInfo t) {
+ // We will copy src contents to a new table and then rename the
+ // new table over the source.
+
+ // Create builder.
+ std::string copy = TableFileName(dbname_, next_file_number_++);
+ WritableFile* file;
+ Status s = env_->NewWritableFile(copy, &file);
+ if (!s.ok()) {
+ return;
+ }
+ TableBuilder* builder = new TableBuilder(options_, file);
+
+ // Copy data.
+ Iterator* iter = NewTableIterator(t.meta);
+ int counter = 0;
+ for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
+ builder->Add(iter->key(), iter->value());
+ counter++;
+ }
+ delete iter;
+
+ ArchiveFile(src);
+ if (counter == 0) {
+ builder->Abandon(); // Nothing to save
+ } else {
+ s = builder->Finish();
+ if (s.ok()) {
+ t.meta.file_size = builder->FileSize();
+ }
+ }
+ delete builder;
+ builder = NULL;
+
+ if (s.ok()) {
+ s = file->Close();
+ }
+ delete file;
+ file = NULL;
+
+ if (counter > 0 && s.ok()) {
+ std::string orig = TableFileName(dbname_, t.meta.number);
+ s = env_->RenameFile(copy, orig);
+ if (s.ok()) {
+ Log(options_.info_log, "Table #%llu: %d entries repaired",
+ (unsigned long long) t.meta.number, counter);
+ tables_.push_back(t);
+ }
+ }
+ if (!s.ok()) {
+ env_->DeleteFile(copy);
+ }
}
Status WriteDescriptor() {
diff --git a/src/leveldb/db/table_cache.cc b/src/leveldb/db/table_cache.cc
index 497db27076..e3d82cd3ea 100644
--- a/src/leveldb/db/table_cache.cc
+++ b/src/leveldb/db/table_cache.cc
@@ -54,6 +54,12 @@ Status TableCache::FindTable(uint64_t file_number, uint64_t file_size,
RandomAccessFile* file = NULL;
Table* table = NULL;
s = env_->NewRandomAccessFile(fname, &file);
+ if (!s.ok()) {
+ std::string old_fname = SSTTableFileName(dbname_, file_number);
+ if (env_->NewRandomAccessFile(old_fname, &file).ok()) {
+ s = Status::OK();
+ }
+ }
if (s.ok()) {
s = Table::Open(*options_, file, file_size, &table);
}
diff --git a/src/leveldb/db/version_set.cc b/src/leveldb/db/version_set.cc
index 66d73be71f..517edd3b18 100644
--- a/src/leveldb/db/version_set.cc
+++ b/src/leveldb/db/version_set.cc
@@ -876,12 +876,6 @@ Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) {
}
if (!s.ok()) {
Log(options_->info_log, "MANIFEST write: %s\n", s.ToString().c_str());
- if (ManifestContains(record)) {
- Log(options_->info_log,
- "MANIFEST contains log record despite error; advancing to new "
- "version to prevent mismatch between in-memory and logged state");
- s = Status::OK();
- }
}
}
@@ -889,8 +883,6 @@ Status VersionSet::LogAndApply(VersionEdit* edit, port::Mutex* mu) {
// new CURRENT file that points to it.
if (s.ok() && !new_manifest_file.empty()) {
s = SetCurrentFile(env_, dbname_, manifest_file_number_);
- // No need to double-check MANIFEST in case of error since it
- // will be discarded below.
}
mu->Lock();
@@ -1124,31 +1116,6 @@ const char* VersionSet::LevelSummary(LevelSummaryStorage* scratch) const {
return scratch->buffer;
}
-// Return true iff the manifest contains the specified record.
-bool VersionSet::ManifestContains(const std::string& record) const {
- std::string fname = DescriptorFileName(dbname_, manifest_file_number_);
- Log(options_->info_log, "ManifestContains: checking %s\n", fname.c_str());
- SequentialFile* file = NULL;
- Status s = env_->NewSequentialFile(fname, &file);
- if (!s.ok()) {
- Log(options_->info_log, "ManifestContains: %s\n", s.ToString().c_str());
- return false;
- }
- log::Reader reader(file, NULL, true/*checksum*/, 0);
- Slice r;
- std::string scratch;
- bool result = false;
- while (reader.ReadRecord(&r, &scratch)) {
- if (r == Slice(record)) {
- result = true;
- break;
- }
- }
- delete file;
- Log(options_->info_log, "ManifestContains: result = %d\n", result ? 1 : 0);
- return result;
-}
-
uint64_t VersionSet::ApproximateOffsetOf(Version* v, const InternalKey& ikey) {
uint64_t result = 0;
for (int level = 0; level < config::kNumLevels; level++) {
diff --git a/src/leveldb/db/version_set.h b/src/leveldb/db/version_set.h
index 20de0e2629..8dc14b8e01 100644
--- a/src/leveldb/db/version_set.h
+++ b/src/leveldb/db/version_set.h
@@ -292,8 +292,6 @@ class VersionSet {
void AppendVersion(Version* v);
- bool ManifestContains(const std::string& record) const;
-
Env* const env_;
const std::string dbname_;
const Options* const options_;
diff --git a/src/leveldb/doc/impl.html b/src/leveldb/doc/impl.html
index e870795d23..28817fe0da 100644
--- a/src/leveldb/doc/impl.html
+++ b/src/leveldb/doc/impl.html
@@ -11,7 +11,7 @@
The implementation of leveldb is similar in spirit to the
representation of a single
-<a href="http://labs.google.com/papers/bigtable.html">
+<a href="http://research.google.com/archive/bigtable.html">
Bigtable tablet (section 5.3)</a>.
However the organization of the files that make up the representation
is somewhat different and is explained below.
diff --git a/src/leveldb/include/leveldb/db.h b/src/leveldb/include/leveldb/db.h
index 57c00a5da0..5ffb29d526 100644
--- a/src/leveldb/include/leveldb/db.h
+++ b/src/leveldb/include/leveldb/db.h
@@ -14,7 +14,7 @@ namespace leveldb {
// Update Makefile if you change these
static const int kMajorVersion = 1;
-static const int kMinorVersion = 13;
+static const int kMinorVersion = 15;
struct Options;
struct ReadOptions;
diff --git a/src/leveldb/include/leveldb/env.h b/src/leveldb/include/leveldb/env.h
index fa32289f58..b2072d02c1 100644
--- a/src/leveldb/include/leveldb/env.h
+++ b/src/leveldb/include/leveldb/env.h
@@ -13,9 +13,9 @@
#ifndef STORAGE_LEVELDB_INCLUDE_ENV_H_
#define STORAGE_LEVELDB_INCLUDE_ENV_H_
-#include <cstdarg>
#include <string>
#include <vector>
+#include <stdarg.h>
#include <stdint.h>
#include "leveldb/status.h"
diff --git a/src/leveldb/issues/issue200_test.cc b/src/leveldb/issues/issue200_test.cc
new file mode 100644
index 0000000000..1cec79f443
--- /dev/null
+++ b/src/leveldb/issues/issue200_test.cc
@@ -0,0 +1,59 @@
+// Copyright (c) 2013 The LevelDB Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file. See the AUTHORS file for names of contributors.
+
+// Test for issue 200: when iterator switches direction from backward
+// to forward, the current key can be yielded unexpectedly if a new
+// mutation has been added just before the current key.
+
+#include "leveldb/db.h"
+#include "util/testharness.h"
+
+namespace leveldb {
+
+class Issue200 { };
+
+TEST(Issue200, Test) {
+ // Get rid of any state from an old run.
+ std::string dbpath = test::TmpDir() + "/leveldb_issue200_test";
+ DestroyDB(dbpath, Options());
+
+ DB *db;
+ Options options;
+ options.create_if_missing = true;
+ ASSERT_OK(DB::Open(options, dbpath, &db));
+
+ WriteOptions write_options;
+ ASSERT_OK(db->Put(write_options, "1", "b"));
+ ASSERT_OK(db->Put(write_options, "2", "c"));
+ ASSERT_OK(db->Put(write_options, "3", "d"));
+ ASSERT_OK(db->Put(write_options, "4", "e"));
+ ASSERT_OK(db->Put(write_options, "5", "f"));
+
+ ReadOptions read_options;
+ Iterator *iter = db->NewIterator(read_options);
+
+ // Add an element that should not be reflected in the iterator.
+ ASSERT_OK(db->Put(write_options, "25", "cd"));
+
+ iter->Seek("5");
+ ASSERT_EQ(iter->key().ToString(), "5");
+ iter->Prev();
+ ASSERT_EQ(iter->key().ToString(), "4");
+ iter->Prev();
+ ASSERT_EQ(iter->key().ToString(), "3");
+ iter->Next();
+ ASSERT_EQ(iter->key().ToString(), "4");
+ iter->Next();
+ ASSERT_EQ(iter->key().ToString(), "5");
+
+ delete iter;
+ delete db;
+ DestroyDB(dbpath, options);
+}
+
+} // namespace leveldb
+
+int main(int argc, char** argv) {
+ return leveldb::test::RunAllTests();
+}
diff --git a/src/leveldb/port/atomic_pointer.h b/src/leveldb/port/atomic_pointer.h
index e17bf435ea..a9866b2302 100644
--- a/src/leveldb/port/atomic_pointer.h
+++ b/src/leveldb/port/atomic_pointer.h
@@ -50,6 +50,13 @@ namespace port {
// http://msdn.microsoft.com/en-us/library/ms684208(v=vs.85).aspx
#define LEVELDB_HAVE_MEMORY_BARRIER
+// Mac OS
+#elif defined(OS_MACOSX)
+inline void MemoryBarrier() {
+ OSMemoryBarrier();
+}
+#define LEVELDB_HAVE_MEMORY_BARRIER
+
// Gcc on x86
#elif defined(ARCH_CPU_X86_FAMILY) && defined(__GNUC__)
inline void MemoryBarrier() {
@@ -68,13 +75,6 @@ inline void MemoryBarrier() {
}
#define LEVELDB_HAVE_MEMORY_BARRIER
-// Mac OS
-#elif defined(OS_MACOSX)
-inline void MemoryBarrier() {
- OSMemoryBarrier();
-}
-#define LEVELDB_HAVE_MEMORY_BARRIER
-
// ARM Linux
#elif defined(ARCH_CPU_ARM_FAMILY) && defined(__linux__)
typedef void (*LinuxKernelMemoryBarrierFunc)(void);
diff --git a/src/leveldb/table/filter_block_test.cc b/src/leveldb/table/filter_block_test.cc
index 3a2a07cf53..8c4a4741f2 100644
--- a/src/leveldb/table/filter_block_test.cc
+++ b/src/leveldb/table/filter_block_test.cc
@@ -29,7 +29,7 @@ class TestHashFilter : public FilterPolicy {
virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const {
uint32_t h = Hash(key.data(), key.size(), 1);
- for (int i = 0; i + 4 <= filter.size(); i += 4) {
+ for (size_t i = 0; i + 4 <= filter.size(); i += 4) {
if (h == DecodeFixed32(filter.data() + i)) {
return true;
}
diff --git a/src/leveldb/util/arena.cc b/src/leveldb/util/arena.cc
index 9551d6a3a2..9367f71492 100644
--- a/src/leveldb/util/arena.cc
+++ b/src/leveldb/util/arena.cc
@@ -40,7 +40,7 @@ char* Arena::AllocateFallback(size_t bytes) {
}
char* Arena::AllocateAligned(size_t bytes) {
- const int align = sizeof(void*); // We'll align to pointer size
+ const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8;
assert((align & (align-1)) == 0); // Pointer size should be a power of 2
size_t current_mod = reinterpret_cast<uintptr_t>(alloc_ptr_) & (align-1);
size_t slop = (current_mod == 0 ? 0 : align - current_mod);
diff --git a/src/leveldb/util/arena.h b/src/leveldb/util/arena.h
index 8f7dde226c..73bbf1cb9b 100644
--- a/src/leveldb/util/arena.h
+++ b/src/leveldb/util/arena.h
@@ -5,9 +5,9 @@
#ifndef STORAGE_LEVELDB_UTIL_ARENA_H_
#define STORAGE_LEVELDB_UTIL_ARENA_H_
-#include <cstddef>
#include <vector>
#include <assert.h>
+#include <stddef.h>
#include <stdint.h>
namespace leveldb {
diff --git a/src/leveldb/util/arena_test.cc b/src/leveldb/util/arena_test.cc
index 63d1778034..58e870ec44 100644
--- a/src/leveldb/util/arena_test.cc
+++ b/src/leveldb/util/arena_test.cc
@@ -40,7 +40,7 @@ TEST(ArenaTest, Simple) {
r = arena.Allocate(s);
}
- for (int b = 0; b < s; b++) {
+ for (size_t b = 0; b < s; b++) {
// Fill the "i"th allocation with a known bit pattern
r[b] = i % 256;
}
@@ -51,10 +51,10 @@ TEST(ArenaTest, Simple) {
ASSERT_LE(arena.MemoryUsage(), bytes * 1.10);
}
}
- for (int i = 0; i < allocated.size(); i++) {
+ for (size_t i = 0; i < allocated.size(); i++) {
size_t num_bytes = allocated[i].first;
const char* p = allocated[i].second;
- for (int b = 0; b < num_bytes; b++) {
+ for (size_t b = 0; b < num_bytes; b++) {
// Check the "i"th allocation for the known bit pattern
ASSERT_EQ(int(p[b]) & 0xff, i % 256);
}
diff --git a/src/leveldb/util/bloom_test.cc b/src/leveldb/util/bloom_test.cc
index 0bf8e8d6eb..77fb1b3159 100644
--- a/src/leveldb/util/bloom_test.cc
+++ b/src/leveldb/util/bloom_test.cc
@@ -126,7 +126,8 @@ TEST(BloomTest, VaryingLengths) {
}
Build();
- ASSERT_LE(FilterSize(), (length * 10 / 8) + 40) << length;
+ ASSERT_LE(FilterSize(), static_cast<size_t>((length * 10 / 8) + 40))
+ << length;
// All added keys must match
for (int i = 0; i < length; i++) {
diff --git a/src/leveldb/util/coding_test.cc b/src/leveldb/util/coding_test.cc
index fb5726e335..521541ea61 100644
--- a/src/leveldb/util/coding_test.cc
+++ b/src/leveldb/util/coding_test.cc
@@ -112,13 +112,13 @@ TEST(Coding, Varint64) {
}
std::string s;
- for (int i = 0; i < values.size(); i++) {
+ for (size_t i = 0; i < values.size(); i++) {
PutVarint64(&s, values[i]);
}
const char* p = s.data();
const char* limit = p + s.size();
- for (int i = 0; i < values.size(); i++) {
+ for (size_t i = 0; i < values.size(); i++) {
ASSERT_TRUE(p < limit);
uint64_t actual;
const char* start = p;
@@ -143,7 +143,7 @@ TEST(Coding, Varint32Truncation) {
std::string s;
PutVarint32(&s, large_value);
uint32_t result;
- for (int len = 0; len < s.size() - 1; len++) {
+ for (size_t len = 0; len < s.size() - 1; len++) {
ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + len, &result) == NULL);
}
ASSERT_TRUE(GetVarint32Ptr(s.data(), s.data() + s.size(), &result) != NULL);
@@ -162,7 +162,7 @@ TEST(Coding, Varint64Truncation) {
std::string s;
PutVarint64(&s, large_value);
uint64_t result;
- for (int len = 0; len < s.size() - 1; len++) {
+ for (size_t len = 0; len < s.size() - 1; len++) {
ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + len, &result) == NULL);
}
ASSERT_TRUE(GetVarint64Ptr(s.data(), s.data() + s.size(), &result) != NULL);
diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc
index 0f5dcfac5a..93eadb1a4f 100644
--- a/src/leveldb/util/env_posix.cc
+++ b/src/leveldb/util/env_posix.cc
@@ -176,147 +176,43 @@ class PosixMmapReadableFile: public RandomAccessFile {
}
};
-// We preallocate up to an extra megabyte and use memcpy to append new
-// data to the file. This is safe since we either properly close the
-// file before reading from it, or for log files, the reading code
-// knows enough to skip zero suffixes.
-class PosixMmapFile : public WritableFile {
+class PosixWritableFile : public WritableFile {
private:
std::string filename_;
- int fd_;
- size_t page_size_;
- size_t map_size_; // How much extra memory to map at a time
- char* base_; // The mapped region
- char* limit_; // Limit of the mapped region
- char* dst_; // Where to write next (in range [base_,limit_])
- char* last_sync_; // Where have we synced up to
- uint64_t file_offset_; // Offset of base_ in file
-
- // Have we done an munmap of unsynced data?
- bool pending_sync_;
-
- // Roundup x to a multiple of y
- static size_t Roundup(size_t x, size_t y) {
- return ((x + y - 1) / y) * y;
- }
-
- size_t TruncateToPageBoundary(size_t s) {
- s -= (s & (page_size_ - 1));
- assert((s % page_size_) == 0);
- return s;
- }
-
- bool UnmapCurrentRegion() {
- bool result = true;
- if (base_ != NULL) {
- if (last_sync_ < limit_) {
- // Defer syncing this data until next Sync() call, if any
- pending_sync_ = true;
- }
- if (munmap(base_, limit_ - base_) != 0) {
- result = false;
- }
- file_offset_ += limit_ - base_;
- base_ = NULL;
- limit_ = NULL;
- last_sync_ = NULL;
- dst_ = NULL;
-
- // Increase the amount we map the next time, but capped at 1MB
- if (map_size_ < (1<<20)) {
- map_size_ *= 2;
- }
- }
- return result;
- }
-
- bool MapNewRegion() {
- assert(base_ == NULL);
- if (ftruncate(fd_, file_offset_ + map_size_) < 0) {
- return false;
- }
- void* ptr = mmap(NULL, map_size_, PROT_READ | PROT_WRITE, MAP_SHARED,
- fd_, file_offset_);
- if (ptr == MAP_FAILED) {
- return false;
- }
- base_ = reinterpret_cast<char*>(ptr);
- limit_ = base_ + map_size_;
- dst_ = base_;
- last_sync_ = base_;
- return true;
- }
+ FILE* file_;
public:
- PosixMmapFile(const std::string& fname, int fd, size_t page_size)
- : filename_(fname),
- fd_(fd),
- page_size_(page_size),
- map_size_(Roundup(65536, page_size)),
- base_(NULL),
- limit_(NULL),
- dst_(NULL),
- last_sync_(NULL),
- file_offset_(0),
- pending_sync_(false) {
- assert((page_size & (page_size - 1)) == 0);
- }
-
-
- ~PosixMmapFile() {
- if (fd_ >= 0) {
- PosixMmapFile::Close();
+ PosixWritableFile(const std::string& fname, FILE* f)
+ : filename_(fname), file_(f) { }
+
+ ~PosixWritableFile() {
+ if (file_ != NULL) {
+ // Ignoring any potential errors
+ fclose(file_);
}
}
virtual Status Append(const Slice& data) {
- const char* src = data.data();
- size_t left = data.size();
- while (left > 0) {
- assert(base_ <= dst_);
- assert(dst_ <= limit_);
- size_t avail = limit_ - dst_;
- if (avail == 0) {
- if (!UnmapCurrentRegion() ||
- !MapNewRegion()) {
- return IOError(filename_, errno);
- }
- }
-
- size_t n = (left <= avail) ? left : avail;
- memcpy(dst_, src, n);
- dst_ += n;
- src += n;
- left -= n;
+ size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_);
+ if (r != data.size()) {
+ return IOError(filename_, errno);
}
return Status::OK();
}
virtual Status Close() {
- Status s;
- size_t unused = limit_ - dst_;
- if (!UnmapCurrentRegion()) {
- s = IOError(filename_, errno);
- } else if (unused > 0) {
- // Trim the extra space at the end of the file
- if (ftruncate(fd_, file_offset_ - unused) < 0) {
- s = IOError(filename_, errno);
- }
- }
-
- if (close(fd_) < 0) {
- if (s.ok()) {
- s = IOError(filename_, errno);
- }
+ Status result;
+ if (fclose(file_) != 0) {
+ result = IOError(filename_, errno);
}
-
- fd_ = -1;
- base_ = NULL;
- limit_ = NULL;
- return s;
+ file_ = NULL;
+ return result;
}
virtual Status Flush() {
+ if (fflush_unlocked(file_) != 0) {
+ return IOError(filename_, errno);
+ }
return Status::OK();
}
@@ -353,26 +249,10 @@ class PosixMmapFile : public WritableFile {
if (!s.ok()) {
return s;
}
-
- if (pending_sync_) {
- // Some unmapped data was not synced
- pending_sync_ = false;
- if (fdatasync(fd_) < 0) {
- s = IOError(filename_, errno);
- }
+ if (fflush_unlocked(file_) != 0 ||
+ fdatasync(fileno(file_)) != 0) {
+ s = Status::IOError(filename_, strerror(errno));
}
-
- if (dst_ > last_sync_) {
- // Find the beginnings of the pages that contain the first and last
- // bytes to be synced.
- size_t p1 = TruncateToPageBoundary(last_sync_ - base_);
- size_t p2 = TruncateToPageBoundary(dst_ - base_ - 1);
- last_sync_ = dst_;
- if (msync(base_ + p1, p2 - p1 + page_size_, MS_SYNC) < 0) {
- s = IOError(filename_, errno);
- }
- }
-
return s;
}
};
@@ -463,12 +343,12 @@ class PosixEnv : public Env {
virtual Status NewWritableFile(const std::string& fname,
WritableFile** result) {
Status s;
- const int fd = open(fname.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0644);
- if (fd < 0) {
+ FILE* f = fopen(fname.c_str(), "w");
+ if (f == NULL) {
*result = NULL;
s = IOError(fname, errno);
} else {
- *result = new PosixMmapFile(fname, fd, page_size_);
+ *result = new PosixWritableFile(fname, f);
}
return s;
}
@@ -631,7 +511,6 @@ class PosixEnv : public Env {
return NULL;
}
- size_t page_size_;
pthread_mutex_t mu_;
pthread_cond_t bgsignal_;
pthread_t bgthread_;
@@ -646,8 +525,7 @@ class PosixEnv : public Env {
MmapLimiter mmap_limit_;
};
-PosixEnv::PosixEnv() : page_size_(getpagesize()),
- started_bgthread_(false) {
+PosixEnv::PosixEnv() : started_bgthread_(false) {
PthreadCall("mutex_init", pthread_mutex_init(&mu_, NULL));
PthreadCall("cvar_init", pthread_cond_init(&bgsignal_, NULL));
}
diff --git a/src/leveldb/util/testharness.cc b/src/leveldb/util/testharness.cc
index eb1bdd554a..402fab34d7 100644
--- a/src/leveldb/util/testharness.cc
+++ b/src/leveldb/util/testharness.cc
@@ -38,7 +38,7 @@ int RunAllTests() {
int num = 0;
if (tests != NULL) {
- for (int i = 0; i < tests->size(); i++) {
+ for (size_t i = 0; i < tests->size(); i++) {
const Test& t = (*tests)[i];
if (matcher != NULL) {
std::string name = t.base;
diff --git a/src/leveldb/util/testutil.cc b/src/leveldb/util/testutil.cc
index 538d09516d..bee56bf75f 100644
--- a/src/leveldb/util/testutil.cc
+++ b/src/leveldb/util/testutil.cc
@@ -32,7 +32,7 @@ std::string RandomKey(Random* rnd, int len) {
extern Slice CompressibleString(Random* rnd, double compressed_fraction,
- int len, std::string* dst) {
+ size_t len, std::string* dst) {
int raw = static_cast<int>(len * compressed_fraction);
if (raw < 1) raw = 1;
std::string raw_data;
diff --git a/src/leveldb/util/testutil.h b/src/leveldb/util/testutil.h
index 824e655bd2..adad3fc1ea 100644
--- a/src/leveldb/util/testutil.h
+++ b/src/leveldb/util/testutil.h
@@ -24,7 +24,7 @@ extern std::string RandomKey(Random* rnd, int len);
// "N*compressed_fraction" bytes and return a Slice that references
// the generated data.
extern Slice CompressibleString(Random* rnd, double compressed_fraction,
- int len, std::string* dst);
+ size_t len, std::string* dst);
// A wrapper that allows injection of errors.
class ErrorEnv : public EnvWrapper {
diff --git a/src/m4/ax_boost_base.m4 b/src/m4/ax_boost_base.m4
index 57d14fe48d..c675f12d84 100644
--- a/src/m4/ax_boost_base.m4
+++ b/src/m4/ax_boost_base.m4
@@ -33,7 +33,7 @@
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 21
+#serial 22
AC_DEFUN([AX_BOOST_BASE],
[
@@ -97,6 +97,12 @@ if test "x$want_boost" = "xyes"; then
;;
esac
+ dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give
+ dnl them priority over the other paths since, if libs are found there, they
+ dnl are almost assuredly the ones desired.
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs"
+
dnl first we check the system location for boost libraries
dnl this location ist chosen if boost libraries are installed with the --layout=system option
dnl or if you install boost with RPM
diff --git a/src/main.cpp b/src/main.cpp
index 25201c7367..e3f9fdd843 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -67,9 +67,6 @@ CScript COINBASE_FLAGS;
const string strMessageMagic = "Bitcoin Signed Message:\n";
-// Settings
-int64_t nTransactionFee = 0;
-
// Internal stuff
namespace {
struct CBlockIndexWorkComparator
@@ -153,17 +150,66 @@ void SyncWithWallets(const uint256 &hash, const CTransaction &tx, const CBlock *
// Registration of network node signals.
//
-int static GetHeight()
+namespace {
+// Maintain validation-specific state about nodes, protected by cs_main, instead
+// by CNode's own locks. This simplifies asynchronous operation, where
+// processing of incoming data is done after the ProcessMessage call returns,
+// and we're no longer holding the node's locks.
+struct CNodeState {
+ int nMisbehavior;
+ bool fShouldBan;
+ std::string name;
+
+ CNodeState() {
+ nMisbehavior = 0;
+ fShouldBan = false;
+ }
+};
+
+map<NodeId, CNodeState> mapNodeState;
+
+// Requires cs_main.
+CNodeState *State(NodeId pnode) {
+ map<NodeId, CNodeState>::iterator it = mapNodeState.find(pnode);
+ if (it == mapNodeState.end())
+ return NULL;
+ return &it->second;
+}
+
+int GetHeight()
{
LOCK(cs_main);
return chainActive.Height();
}
+void InitializeNode(NodeId nodeid, const CNode *pnode) {
+ LOCK(cs_main);
+ CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
+ state.name = pnode->addrName;
+}
+
+void FinalizeNode(NodeId nodeid) {
+ LOCK(cs_main);
+ mapNodeState.erase(nodeid);
+}
+}
+
+bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
+ LOCK(cs_main);
+ CNodeState *state = State(nodeid);
+ if (state == NULL)
+ return false;
+ stats.nMisbehavior = state->nMisbehavior;
+ return true;
+}
+
void RegisterNodeSignals(CNodeSignals& nodeSignals)
{
nodeSignals.GetHeight.connect(&GetHeight);
nodeSignals.ProcessMessages.connect(&ProcessMessages);
nodeSignals.SendMessages.connect(&SendMessages);
+ nodeSignals.InitializeNode.connect(&InitializeNode);
+ nodeSignals.FinalizeNode.connect(&FinalizeNode);
}
void UnregisterNodeSignals(CNodeSignals& nodeSignals)
@@ -171,6 +217,8 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals)
nodeSignals.GetHeight.disconnect(&GetHeight);
nodeSignals.ProcessMessages.disconnect(&ProcessMessages);
nodeSignals.SendMessages.disconnect(&SendMessages);
+ nodeSignals.InitializeNode.disconnect(&InitializeNode);
+ nodeSignals.FinalizeNode.disconnect(&FinalizeNode);
}
//////////////////////////////////////////////////////////////////////////////
@@ -2915,6 +2963,23 @@ bool static AlreadyHave(const CInv& inv)
}
+void Misbehaving(NodeId pnode, int howmuch)
+{
+ if (howmuch == 0)
+ return;
+
+ CNodeState *state = State(pnode);
+ if (state == NULL)
+ return;
+
+ state->nMisbehavior += howmuch;
+ if (state->nMisbehavior >= GetArg("-banscore", 100))
+ {
+ LogPrintf("Misbehaving: %s (%d -> %d) BAN THRESHOLD EXCEEDED\n", state->name.c_str(), state->nMisbehavior-howmuch, state->nMisbehavior);
+ state->fShouldBan = true;
+ } else
+ LogPrintf("Misbehaving: %s (%d -> %d)\n", state->name.c_str(), state->nMisbehavior-howmuch, state->nMisbehavior);
+}
void static ProcessGetData(CNode* pfrom)
{
@@ -3048,7 +3113,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (pfrom->nVersion != 0)
{
pfrom->PushMessage("reject", strCommand, REJECT_DUPLICATE, string("Duplicate version message"));
- pfrom->Misbehaving(1);
+ Misbehaving(pfrom->GetId(), 1);
return false;
}
@@ -3153,7 +3218,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
else if (pfrom->nVersion == 0)
{
// Must have a version message before anything else
- pfrom->Misbehaving(1);
+ Misbehaving(pfrom->GetId(), 1);
return false;
}
@@ -3174,7 +3239,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return true;
if (vAddr.size() > 1000)
{
- pfrom->Misbehaving(20);
+ Misbehaving(pfrom->GetId(), 20);
return error("message addr size() = %"PRIszu"", vAddr.size());
}
@@ -3237,7 +3302,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> vInv;
if (vInv.size() > MAX_INV_SZ)
{
- pfrom->Misbehaving(20);
+ Misbehaving(pfrom->GetId(), 20);
return error("message inv size() = %"PRIszu"", vInv.size());
}
@@ -3288,7 +3353,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> vInv;
if (vInv.size() > MAX_INV_SZ)
{
- pfrom->Misbehaving(20);
+ Misbehaving(pfrom->GetId(), 20);
return error("message getdata size() = %"PRIszu"", vInv.size());
}
@@ -3461,7 +3526,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
state.GetRejectReason(), inv.hash);
if (nDoS > 0)
- pfrom->Misbehaving(nDoS);
+ Misbehaving(pfrom->GetId(), nDoS);
}
}
@@ -3488,7 +3553,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
state.GetRejectReason(), inv.hash);
if (nDoS > 0)
- pfrom->Misbehaving(nDoS);
+ Misbehaving(pfrom->GetId(), nDoS);
}
}
@@ -3631,7 +3696,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// This isn't a Misbehaving(100) (immediate ban) because the
// peer might be an older or different implementation with
// a different signature key, etc.
- pfrom->Misbehaving(10);
+ Misbehaving(pfrom->GetId(), 10);
}
}
}
@@ -3644,7 +3709,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (!filter.IsWithinSizeConstraints())
// There is no excuse for sending a too-large filter
- pfrom->Misbehaving(100);
+ Misbehaving(pfrom->GetId(), 100);
else
{
LOCK(pfrom->cs_filter);
@@ -3665,13 +3730,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// and thus, the maximum size any matched object can have) in a filteradd message
if (vData.size() > MAX_SCRIPT_ELEMENT_SIZE)
{
- pfrom->Misbehaving(100);
+ Misbehaving(pfrom->GetId(), 100);
} else {
LOCK(pfrom->cs_filter);
if (pfrom->pfilter)
pfrom->pfilter->insert(vData);
else
- pfrom->Misbehaving(100);
+ Misbehaving(pfrom->GetId(), 100);
}
}
@@ -3936,6 +4001,16 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
if (!lockMain)
return true;
+ if (State(pto->GetId())->fShouldBan) {
+ if (pto->addr.IsLocal())
+ LogPrintf("Warning: not banning local node %s!\n", pto->addr.ToString().c_str());
+ else {
+ pto->fDisconnect = true;
+ CNode::Ban(pto->addr);
+ }
+ State(pto->GetId())->fShouldBan = false;
+ }
+
// Start block sync
if (pto->fStartSync && !fImporting && !fReindex) {
pto->fStartSync = false;
diff --git a/src/main.h b/src/main.h
index c4e1839443..f3f9acb639 100644
--- a/src/main.h
+++ b/src/main.h
@@ -35,10 +35,12 @@ class CInv;
/** The maximum allowed size for a serialized block, in bytes (network rule) */
static const unsigned int MAX_BLOCK_SIZE = 1000000;
-/** The maximum size for mined blocks */
-static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
+/** Default for -blockmaxsize, maximum size for mined blocks **/
+static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
+/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
+static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000;
/** The maximum size for transactions we're willing to relay/mine */
-static const unsigned int MAX_STANDARD_TX_SIZE = MAX_BLOCK_SIZE_GEN/5;
+static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
/** The maximum allowed number of signature check operations in a block (network rule) */
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
/** The maximum number of orphan transactions kept in memory */
@@ -55,8 +57,6 @@ static const int COINBASE_MATURITY = 100;
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
/** Maximum number of script-checking threads allowed */
static const int MAX_SCRIPTCHECK_THREADS = 16;
-/** Default amount of block size reserved for high-priority transactions (in bytes) */
-static const int DEFAULT_BLOCK_PRIORITY_SIZE = 27000;
#ifdef USE_UPNP
static const int fHaveUPnP = true;
#else
@@ -96,9 +96,6 @@ extern bool fTxIndex;
extern unsigned int nCoinCacheSize;
extern bool fHaveGUI;
-// Settings
-extern int64_t nTransactionFee;
-
// Minimum disk space required - used in CheckDiskSpace()
static const uint64_t nMinDiskSpace = 52428800;
@@ -110,6 +107,7 @@ class CTxUndo;
class CScriptCheck;
class CValidationState;
class CWalletInterface;
+struct CNodeStateStats;
struct CBlockTemplate;
@@ -182,6 +180,8 @@ CBlockIndex * InsertBlockIndex(uint256 hash);
bool VerifySignature(const CCoins& txFrom, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
/** Abort with a message */
bool AbortNode(const std::string &msg);
+/** Get statistics from node state */
+bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
/** (try to) add transaction to memory pool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
@@ -194,6 +194,10 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
+struct CNodeStateStats {
+ int nMisbehavior;
+};
+
struct CDiskBlockPos
{
int nFile;
diff --git a/src/miner.cpp b/src/miner.cpp
index ecc40ac708..21a9fa256b 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -8,11 +8,9 @@
#include "core.h"
#include "main.h"
#include "net.h"
+#ifdef ENABLE_WALLET
#include "wallet.h"
-
-double dHashesPerSec = 0.0;
-int64_t nHPSTimerStart = 0;
-
+#endif
//////////////////////////////////////////////////////////////////////////////
//
// BitcoinMiner
@@ -54,41 +52,6 @@ void SHA256Transform(void* pstate, void* pinput, const void* pinit)
((uint32_t*)pstate)[i] = ctx.h[i];
}
-//
-// ScanHash scans nonces looking for a hash with at least some zero bits.
-// It operates on big endian data. Caller does the byte reversing.
-// All input buffers are 16-byte aligned. nNonce is usually preserved
-// between calls, but periodically or if nNonce is 0xffff0000 or above,
-// the block is rebuilt and nNonce starts over at zero.
-//
-unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
-{
- unsigned int& nNonce = *(unsigned int*)(pdata + 12);
- for (;;)
- {
- // Crypto++ SHA256
- // Hash pdata using pmidstate as the starting state into
- // pre-formatted buffer phash1, then hash phash1 into phash
- nNonce++;
- SHA256Transform(phash1, pdata, pmidstate);
- SHA256Transform(phash, phash1, pSHA256InitState);
-
- // Return the nonce if the hash has at least some zero bits,
- // caller will check if it has enough to reach the target
- if (((unsigned short*)phash)[14] == 0)
- return nNonce;
-
- // If nothing found after trying for a while, return -1
- if ((nNonce & 0xffff) == 0)
- {
- nHashesDone = 0xffff+1;
- return (unsigned int) -1;
- }
- if ((nNonce & 0xfff) == 0)
- boost::this_thread::interruption_point();
- }
-}
-
// Some explaining would be appreciated
class COrphan
{
@@ -162,7 +125,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
pblocktemplate->vTxSigOps.push_back(-1); // updated at end
// Largest block you're willing to create:
- unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2);
+ unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
// Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
@@ -381,16 +344,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
return pblocktemplate.release();
}
-CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
-{
- CPubKey pubkey;
- if (!reservekey.GetReservedKey(pubkey))
- return NULL;
-
- CScript scriptPubKey = CScript() << pubkey << OP_CHECKSIG;
- return CreateNewBlock(scriptPubKey);
-}
-
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
{
// Update nExtraNonce
@@ -454,6 +407,58 @@ void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash
memcpy(phash1, &tmp.hash1, 64);
}
+#ifdef ENABLE_WALLET
+//////////////////////////////////////////////////////////////////////////////
+//
+// Internal miner
+//
+double dHashesPerSec = 0.0;
+int64_t nHPSTimerStart = 0;
+
+//
+// ScanHash scans nonces looking for a hash with at least some zero bits.
+// It operates on big endian data. Caller does the byte reversing.
+// All input buffers are 16-byte aligned. nNonce is usually preserved
+// between calls, but periodically or if nNonce is 0xffff0000 or above,
+// the block is rebuilt and nNonce starts over at zero.
+//
+unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
+{
+ unsigned int& nNonce = *(unsigned int*)(pdata + 12);
+ for (;;)
+ {
+ // Crypto++ SHA256
+ // Hash pdata using pmidstate as the starting state into
+ // pre-formatted buffer phash1, then hash phash1 into phash
+ nNonce++;
+ SHA256Transform(phash1, pdata, pmidstate);
+ SHA256Transform(phash, phash1, pSHA256InitState);
+
+ // Return the nonce if the hash has at least some zero bits,
+ // caller will check if it has enough to reach the target
+ if (((unsigned short*)phash)[14] == 0)
+ return nNonce;
+
+ // If nothing found after trying for a while, return -1
+ if ((nNonce & 0xffff) == 0)
+ {
+ nHashesDone = 0xffff+1;
+ return (unsigned int) -1;
+ }
+ if ((nNonce & 0xfff) == 0)
+ boost::this_thread::interruption_point();
+ }
+}
+
+CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
+{
+ CPubKey pubkey;
+ if (!reservekey.GetReservedKey(pubkey))
+ return NULL;
+
+ CScript scriptPubKey = CScript() << pubkey << OP_CHECKSIG;
+ return CreateNewBlock(scriptPubKey);
+}
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
{
@@ -665,5 +670,5 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
}
-
+#endif
diff --git a/src/net.cpp b/src/net.cpp
index fcef9feea0..ab39be60b5 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -12,7 +12,6 @@
#include "addrman.h"
#include "chainparams.h"
#include "core.h"
-#include "db.h"
#include "ui_interface.h"
#ifdef WIN32
@@ -80,6 +79,9 @@ CCriticalSection cs_setservAddNodeAddresses;
vector<std::string> vAddedNodes;
CCriticalSection cs_vAddedNodes;
+NodeId nLastNodeId = 0;
+CCriticalSection cs_nLastNodeId;
+
static CSemaphore *semOutbound = NULL;
// Signals for message handling
@@ -581,35 +583,21 @@ bool CNode::IsBanned(CNetAddr ip)
return fResult;
}
-bool CNode::Misbehaving(int howmuch)
-{
- if (addr.IsLocal())
+bool CNode::Ban(const CNetAddr &addr) {
+ int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
{
- LogPrintf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
- return false;
+ LOCK(cs_setBanned);
+ if (setBanned[addr] < banTime)
+ setBanned[addr] = banTime;
}
-
- nMisbehavior += howmuch;
- if (nMisbehavior >= GetArg("-banscore", 100))
- {
- int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
- LogPrintf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
- {
- LOCK(cs_setBanned);
- if (setBanned[addr] < banTime)
- setBanned[addr] = banTime;
- }
- CloseSocketDisconnect();
- return true;
- } else
- LogPrintf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
- return false;
+ return true;
}
#undef X
#define X(name) stats.name = name
void CNode::copyStats(CNodeStats &stats)
{
+ stats.nodeid = this->GetId();
X(nServices);
X(nLastSend);
X(nLastRecv);
@@ -619,7 +607,6 @@ void CNode::copyStats(CNodeStats &stats)
X(cleanSubVer);
X(fInbound);
X(nStartingHeight);
- X(nMisbehavior);
X(nSendBytes);
X(nRecvBytes);
stats.fSyncNode = (this == pnodeSync);
@@ -1690,7 +1677,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
return true;
}
-void static Discover()
+void static Discover(boost::thread_group& threadGroup)
{
if (!fDiscover)
return;
@@ -1743,7 +1730,7 @@ void static Discover()
// Don't use external IPv4 discovery, when -onlynet="IPv6"
if (!IsLimited(NET_IPV4))
- boost::thread(boost::bind(&TraceThread<void (*)()>, "ext-ip", &ThreadGetMyExternalIP));
+ threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "ext-ip", &ThreadGetMyExternalIP));
}
void StartNode(boost::thread_group& threadGroup)
@@ -1757,7 +1744,7 @@ void StartNode(boost::thread_group& threadGroup)
if (pnodeLocalHost == NULL)
pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
- Discover();
+ Discover(threadGroup);
//
// Start threads
@@ -1942,3 +1929,103 @@ void CNode::Fuzz(int nChance)
// (more changes exponentially less likely):
Fuzz(2);
}
+
+//
+// CAddrDB
+//
+
+CAddrDB::CAddrDB()
+{
+ pathAddr = GetDataDir() / "peers.dat";
+}
+
+bool CAddrDB::Write(const CAddrMan& addr)
+{
+ // Generate random temporary filename
+ unsigned short randv = 0;
+ RAND_bytes((unsigned char *)&randv, sizeof(randv));
+ std::string tmpfn = strprintf("peers.dat.%04x", randv);
+
+ // serialize addresses, checksum data up to that point, then append csum
+ CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
+ ssPeers << FLATDATA(Params().MessageStart());
+ ssPeers << addr;
+ uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
+ ssPeers << hash;
+
+ // open temp output file, and associate with CAutoFile
+ boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
+ FILE *file = fopen(pathTmp.string().c_str(), "wb");
+ CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION);
+ if (!fileout)
+ return error("CAddrman::Write() : open failed");
+
+ // Write and commit header, data
+ try {
+ fileout << ssPeers;
+ }
+ catch (std::exception &e) {
+ return error("CAddrman::Write() : I/O error");
+ }
+ FileCommit(fileout);
+ fileout.fclose();
+
+ // replace existing peers.dat, if any, with new peers.dat.XXXX
+ if (!RenameOver(pathTmp, pathAddr))
+ return error("CAddrman::Write() : Rename-into-place failed");
+
+ return true;
+}
+
+bool CAddrDB::Read(CAddrMan& addr)
+{
+ // open input file, and associate with CAutoFile
+ FILE *file = fopen(pathAddr.string().c_str(), "rb");
+ CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION);
+ if (!filein)
+ return error("CAddrman::Read() : open failed");
+
+ // use file size to size memory buffer
+ int fileSize = GetFilesize(filein);
+ int dataSize = fileSize - sizeof(uint256);
+ //Don't try to resize to a negative number if file is small
+ if ( dataSize < 0 ) dataSize = 0;
+ vector<unsigned char> vchData;
+ vchData.resize(dataSize);
+ uint256 hashIn;
+
+ // read data and checksum from file
+ try {
+ filein.read((char *)&vchData[0], dataSize);
+ filein >> hashIn;
+ }
+ catch (std::exception &e) {
+ return error("CAddrman::Read() 2 : I/O error or stream data corrupted");
+ }
+ filein.fclose();
+
+ CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
+
+ // verify stored checksum matches input data
+ uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
+ if (hashIn != hashTmp)
+ return error("CAddrman::Read() : checksum mismatch; data corrupted");
+
+ unsigned char pchMsgTmp[4];
+ try {
+ // de-serialize file header (network specific magic number) and ..
+ ssPeers >> FLATDATA(pchMsgTmp);
+
+ // ... verify the network matches ours
+ if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
+ return error("CAddrman::Read() : invalid network magic number");
+
+ // de-serialize address data into one CAddrMan object
+ ssPeers >> addr;
+ }
+ catch (std::exception &e) {
+ return error("CAddrman::Read() : I/O error or stream data corrupted");
+ }
+
+ return true;
+}
diff --git a/src/net.h b/src/net.h
index effce35dc4..5835001739 100644
--- a/src/net.h
+++ b/src/net.h
@@ -57,14 +57,19 @@ void StartNode(boost::thread_group& threadGroup);
bool StopNode();
void SocketSendData(CNode *pnode);
+typedef int NodeId;
+
// Signals for message handling
struct CNodeSignals
{
boost::signals2::signal<int ()> GetHeight;
boost::signals2::signal<bool (CNode*)> ProcessMessages;
boost::signals2::signal<bool (CNode*, bool)> SendMessages;
+ boost::signals2::signal<void (NodeId, const CNode*)> InitializeNode;
+ boost::signals2::signal<void (NodeId)> FinalizeNode;
};
+
CNodeSignals& GetNodeSignals();
@@ -109,12 +114,14 @@ extern limitedmap<CInv, int64_t> mapAlreadyAskedFor;
extern std::vector<std::string> vAddedNodes;
extern CCriticalSection cs_vAddedNodes;
-
+extern NodeId nLastNodeId;
+extern CCriticalSection cs_nLastNodeId;
class CNodeStats
{
public:
+ NodeId nodeid;
uint64_t nServices;
int64_t nLastSend;
int64_t nLastRecv;
@@ -124,7 +131,6 @@ public:
std::string cleanSubVer;
bool fInbound;
int nStartingHeight;
- int nMisbehavior;
uint64_t nSendBytes;
uint64_t nRecvBytes;
bool fSyncNode;
@@ -223,13 +229,13 @@ public:
CCriticalSection cs_filter;
CBloomFilter* pfilter;
int nRefCount;
+ NodeId id;
protected:
// Denial-of-service detection/prevention
// Key is IP address, value is banned-until-time
static std::map<CNetAddr, int64_t> setBanned;
static CCriticalSection cs_setBanned;
- int nMisbehavior;
// Basic fuzz-testing
void Fuzz(int nChance); // modifies ssSend
@@ -289,7 +295,6 @@ public:
nStartingHeight = -1;
fStartSync = false;
fGetAddr = false;
- nMisbehavior = 0;
fRelayTxes = false;
setInventoryKnown.max_size(SendBufferSize() / 1000);
pfilter = new CBloomFilter();
@@ -298,9 +303,16 @@ public:
nPingUsecTime = 0;
fPingQueued = false;
+ {
+ LOCK(cs_nLastNodeId);
+ id = nLastNodeId++;
+ }
+
// Be shy and don't send version until we hear
if (hSocket != INVALID_SOCKET && !fInbound)
PushVersion();
+
+ GetNodeSignals().InitializeNode(GetId(), this);
}
~CNode()
@@ -312,6 +324,7 @@ public:
}
if (pfilter)
delete pfilter;
+ GetNodeSignals().FinalizeNode(GetId());
}
private:
@@ -326,6 +339,9 @@ private:
public:
+ NodeId GetId() const {
+ return id;
+ }
int GetRefCount()
{
@@ -673,7 +689,7 @@ public:
// new code.
static void ClearBanned(); // needed for unit testing
static bool IsBanned(CNetAddr ip);
- bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
+ static bool Ban(const CNetAddr &ip);
void copyStats(CNodeStats &stats);
// Network stats
@@ -690,4 +706,15 @@ class CTransaction;
void RelayTransaction(const CTransaction& tx, const uint256& hash);
void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss);
+/** Access to the (IP) address database (peers.dat) */
+class CAddrDB
+{
+private:
+ boost::filesystem::path pathAddr;
+public:
+ CAddrDB();
+ bool Write(const CAddrMan& addr);
+ bool Read(CAddrMan& addr);
+};
+
#endif
diff --git a/src/noui.cpp b/src/noui.cpp
index fd285c5719..86954f3c34 100644
--- a/src/noui.cpp
+++ b/src/noui.cpp
@@ -34,11 +34,6 @@ static bool noui_ThreadSafeMessageBox(const std::string& message, const std::str
return false;
}
-static bool noui_ThreadSafeAskFee(int64_t /*nFeeRequired*/)
-{
- return true;
-}
-
static void noui_InitMessage(const std::string &message)
{
LogPrintf("init message: %s\n", message.c_str());
@@ -48,6 +43,5 @@ void noui_connect()
{
// Connect bitcoind signal handlers
uiInterface.ThreadSafeMessageBox.connect(noui_ThreadSafeMessageBox);
- uiInterface.ThreadSafeAskFee.connect(noui_ThreadSafeAskFee);
uiInterface.InitMessage.connect(noui_InitMessage);
}
diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am
index e302adc89f..434373da29 100644
--- a/src/qt/Makefile.am
+++ b/src/qt/Makefile.am
@@ -96,6 +96,7 @@ QT_MOC_CPP = moc_aboutdialog.cpp moc_addressbookpage.cpp \
moc_optionsmodel.cpp moc_overviewpage.cpp moc_paymentserver.cpp \
moc_receiverequestdialog.cpp moc_qvalidatedlineedit.cpp moc_qvaluecombobox.cpp \
moc_receivecoinsdialog.cpp \
+ moc_recentrequeststablemodel.cpp \
moc_rpcconsole.cpp moc_sendcoinsdialog.cpp moc_sendcoinsentry.cpp \
moc_signverifymessagedialog.cpp moc_splashscreen.cpp moc_trafficgraphwidget.cpp moc_transactiondesc.cpp \
moc_transactiondescdialog.cpp moc_transactionfilterproxy.cpp \
@@ -122,6 +123,7 @@ BITCOIN_QT_H = aboutdialog.h addressbookpage.h addresstablemodel.h \
optionsdialog.h \
optionsmodel.h overviewpage.h paymentrequestplus.h paymentserver.h \
receivecoinsdialog.h \
+ recentrequeststablemodel.h \
receiverequestdialog.h qvalidatedlineedit.h qvaluecombobox.h rpcconsole.h \
sendcoinsdialog.h sendcoinsentry.h signverifymessagedialog.h splashscreen.h \
trafficgraphwidget.h transactiondescdialog.h transactiondesc.h transactionfilterproxy.h \
@@ -157,6 +159,7 @@ BITCOIN_QT_CPP = aboutdialog.cpp addressbookpage.cpp \
optionsdialog.cpp optionsmodel.cpp overviewpage.cpp paymentrequestplus.cpp \
paymentserver.cpp qvalidatedlineedit.cpp qvaluecombobox.cpp \
receivecoinsdialog.cpp receiverequestdialog.cpp \
+ recentrequeststablemodel.cpp \
rpcconsole.cpp sendcoinsdialog.cpp sendcoinsentry.cpp \
signverifymessagedialog.cpp splashscreen.cpp trafficgraphwidget.cpp transactiondesc.cpp \
transactiondescdialog.cpp transactionfilterproxy.cpp transactionrecord.cpp \
@@ -197,7 +200,7 @@ endif
bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) \
-I$(top_srcdir)/src/qt/forms
bitcoin_qt_SOURCES = bitcoin.cpp
-bitcoin_qt_LDADD = libbitcoinqt.a $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
+bitcoin_qt_LDADD = libbitcoinqt.a $(LIBBITCOIN_SERVER) $(LIBBITCOIN_WALLET) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
# forms/foo.h -> forms/ui_foo.h
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index d686cd4fd8..5e7d8e6178 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -297,7 +297,7 @@ QVariant AddressTableModel::headerData(int section, Qt::Orientation orientation,
{
if(orientation == Qt::Horizontal)
{
- if(role == Qt::DisplayRole)
+ if(role == Qt::DisplayRole && section < columns.size())
{
return columns[section];
}
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 57ce7da361..657b42d16a 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -17,6 +17,7 @@
#include "main.h"
#include "ui_interface.h"
#include "util.h"
+#include "wallet.h"
#include <stdint.h>
@@ -53,7 +54,6 @@ static SplashScreen *splashref;
static bool ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
{
- // Message from network thread
if(guiref)
{
bool modal = (style & CClientUIInterface::MODAL);
@@ -75,22 +75,6 @@ static bool ThreadSafeMessageBox(const std::string& message, const std::string&
}
}
-static bool ThreadSafeAskFee(int64_t nFeeRequired)
-{
- if(!guiref)
- return false;
- if(nFeeRequired < CTransaction::nMinTxFee || nFeeRequired <= nTransactionFee || fDaemon)
- return true;
-
- bool payFee = false;
-
- QMetaObject::invokeMethod(guiref, "askFee", GUIUtil::blockingGUIThreadConnection(),
- Q_ARG(qint64, nFeeRequired),
- Q_ARG(bool*, &payFee));
-
- return payFee;
-}
-
static void InitMessage(const std::string &message)
{
if(splashref)
@@ -160,17 +144,17 @@ static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTrans
/* qDebug() message handler --> debug.log */
#if QT_VERSION < 0x050000
-void DebugMessageHandler(QtMsgType type, const char * msg)
+void DebugMessageHandler(QtMsgType type, const char *msg)
{
Q_UNUSED(type);
- LogPrint("qt", "Bitcoin-Qt: %s\n", msg);
+ LogPrint("qt", "GUI: %s\n", msg);
}
#else
void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
{
Q_UNUSED(type);
Q_UNUSED(context);
- LogPrint("qt", "Bitcoin-Qt: %s\n", qPrintable(msg));
+ LogPrint("qt", "GUI: %s\n", qPrintable(msg));
}
#endif
@@ -201,15 +185,23 @@ int main(int argc, char *argv[])
Q_INIT_RESOURCE(bitcoin);
QApplication app(argc, argv);
+#if QT_VERSION > 0x050100
+ // Generate high-dpi pixmaps
+ QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
+#endif
+#ifdef Q_OS_MAC
+ QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
+#endif
// Register meta types used for QMetaObject::invokeMethod
qRegisterMetaType< bool* >();
// Application identification (must be set before OptionsModel is initialized,
// as it is used to locate QSettings)
+ bool isaTestNet = TestNet() || RegTest();
QApplication::setOrganizationName("Bitcoin");
QApplication::setOrganizationDomain("bitcoin.org");
- if (TestNet()) // Separate UI settings for testnet
+ if (isaTestNet) // Separate UI settings for testnets
QApplication::setApplicationName("Bitcoin-Qt-testnet");
else
QApplication::setApplicationName("Bitcoin-Qt");
@@ -240,7 +232,7 @@ int main(int argc, char *argv[])
PaymentServer* paymentServer = new PaymentServer(&app);
// User language is set up: pick a data directory
- Intro::pickDataDirectory(TestNet());
+ Intro::pickDataDirectory(isaTestNet);
// Install global event filter that makes sure that long tooltips can be word-wrapped
app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
@@ -256,7 +248,6 @@ int main(int argc, char *argv[])
// Subscribe to global signals from core
uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
- uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
uiInterface.InitMessage.connect(InitMessage);
uiInterface.Translate.connect(Translate);
@@ -269,7 +260,7 @@ int main(int argc, char *argv[])
return 1;
}
- SplashScreen splash(QPixmap(), 0);
+ SplashScreen splash(QPixmap(), 0, isaTestNet);
if (GetBoolArg("-splash", true) && !GetBoolArg("-min", false))
{
splash.show();
@@ -291,7 +282,7 @@ int main(int argc, char *argv[])
boost::thread_group threadGroup;
- BitcoinGUI window(TestNet(), 0);
+ BitcoinGUI window(isaTestNet, 0);
guiref = &window;
QTimer* pollShutdownTimer = new QTimer(guiref);
@@ -313,11 +304,12 @@ int main(int argc, char *argv[])
splash.finish(&window);
ClientModel clientModel(&optionsModel);
+ window.setClientModel(&clientModel);
+
WalletModel *walletModel = 0;
if(pwalletMain)
walletModel = new WalletModel(pwalletMain, &optionsModel);
- window.setClientModel(&clientModel);
if(walletModel)
{
window.addWallet("~Default", walletModel);
@@ -357,7 +349,7 @@ int main(int argc, char *argv[])
guiref = 0;
delete walletModel;
}
- // Shutdown the core and its threads, but don't exit Bitcoin-Qt here
+ // Shutdown the core and its threads, but don't exit the GUI here
threadGroup.interrupt_all();
threadGroup.join_all();
Shutdown();
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index 6b083331d3..1698595188 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -14,8 +14,10 @@
#include <QKeyEvent>
#include <qmath.h> // for qPow()
-BitcoinAmountField::BitcoinAmountField(QWidget *parent):
- QWidget(parent), amount(0), currentUnit(-1)
+BitcoinAmountField::BitcoinAmountField(QWidget *parent) :
+ QWidget(parent),
+ amount(0),
+ currentUnit(-1)
{
amount = new QDoubleSpinBox(this);
amount->setLocale(QLocale::c());
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index a44627690f..2d0f51a3fb 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -69,28 +69,32 @@ BitcoinGUI::BitcoinGUI(bool fIsTestnet, QWidget *parent) :
{
GUIUtil::restoreWindowGeometry("nWindow", QSize(850, 550), this);
-#ifndef Q_OS_MAC
if (!fIsTestnet)
{
- setWindowTitle(tr("Bitcoin") + " - " + tr("Wallet"));
+ setWindowTitle(tr("Bitcoin Core") + " - " + tr("Wallet"));
+#ifndef Q_OS_MAC
QApplication::setWindowIcon(QIcon(":icons/bitcoin"));
setWindowIcon(QIcon(":icons/bitcoin"));
+#else
+ MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin"));
+#endif
}
else
{
- setWindowTitle(tr("Bitcoin") + " - " + tr("Wallet") + " " + tr("[testnet]"));
+ setWindowTitle(tr("Bitcoin Core") + " - " + tr("Wallet") + " " + tr("[testnet]"));
+#ifndef Q_OS_MAC
QApplication::setWindowIcon(QIcon(":icons/bitcoin_testnet"));
setWindowIcon(QIcon(":icons/bitcoin_testnet"));
- }
#else
- setUnifiedTitleAndToolBarOnMac(true);
- QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
-
- if (!fIsTestnet)
- MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin"));
- else
MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
#endif
+ }
+
+#if defined(Q_OS_MAC) && QT_VERSION < 0x050000
+ // This property is not implemented in Qt 5. Setting it has no effect.
+ // A replacement API (QtMacUnifiedToolBar) is available in QtMacExtras.
+ setUnifiedTitleAndToolBarOnMac(true);
+#endif
// Create wallet frame and make it the central widget
walletFrame = new WalletFrame(this);
@@ -211,6 +215,8 @@ void BitcoinGUI::createActions(bool fIsTestnet)
historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
tabGroup->addAction(historyAction);
+ // These showNormalIfMinimized are needed because Send Coins and Receive Coins
+ // can be triggered from the tray menu, and need to show the GUI to be useful.
connect(overviewAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
@@ -225,9 +231,9 @@ void BitcoinGUI::createActions(bool fIsTestnet)
quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q));
quitAction->setMenuRole(QAction::QuitRole);
if (!fIsTestnet)
- aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin"), this);
+ aboutAction = new QAction(QIcon(":/icons/bitcoin"), tr("&About Bitcoin Core"), this);
else
- aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Bitcoin"), this);
+ aboutAction = new QAction(QIcon(":/icons/bitcoin_testnet"), tr("&About Bitcoin Core"), this);
aboutAction->setStatusTip(tr("Show information about Bitcoin"));
aboutAction->setMenuRole(QAction::AboutRole);
#if QT_VERSION < 0x050000
@@ -327,6 +333,7 @@ void BitcoinGUI::createToolBars()
toolbar->addAction(sendCoinsAction);
toolbar->addAction(receiveCoinsAction);
toolbar->addAction(historyAction);
+ overviewAction->setChecked(true);
}
void BitcoinGUI::setClientModel(ClientModel *clientModel)
@@ -405,7 +412,7 @@ void BitcoinGUI::createTrayIcon(bool fIsTestnet)
trayIcon->show();
#endif
- notificator = new Notificator(QApplication::applicationName(), trayIcon);
+ notificator = new Notificator(QApplication::applicationName(), trayIcon, this);
}
void BitcoinGUI::createTrayIconMenu()
@@ -722,19 +729,6 @@ void BitcoinGUI::closeEvent(QCloseEvent *event)
QMainWindow::closeEvent(event);
}
-void BitcoinGUI::askFee(qint64 nFeeRequired, bool *payFee)
-{
- if (!clientModel || !clientModel->getOptionsModel())
- return;
-
- QString strMessage = tr("This transaction is over the size limit. You can still send it for a fee of %1, "
- "which goes to the nodes that process your transaction and helps to support the network. "
- "Do you want to pay the fee?").arg(BitcoinUnits::formatWithUnit(clientModel->getOptionsModel()->getDisplayUnit(), nFeeRequired));
- QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm transaction fee"), strMessage,
- QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
- *payFee = (retval == QMessageBox::Yes);
-}
-
void BitcoinGUI::incomingTransaction(const QString& date, int unit, qint64 amount, const QString& type, const QString& address)
{
// On new transaction, make an info balloon
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index b9a8a03139..75c61d2a8a 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -135,16 +135,6 @@ public slots:
*/
void message(const QString &title, const QString &message, unsigned int style, bool *ret = NULL);
- /** Asks the user whether to pay the transaction fee or to cancel the transaction.
- It is currently not possible to pass a return value to another thread through
- BlockingQueuedConnection, so an indirected pointer is used.
- https://bugreports.qt-project.org/browse/QTBUG-10440
-
- @param[in] nFeeRequired the required fee
- @param[out] payFee true to pay the fee, false to not pay the fee
- */
- void askFee(qint64 nFeeRequired, bool *payFee);
-
bool handlePaymentRequest(const SendCoinsRecipient& recipient);
/** Show incoming transaction notification for new transactions. */
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 45a9bf6a41..183a98061d 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -61,8 +61,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Number of seconds to keep misbehaving peers from reconnecting (default: "
"86400)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Set maximum size of high-priority/low-fee transactions in bytes (default: "
-"27000)"),
+"Output debugging information (default: 0, supplying <category> is optional)"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Set the number of script verification threads (up to 16, 0 = auto, <0 = "
"leave that many cores free, default: 0)"),
@@ -72,6 +73,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Unable to bind to %s on this computer. Bitcoin is probably already running."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -"
+"proxy)"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Warning: -paytxfee is set very high! This is the transaction fee you will "
"pay if you send a transaction."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -95,21 +99,22 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"%s\n"
"If the file does not exist, create it with owner-readable-only file "
"permissions."),
+QT_TRANSLATE_NOOP("bitcoin-core", "<category> can be:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Accept command line and JSON-RPC commands"),
QT_TRANSLATE_NOOP("bitcoin-core", "Accept connections from outside (default: 1 if no -proxy or -connect)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Add a node to connect to and attempt to keep the connection open"),
QT_TRANSLATE_NOOP("bitcoin-core", "Allow DNS lookups for -addnode, -seednode and -connect"),
QT_TRANSLATE_NOOP("bitcoin-core", "Allow JSON-RPC connections from specified IP address"),
QT_TRANSLATE_NOOP("bitcoin-core", "Attempt to recover private keys from a corrupt wallet.dat"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin Core Daemon"),
QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin RPC client version"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin version"),
QT_TRANSLATE_NOOP("bitcoin-core", "Block creation options:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot downgrade wallet"),
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -bind address: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot resolve -externalip address: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Cannot write default address"),
QT_TRANSLATE_NOOP("bitcoin-core", "Connect only to the specified node(s)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Connect through socks proxy"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Connect through SOCKS proxy"),
QT_TRANSLATE_NOOP("bitcoin-core", "Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Connect to a node to retrieve peer addresses, and disconnect"),
QT_TRANSLATE_NOOP("bitcoin-core", "Corrupted block database detected"),
@@ -138,12 +143,13 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write file info"),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write to coin database"),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write transaction index"),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write undo data"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Fee per KB to add to transactions you send"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Fee per kB to add to transactions you send"),
QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using DNS lookup (default: 1 unless -connect)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins (default: 0)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"),
QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: 288, 0 = all)"),
QT_TRANSLATE_NOOP("bitcoin-core", "How thorough the block verification is (0-4, default: 3)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "If <category> is not supplied, output all debugging information."),
QT_TRANSLATE_NOOP("bitcoin-core", "Imports blocks from external blk000??.dat file"),
QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"),
QT_TRANSLATE_NOOP("bitcoin-core", "Information"),
@@ -167,16 +173,15 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Not enough file descriptors available."),
QT_TRANSLATE_NOOP("bitcoin-core", "Only accept block chain matching built-in checkpoints (default: 1)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Only connect to nodes in network <net> (IPv4, IPv6 or Tor)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Options:"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Output extra debugging information. Implies all other -debug* options"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Output extra network debugging information"),
QT_TRANSLATE_NOOP("bitcoin-core", "Password for JSON-RPC connections"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Prepend debug output with timestamp"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Prepend debug output with timestamp (default: 1)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "RPC client options:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Rebuild block chain index from current blk000??.dat files"),
QT_TRANSLATE_NOOP("bitcoin-core", "Rescan the block chain for missing wallet transactions"),
QT_TRANSLATE_NOOP("bitcoin-core", "Rescanning..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Run in the background as a daemon and accept commands"),
QT_TRANSLATE_NOOP("bitcoin-core", "SSL options: (see the Bitcoin Wiki for SSL setup instructions)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Select the version of socks proxy to use (4-5, default: 5)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Select SOCKS version for -proxy (4 or 5, default: 5)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Send command to Bitcoin server"),
QT_TRANSLATE_NOOP("bitcoin-core", "Send commands to node running on <ip> (default: 127.0.0.1)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Send trace/debug info to console instead of debug.log file"),
@@ -185,7 +190,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Server certificate file (default: server.cert
QT_TRANSLATE_NOOP("bitcoin-core", "Server private key (default: server.pem)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set database cache size in megabytes (default: 25)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set key pool size to <n> (default: 100)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block size in bytes (default: 250000)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Set maximum block size in bytes (default: %d)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set minimum block size in bytes (default: 0)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Set the number of threads to service RPC calls (default: 4)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Shrink debug.log file on client startup (default: 1 when no -debug)"),
@@ -213,15 +218,17 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Usage:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Use OpenSSL (https) for JSON-RPC connections"),
QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 0)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: 1 when listening)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Use proxy to reach tor hidden services (default: same as -proxy)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Use the test network"),
QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"),
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying blocks..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying wallet..."),
+QT_TRANSLATE_NOOP("bitcoin-core", "Wait for RPC server to start"),
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet %s resides outside data directory %s"),
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoin to complete"),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Deprecated argument -debugnet ignored, use -debug=net"),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete, upgrade required!"),
QT_TRANSLATE_NOOP("bitcoin-core", "You need to rebuild the database using -reindex to change -txindex"),
+QT_TRANSLATE_NOOP("bitcoin-core", "version"),
QT_TRANSLATE_NOOP("bitcoin-core", "wallet.dat corrupt, salvage failed"),
};
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index c64e411bca..f273b9ea46 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -123,9 +123,12 @@ void ClientModel::updateAlert(const QString &hash, int status)
emit alertsChanged(getStatusBarWarnings());
}
-bool ClientModel::isTestNet() const
+QString ClientModel::getNetworkName() const
{
- return TestNet();
+ QString netname(QString::fromStdString(Params().DataDir()));
+ if(netname.isEmpty())
+ netname = "main";
+ return netname;
}
bool ClientModel::inInitialBlockDownload() const
diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h
index dcc528f4fd..ca735f14ce 100644
--- a/src/qt/clientmodel.h
+++ b/src/qt/clientmodel.h
@@ -46,8 +46,8 @@ public:
double getVerificationProgress() const;
QDateTime getLastBlockDate() const;
- //! Return true if client connected to testnet
- bool isTestNet() const;
+ //! Return network (main, testnet3, regtest)
+ QString getNetworkName() const;
//! Return true if core is doing initial block download
bool inInitialBlockDownload() const;
//! Return true if core is importing blocks
@@ -84,7 +84,7 @@ signals:
void alertsChanged(const QString &warnings);
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut);
- //! Asynchronous message notification
+ //! Fired when a message should be reported to the user
void message(const QString &title, const QString &message, unsigned int style);
public slots:
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 14e5b07133..b4e6aeb1dd 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -20,7 +20,6 @@
#include <QCheckBox>
#include <QColor>
#include <QCursor>
-#include <QDateTime>
#include <QDialogButtonBox>
#include <QFlags>
#include <QIcon>
@@ -730,7 +729,7 @@ void CoinControlDialog::updateView()
itemOutput->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(out.tx->vout[out.i].nValue), 15, " ")); // padding so that sorting works correctly
// date
- itemOutput->setText(COLUMN_DATE, QDateTime::fromTime_t(out.tx->GetTxTime()).toString("yy-MM-dd hh:mm"));
+ itemOutput->setText(COLUMN_DATE, GUIUtil::dateTimeStr(out.tx->GetTxTime()));
// confirmations
itemOutput->setText(COLUMN_CONFIRMATIONS, strPad(QString::number(out.nDepth), 8, " "));
diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp
index 618567218f..46982cc339 100644
--- a/src/qt/editaddressdialog.cpp
+++ b/src/qt/editaddressdialog.cpp
@@ -13,7 +13,10 @@
EditAddressDialog::EditAddressDialog(Mode mode, QWidget *parent) :
QDialog(parent),
- ui(new Ui::EditAddressDialog), mapper(0), mode(mode), model(0)
+ ui(new Ui::EditAddressDialog),
+ mapper(0),
+ mode(mode),
+ model(0)
{
ui->setupUi(this);
diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui
index 80768f89b0..10a5857cab 100644
--- a/src/qt/forms/aboutdialog.ui
+++ b/src/qt/forms/aboutdialog.ui
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
- <string>About Bitcoin</string>
+ <string>About Bitcoin Core</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
@@ -50,7 +50,7 @@
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
- <string>&lt;b&gt;Bitcoin&lt;/b&gt; version</string>
+ <string>&lt;b&gt;Bitcoin Core&lt;/b&gt; version</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
@@ -91,7 +91,7 @@
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
- <string notr="true">Copyright &amp;copy; 2009-YYYY The Bitcoin developers</string>
+ <string notr="true">Copyright &amp;copy; 2009-YYYY The Bitcoin Core developers</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
diff --git a/src/qt/forms/intro.ui b/src/qt/forms/intro.ui
index 0f6ae5a7d0..05ee9466c4 100644
--- a/src/qt/forms/intro.ui
+++ b/src/qt/forms/intro.ui
@@ -20,7 +20,7 @@
<string notr="true">QLabel { font-style:italic; }</string>
</property>
<property name="text">
- <string>Welcome to Bitcoin-Qt.</string>
+ <string>Welcome to Bitcoin Core.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -46,7 +46,7 @@
<item>
<widget class="QLabel" name="label_4">
<property name="text">
- <string>As this is the first time the program is launched, you can choose where Bitcoin-Qt will store its data.</string>
+ <string>As this is the first time the program is launched, you can choose where Bitcoin Core will store its data.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -56,7 +56,7 @@
<item>
<widget class="QLabel" name="sizeWarningLabel">
<property name="text">
- <string>Bitcoin-Qt will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory.</string>
+ <string>Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui
index 6d1a72ecd2..e7138f5371 100644
--- a/src/qt/forms/receivecoinsdialog.ui
+++ b/src/qt/forms/receivecoinsdialog.ui
@@ -7,35 +7,60 @@
<x>0</x>
<y>0</y>
<width>776</width>
- <height>343</height>
+ <height>364</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
- <item row="3" column="0">
- <widget class="QLabel" name="label">
+ <item row="7" column="2">
+ <widget class="QCheckBox" name="reuseAddress">
+ <property name="toolTip">
+ <string>Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before.</string>
+ </property>
<property name="text">
- <string>&amp;Amount:</string>
+ <string>R&amp;euse an existing receiving address (not recommended)</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>&amp;Message:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
- <cstring>reqAmount</cstring>
+ <cstring>reqMessage</cstring>
</property>
</widget>
</item>
- <item row="3" column="1">
- <widget class="BitcoinAmountField" name="reqAmount">
- <property name="minimumSize">
- <size>
- <width>80</width>
- <height>0</height>
- </size>
+ <item row="4" column="2">
+ <widget class="QLineEdit" name="reqLabel">
+ <property name="toolTip">
+ <string>The label to associate with the new receiving address</string>
</property>
+ </widget>
+ </item>
+ <item row="6" column="2">
+ <widget class="QLineEdit" name="reqMessage">
<property name="toolTip">
- <string>The amount to request</string>
+ <string>The message to attach to payment request</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Use this form to request payments. All fields are optional.</string>
</property>
</widget>
</item>
@@ -52,73 +77,35 @@
</property>
</widget>
</item>
- <item row="4" column="1">
- <widget class="QLineEdit" name="reqLabel">
- <property name="toolTip">
- <string>The label to associate with the receiving address</string>
- </property>
- </widget>
- </item>
<item row="5" column="0">
- <widget class="QLabel" name="label_3">
+ <widget class="QLabel" name="label">
<property name="text">
- <string>&amp;Message:</string>
+ <string>&amp;Amount:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
- <cstring>reqMessage</cstring>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QLineEdit" name="reqMessage">
- <property name="toolTip">
- <string>The message to attach to payment request</string>
+ <cstring>reqAmount</cstring>
</property>
</widget>
</item>
- <item row="6" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string/>
+ <item row="5" column="2">
+ <widget class="BitcoinAmountField" name="reqAmount">
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>0</height>
+ </size>
</property>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QCheckBox" name="reuseAddress">
<property name="toolTip">
- <string>Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before.</string>
- </property>
- <property name="text">
- <string>R&amp;euse an existing receiving address (not recommended)</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>Use this form to request payments. All fields are optional.</string>
+ <string>The amount to request</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="clearButton">
@@ -178,6 +165,98 @@
</item>
</layout>
</item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QFrame" name="frame">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_6">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Previously requested payments</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableView" name="recentRequestsView"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QPushButton" name="showRequestButton">
+ <property name="toolTip">
+ <string>Show the selected request (does the same as double clicking an entry)</string>
+ </property>
+ <property name="text">
+ <string>Show</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/edit</normaloff>:/icons/edit</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="removeRequestButton">
+ <property name="toolTip">
+ <string>Remove the selected entries from the list</string>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
</layout>
</widget>
<customwidgets>
@@ -187,6 +266,17 @@
<header>bitcoinamountfield.h</header>
</customwidget>
</customwidgets>
+ <tabstops>
+ <tabstop>reqLabel</tabstop>
+ <tabstop>reqAmount</tabstop>
+ <tabstop>reqMessage</tabstop>
+ <tabstop>reuseAddress</tabstop>
+ <tabstop>clearButton</tabstop>
+ <tabstop>receiveButton</tabstop>
+ <tabstop>recentRequestsView</tabstop>
+ <tabstop>showRequestButton</tabstop>
+ <tabstop>removeRequestButton</tabstop>
+ </tabstops>
<resources>
<include location="../bitcoin.qrc"/>
</resources>
diff --git a/src/qt/forms/receiverequestdialog.ui b/src/qt/forms/receiverequestdialog.ui
index c9cb3de69f..85928c9be5 100644
--- a/src/qt/forms/receiverequestdialog.ui
+++ b/src/qt/forms/receiverequestdialog.ui
@@ -84,13 +84,6 @@
</widget>
</item>
<item>
- <widget class="QPushButton" name="btnCopyImage">
- <property name="text">
- <string>&amp;Copy Image</string>
- </property>
- </widget>
- </item>
- <item>
<widget class="QPushButton" name="btnSaveAs">
<property name="text">
<string>&amp;Save Image...</string>
diff --git a/src/qt/forms/rpcconsole.ui b/src/qt/forms/rpcconsole.ui
index c77c5a384c..69504f3159 100644
--- a/src/qt/forms/rpcconsole.ui
+++ b/src/qt/forms/rpcconsole.ui
@@ -36,7 +36,7 @@
</font>
</property>
<property name="text">
- <string>Bitcoin Core</string>
+ <string>General</string>
</property>
</widget>
</item>
@@ -172,14 +172,14 @@
</widget>
</item>
<item row="7" column="0">
- <widget class="QLabel" name="label_7">
+ <widget class="QLabel" name="label_8">
<property name="text">
- <string>Number of connections</string>
+ <string>Name</string>
</property>
</widget>
</item>
<item row="7" column="1">
- <widget class="QLabel" name="numberOfConnections">
+ <widget class="QLabel" name="networkName">
<property name="cursor">
<cursorShape>IBeamCursor</cursorShape>
</property>
@@ -195,19 +195,25 @@
</widget>
</item>
<item row="8" column="0">
- <widget class="QLabel" name="label_8">
+ <widget class="QLabel" name="label_7">
<property name="text">
- <string>On testnet</string>
+ <string>Number of connections</string>
</property>
</widget>
</item>
<item row="8" column="1">
- <widget class="QCheckBox" name="isTestNet">
- <property name="enabled">
- <bool>false</bool>
+ <widget class="QLabel" name="numberOfConnections">
+ <property name="cursor">
+ <cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
- <string/>
+ <string>N/A</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
@@ -348,7 +354,7 @@
<item row="17" column="0">
<widget class="QPushButton" name="showCLOptionsButton">
<property name="toolTip">
- <string>Show the Bitcoin-Qt help message to get a list with possible Bitcoin command-line options.</string>
+ <string>Show the Bitcoin-Core help message to get a list with possible Bitcoin command-line options.</string>
</property>
<property name="text">
<string>&amp;Show</string>
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 2ce09b479e..b87498402d 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -32,6 +32,7 @@
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
+
#include <QAbstractItemView>
#include <QApplication>
#include <QClipboard>
@@ -593,7 +594,7 @@ void restoreWindowGeometry(const QString& strSetting, const QSize& defaultSize,
HelpMessageBox::HelpMessageBox(QWidget *parent) :
QMessageBox(parent)
{
- header = tr("Bitcoin-Qt") + " " + tr("version") + " " +
+ header = tr("Bitcoin Core") + " " + tr("version") + " " +
QString::fromStdString(FormatFullVersion()) + "\n\n" +
tr("Usage:") + "\n" +
" bitcoin-qt [" + tr("command-line options") + "] " + "\n";
@@ -606,7 +607,7 @@ HelpMessageBox::HelpMessageBox(QWidget *parent) :
" -splash " + tr("Show splash screen on startup (default: 1)") + "\n" +
" -choosedatadir " + tr("Choose data directory on startup (default: 0)") + "\n";
- setWindowTitle(tr("Bitcoin-Qt"));
+ setWindowTitle(tr("Bitcoin Core"));
setTextFormat(Qt::PlainText);
// setMinimumWidth is ignored for QMessageBox so put in non-breaking spaces to make it wider.
setText(header + QString(QChar(0x2003)).repeated(50));
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 0dc56ac5dc..368a4d6003 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -5,13 +5,13 @@
<name>AboutDialog</name>
<message>
<location filename="../forms/aboutdialog.ui" line="+14"/>
- <source>About Bitcoin</source>
- <translation>About Bitcoin</translation>
+ <source>About Bitcoin Core</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+39"/>
- <source>&lt;b&gt;Bitcoin&lt;/b&gt; version</source>
- <translation>&lt;b&gt;Bitcoin&lt;/b&gt; version</translation>
+ <source>&lt;b&gt;Bitcoin Core&lt;/b&gt; version</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+57"/>
@@ -29,7 +29,7 @@ Distributed under the MIT/X11 software license, see the accompanying file COPYIN
This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/) and cryptographic software written by Eric Young (eay@cryptsoft.com) and UPnP software written by Thomas Bernard.</translation>
</message>
<message>
- <location filename="../aboutdialog.cpp" line="+14"/>
+ <location filename="../aboutdialog.cpp" line="+19"/>
<source>Copyright</source>
<translation>Copyright</translation>
</message>
@@ -72,7 +72,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../addressbookpage.cpp" line="+72"/>
+ <location filename="../addressbookpage.cpp" line="+74"/>
<source>&amp;Copy Address</source>
<translation>&amp;Copy Address</translation>
</message>
@@ -142,7 +142,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Edit</translation>
</message>
<message>
- <location line="+197"/>
+ <location line="+194"/>
<source>Export Address List</source>
<translation type="unfinished"></translation>
</message>
@@ -165,7 +165,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<context>
<name>AddressTableModel</name>
<message>
- <location filename="../addresstablemodel.cpp" line="+164"/>
+ <location filename="../addresstablemodel.cpp" line="+168"/>
<source>Label</source>
<translation>Label</translation>
</message>
@@ -203,7 +203,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Repeat new passphrase</translation>
</message>
<message>
- <location filename="../askpassphrasedialog.cpp" line="+34"/>
+ <location filename="../askpassphrasedialog.cpp" line="+40"/>
<source>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;10 or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</source>
<translation>Enter the new passphrase to the wallet.&lt;br/&gt;Please use a passphrase of &lt;b&gt;10 or more random characters&lt;/b&gt;, or &lt;b&gt;eight or more words&lt;/b&gt;.</translation>
</message>
@@ -324,17 +324,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="+250"/>
+ <location filename="../bitcoingui.cpp" line="+260"/>
<source>Sign &amp;message...</source>
<translation>Sign &amp;message...</translation>
</message>
<message>
- <location line="+254"/>
+ <location line="+290"/>
<source>Synchronizing with network...</source>
<translation>Synchronizing with network...</translation>
</message>
<message>
- <location line="-324"/>
+ <location line="-360"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
@@ -400,7 +400,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Change Passphrase...</translation>
</message>
<message>
- <location line="+259"/>
+ <location line="+295"/>
<source>Importing blocks from disk...</source>
<translation>Importing blocks from disk...</translation>
</message>
@@ -410,7 +410,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Reindexing blocks on disk...</translation>
</message>
<message>
- <location line="-322"/>
+ <location line="-358"/>
<source>Send coins to a Bitcoin address</source>
<translation>Send coins to a Bitcoin address</translation>
</message>
@@ -445,20 +445,18 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Verify message...</translation>
</message>
<message>
- <location line="-180"/>
- <location line="+6"/>
- <location line="+513"/>
+ <location line="+375"/>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
<message>
- <location line="-519"/>
- <location line="+6"/>
+ <location line="-563"/>
+ <location line="+10"/>
<source>Wallet</source>
<translation>Wallet</translation>
</message>
<message>
- <location line="+109"/>
+ <location line="+113"/>
<source>&amp;Send</source>
<translation>&amp;Send</translation>
</message>
@@ -468,13 +466,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Receive</translation>
</message>
<message>
- <location line="+28"/>
- <location line="+2"/>
- <source>&amp;About Bitcoin</source>
- <translation>&amp;About Bitcoin</translation>
- </message>
- <message>
- <location line="+14"/>
+ <location line="+44"/>
<location line="+2"/>
<source>&amp;Show / Hide</source>
<translation>&amp;Show / Hide</translation>
@@ -500,12 +492,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Verify messages to ensure they were signed with specified Bitcoin addresses</translation>
</message>
<message>
- <location line="+35"/>
+ <location line="+39"/>
<source>&amp;File</source>
<translation>&amp;File</translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+11"/>
<source>&amp;Settings</source>
<translation>&amp;Settings</translation>
</message>
@@ -520,18 +512,30 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Tabs toolbar</translation>
</message>
<message>
- <location line="-235"/>
- <location line="+294"/>
+ <location line="-244"/>
+ <location line="+321"/>
<source>[testnet]</source>
<translation>[testnet]</translation>
</message>
<message>
- <location line="-177"/>
+ <location line="-331"/>
+ <location line="+10"/>
+ <source>Bitcoin Core</source>
+ <translation type="unfinished">Bitcoin Core</translation>
+ </message>
+ <message>
+ <location line="+121"/>
<source>Request payments (generates QR codes and bitcoin: URIs)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+63"/>
+ <location line="+27"/>
+ <location line="+2"/>
+ <source>&amp;About Bitcoin Core</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+34"/>
<source>&amp;Used sending addresses...</source>
<translation type="unfinished"></translation>
</message>
@@ -551,13 +555,23 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+106"/>
+ <location line="+2"/>
+ <source>Open URI...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Open a bitcoin: URI or payment request</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+126"/>
<location line="+5"/>
<source>Bitcoin client</source>
<translation>Bitcoin client</translation>
</message>
<message numerus="yes">
- <location line="+120"/>
+ <location line="+133"/>
<source>%n active connection(s) to Bitcoin network</source>
<translation>
<numerusform>%n active connection to Bitcoin network</numerusform>
@@ -677,17 +691,7 @@ Address: %4
</translation>
</message>
<message>
- <location line="+34"/>
- <source>URI handling</source>
- <translation>URI handling</translation>
- </message>
- <message>
- <location line="+0"/>
- <source>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
- <translation>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation>
- </message>
- <message>
- <location line="+45"/>
+ <location line="+67"/>
<source>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</source>
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;unlocked&lt;/b&gt;</translation>
</message>
@@ -697,7 +701,7 @@ Address: %4
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
<message>
- <location filename="../bitcoin.cpp" line="+110"/>
+ <location filename="../bitcoin.cpp" line="+116"/>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
<translation>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</translation>
</message>
@@ -705,12 +709,299 @@ Address: %4
<context>
<name>ClientModel</name>
<message>
- <location filename="../clientmodel.cpp" line="+115"/>
+ <location filename="../clientmodel.cpp" line="+119"/>
<source>Network Alert</source>
<translation>Network Alert</translation>
</message>
</context>
<context>
+ <name>CoinControlDialog</name>
+ <message>
+ <location filename="../forms/coincontroldialog.ui" line="+14"/>
+ <source>Coin Control Address Selection</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+34"/>
+ <source>Quantity:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+29"/>
+ <source>Bytes:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+45"/>
+ <source>Amount:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+29"/>
+ <source>Priority:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+45"/>
+ <source>Fee:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+32"/>
+ <source>Low Output:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+48"/>
+ <source>After Fee:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+32"/>
+ <source>Change:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+63"/>
+ <source>(un)select all</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Tree mode</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+16"/>
+ <source>List mode</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+52"/>
+ <source>Amount</source>
+ <translation type="unfinished">Amount</translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>Address</source>
+ <translation type="unfinished">Address</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Date</source>
+ <translation type="unfinished">Date</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Confirmations</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Confirmed</source>
+ <translation type="unfinished">Confirmed</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>Priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../coincontroldialog.cpp" line="+42"/>
+ <source>Copy address</source>
+ <translation type="unfinished">Copy address</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy label</source>
+ <translation type="unfinished">Copy label</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <location line="+26"/>
+ <source>Copy amount</source>
+ <translation type="unfinished">Copy amount</translation>
+ </message>
+ <message>
+ <location line="-25"/>
+ <source>Copy transaction ID</source>
+ <translation type="unfinished">Copy transaction ID</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Lock unspent</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Unlock unspent</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Copy quantity</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Copy fee</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy after fee</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy bytes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy low output</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy change</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+323"/>
+ <source>highest</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>higher</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>high</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>medium-high</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>medium</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>low-medium</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>low</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>lower</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>lowest</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>(%1 locked)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+171"/>
+ <source>Dust</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>yes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>no</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+10"/>
+ <source>This label turns red, if the transaction size is greater than 1000 bytes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <location line="+5"/>
+ <source>This means a fee of at least %1 per kB is required.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-4"/>
+ <source>Can vary +/- 1 byte per input.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Transactions with higher priority are more likely to get included into a block.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>This label turns red, if the priority is smaller than &quot;medium&quot;</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>This label turns red, if any recipient receives an amount smaller than %1.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <location line="+4"/>
+ <source>This means a fee of at least %1 is required.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-3"/>
+ <source>Amounts below 0.546 times the minimum relay fee are shown as dust.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>This label turns red, if the change is smaller than %1.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+43"/>
+ <location line="+66"/>
+ <source>(no label)</source>
+ <translation type="unfinished">(no label)</translation>
+ </message>
+ <message>
+ <location line="-9"/>
+ <source>change from %1 (%2)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>(change)</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>EditAddressDialog</name>
<message>
<location filename="../forms/editaddressdialog.ui" line="+14"/>
@@ -738,7 +1029,7 @@ Address: %4
<translation>&amp;Address</translation>
</message>
<message>
- <location filename="../editaddressdialog.cpp" line="+21"/>
+ <location filename="../editaddressdialog.cpp" line="+25"/>
<source>New receiving address</source>
<translation>New receiving address</translation>
</message>
@@ -781,7 +1072,7 @@ Address: %4
<context>
<name>FreespaceChecker</name>
<message>
- <location filename="../intro.cpp" line="+61"/>
+ <location filename="../intro.cpp" line="+65"/>
<source>A new data directory will be created.</source>
<translation>A new data directory will be created.</translation>
</message>
@@ -809,18 +1100,18 @@ Address: %4
<context>
<name>GUIUtil::HelpMessageBox</name>
<message>
- <location filename="../guiutil.cpp" line="+558"/>
- <location line="+13"/>
- <source>Bitcoin-Qt</source>
- <translation>Bitcoin-Qt</translation>
- </message>
- <message>
- <location line="-13"/>
+ <location filename="../guiutil.cpp" line="+597"/>
<source>version</source>
<translation>version</translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+0"/>
+ <location line="+13"/>
+ <source>Bitcoin Core</source>
+ <translation type="unfinished">Bitcoin Core</translation>
+ </message>
+ <message>
+ <location line="-11"/>
<source>Usage:</source>
<translation>Usage:</translation>
</message>
@@ -864,18 +1155,18 @@ Address: %4
</message>
<message>
<location line="+9"/>
- <source>Welcome to Bitcoin-Qt.</source>
- <translation>Welcome to Bitcoin-Qt.</translation>
+ <source>Welcome to Bitcoin Core.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+26"/>
- <source>As this is the first time the program is launched, you can choose where Bitcoin-Qt will store its data.</source>
- <translation>As this is the first time the program is launched, you can choose where Bitcoin-Qt will store its data.</translation>
+ <source>As this is the first time the program is launched, you can choose where Bitcoin Core will store its data.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+10"/>
- <source>Bitcoin-Qt will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory.</source>
- <translation>Bitcoin-Qt will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory.</translation>
+ <source>Bitcoin Core will download and store a copy of the Bitcoin block chain. At least %1GB of data will be stored in this directory, and it will grow over time. The wallet will also be stored in this directory.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+10"/>
@@ -888,7 +1179,17 @@ Address: %4
<translation>Use a custom data directory:</translation>
</message>
<message>
- <location filename="../intro.cpp" line="+105"/>
+ <location filename="../intro.cpp" line="+85"/>
+ <source>Bitcoin</source>
+ <translation type="unfinished">Bitcoin</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Error: Specified data directory &quot;%1&quot; can not be created.</source>
+ <translation type="unfinished">Error: Specified data directory &quot;%1&quot; can not be created.</translation>
+ </message>
+ <message>
+ <location line="+19"/>
<source>Error</source>
<translation>Error</translation>
</message>
@@ -904,6 +1205,34 @@ Address: %4
</message>
</context>
<context>
+ <name>OpenURIDialog</name>
+ <message>
+ <location filename="../forms/openuridialog.ui" line="+14"/>
+ <source>Open URI</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Open payment request from URI or file</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>URI:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>Select payment request file</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../openuridialog.cpp" line="+47"/>
+ <source>Select payment request file to open</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>OptionsDialog</name>
<message>
<location filename="../forms/optionsdialog.ui" line="+14"/>
@@ -1061,6 +1390,16 @@ Address: %4
<translation>&amp;Display addresses in transaction list</translation>
</message>
<message>
+ <location line="+7"/>
+ <source>Whether to show coin control features or not.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Display coin &amp;control features (experts only)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+71"/>
<source>&amp;OK</source>
<translation>&amp;OK</translation>
@@ -1076,12 +1415,12 @@ Address: %4
<translation>&amp;Apply</translation>
</message>
<message>
- <location filename="../optionsdialog.cpp" line="+58"/>
+ <location filename="../optionsdialog.cpp" line="+63"/>
<source>default</source>
<translation>default</translation>
</message>
<message>
- <location line="+130"/>
+ <location line="+131"/>
<source>Confirm options reset</source>
<translation>Confirm options reset</translation>
</message>
@@ -1122,17 +1461,17 @@ Address: %4
</message>
<message>
<location line="+50"/>
- <location line="+202"/>
+ <location line="+214"/>
<source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
<translation>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</translation>
</message>
<message>
- <location line="-131"/>
+ <location line="-140"/>
<source>Unconfirmed:</source>
<translation>Unconfirmed:</translation>
</message>
<message>
- <location line="-78"/>
+ <location line="-81"/>
<source>Wallet</source>
<translation>Wallet</translation>
</message>
@@ -1147,12 +1486,12 @@ Address: %4
<translation>Your current spendable balance</translation>
</message>
<message>
- <location line="+29"/>
+ <location line="+32"/>
<source>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</source>
<translation>Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance</translation>
</message>
<message>
- <location line="+13"/>
+ <location line="+16"/>
<source>Immature:</source>
<translation>Immature:</translation>
</message>
@@ -1162,7 +1501,7 @@ Address: %4
<translation>Mined balance that has not yet matured</translation>
</message>
<message>
- <location line="+13"/>
+ <location line="+16"/>
<source>Total:</source>
<translation>Total:</translation>
</message>
@@ -1172,12 +1511,12 @@ Address: %4
<translation>Your current total balance</translation>
</message>
<message>
- <location line="+53"/>
+ <location line="+56"/>
<source>&lt;b&gt;Recent transactions&lt;/b&gt;</source>
<translation>&lt;b&gt;Recent transactions&lt;/b&gt;</translation>
</message>
<message>
- <location filename="../overviewpage.cpp" line="+116"/>
+ <location filename="../overviewpage.cpp" line="+120"/>
<location line="+1"/>
<source>out of sync</source>
<translation>out of sync</translation>
@@ -1186,7 +1525,7 @@ Address: %4
<context>
<name>PaymentServer</name>
<message>
- <location filename="../paymentserver.cpp" line="+392"/>
+ <location filename="../paymentserver.cpp" line="+397"/>
<source>URI handling</source>
<translation type="unfinished">URI handling</translation>
</message>
@@ -1196,23 +1535,29 @@ Address: %4
<translation type="unfinished">URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation>
</message>
<message>
- <location line="+69"/>
+ <location line="+91"/>
<source>Requested payment amount of %1 is too small (considered dust).</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
- <location line="+37"/>
+ <location line="-204"/>
+ <location line="+195"/>
+ <location line="+13"/>
<source>Payment request error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
- <source>Insecure requests to custom payment scripts unsupported</source>
+ <location line="-207"/>
+ <source>Cannot start bitcoin: click-to-pay handler</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+38"/>
+ <location line="+195"/>
+ <source>Unverified payment requests to custom payment scripts are unsupported.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+59"/>
<source>Refund from %1</source>
<translation type="unfinished"></translation>
</message>
@@ -1222,7 +1567,7 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+31"/>
+ <location line="+28"/>
<source>Bad response from server %1</source>
<translation type="unfinished"></translation>
</message>
@@ -1232,8 +1577,8 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="-58"/>
- <location line="+30"/>
+ <location line="-55"/>
+ <location line="+27"/>
<location line="+17"/>
<source>Network request error</source>
<translation type="unfinished"></translation>
@@ -1242,9 +1587,8 @@ Address: %4
<context>
<name>QObject</name>
<message>
- <location filename="../bitcoin.cpp" line="+114"/>
+ <location filename="../bitcoin.cpp" line="+119"/>
<location line="+5"/>
- <location filename="../intro.cpp" line="-32"/>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
@@ -1258,16 +1602,11 @@ Address: %4
<source>Error: Invalid combination of -regtest and -testnet.</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location filename="../intro.cpp" line="+1"/>
- <source>Error: Specified data directory &quot;%1&quot; can not be created.</source>
- <translation>Error: Specified data directory &quot;%1&quot; can not be created.</translation>
- </message>
</context>
<context>
<name>QRImageWidget</name>
<message>
- <location filename="../receiverequestdialog.cpp" line="+32"/>
+ <location filename="../receiverequestdialog.cpp" line="+36"/>
<source>&amp;Save Image...</source>
<translation type="unfinished"></translation>
</message>
@@ -1283,8 +1622,8 @@ Address: %4
</message>
<message>
<location line="+0"/>
- <source>PNG Images (*.png)</source>
- <translation type="unfinished">PNG Images (*.png)</translation>
+ <source>PNG Image (*.png)</source>
+ <translation type="unfinished"></translation>
</message>
</context>
<context>
@@ -1304,7 +1643,7 @@ Address: %4
<location line="+53"/>
<location line="+23"/>
<location line="+23"/>
- <location filename="../rpcconsole.cpp" line="+352"/>
+ <location filename="../rpcconsole.cpp" line="+360"/>
<source>N/A</source>
<translation>N/A</translation>
</message>
@@ -1319,7 +1658,12 @@ Address: %4
<translation>&amp;Information</translation>
</message>
<message>
- <location line="+68"/>
+ <location line="-10"/>
+ <source>Debug window</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+78"/>
<source>Using OpenSSL version</source>
<translation>Using OpenSSL version</translation>
</message>
@@ -1374,12 +1718,7 @@ Address: %4
<translation>Command-line options</translation>
</message>
<message>
- <location line="+7"/>
- <source>Show the Bitcoin-Qt help message to get a list with possible Bitcoin command-line options.</source>
- <translation>Show the Bitcoin-Qt help message to get a list with possible Bitcoin command-line options.</translation>
- </message>
- <message>
- <location line="+3"/>
+ <location line="+10"/>
<source>&amp;Show</source>
<translation>&amp;Show</translation>
</message>
@@ -1419,12 +1758,7 @@ Address: %4
<translation>Build date</translation>
</message>
<message>
- <location line="-104"/>
- <source>Bitcoin - Debug window</source>
- <translation>Bitcoin - Debug window</translation>
- </message>
- <message>
- <location line="+25"/>
+ <location line="-79"/>
<source>Bitcoin Core</source>
<translation>Bitcoin Core</translation>
</message>
@@ -1439,7 +1773,12 @@ Address: %4
<translation>Open the Bitcoin debug log file from the current data directory. This can take a few seconds for large log files.</translation>
</message>
<message>
- <location line="+102"/>
+ <location line="+26"/>
+ <source>Show the Bitcoin-Core help message to get a list with possible Bitcoin command-line options.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+76"/>
<source>Clear console</source>
<translation>Clear console</translation>
</message>
@@ -1497,37 +1836,32 @@ Address: %4
<context>
<name>ReceiveCoinsDialog</name>
<message>
- <location filename="../forms/receivecoinsdialog.ui" line="+22"/>
+ <location filename="../forms/receivecoinsdialog.ui" line="+83"/>
<source>&amp;Amount:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+16"/>
+ <location line="+19"/>
<source>The amount to request</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="-32"/>
<source>&amp;Label:</source>
<translation type="unfinished">&amp;Label:</translation>
</message>
<message>
- <location line="+10"/>
- <source>The label to associate with the receiving address</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+7"/>
+ <location line="-34"/>
<source>&amp;Message:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+20"/>
<source>The message to attach to payment request</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+14"/>
+ <location line="-37"/>
<source>Reuse one of the previously used receiving addresses. Reusing addresses has security and privacy issues. Do not use this unless re-generating a payment request made before.</source>
<translation type="unfinished"></translation>
</message>
@@ -1537,12 +1871,17 @@ Address: %4
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+27"/>
+ <source>The label to associate with the new receiving address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+14"/>
<source>Use this form to request payments. All fields are optional.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+17"/>
+ <location line="+56"/>
<source>Clear all fields of the form.</source>
<translation type="unfinished"></translation>
</message>
@@ -1556,6 +1895,31 @@ Address: %4
<source>&amp;Request payment</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location line="+47"/>
+ <source>Previously requested payments</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>Show the selected request (does the same as double clicking an entry)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Show</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>Remove the selected entries from the list</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Remove</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>ReceiveRequestDialog</name>
@@ -1576,16 +1940,11 @@ Address: %4
</message>
<message>
<location line="+7"/>
- <source>&amp;Copy Image</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+7"/>
<source>&amp;Save Image...</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../receiverequestdialog.cpp" line="+58"/>
+ <location filename="../receiverequestdialog.cpp" line="+56"/>
<source>Request payment to %1</source>
<translation type="unfinished"></translation>
</message>
@@ -1631,16 +1990,119 @@ Address: %4
</message>
</context>
<context>
+ <name>RecentRequestsTableModel</name>
+ <message>
+ <location filename="../recentrequeststablemodel.cpp" line="+14"/>
+ <source>Date</source>
+ <translation type="unfinished">Date</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Label</source>
+ <translation type="unfinished">Label</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Message</source>
+ <translation type="unfinished">Message</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Amount</source>
+ <translation type="unfinished">Amount</translation>
+ </message>
+ <message>
+ <location line="+36"/>
+ <source>(no label)</source>
+ <translation type="unfinished">(no label)</translation>
+ </message>
+ <message>
+ <location line="+9"/>
+ <source>(no message)</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>SendCoinsDialog</name>
<message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/>
- <location filename="../sendcoinsdialog.cpp" line="+140"/>
- <location line="+213"/>
+ <location filename="../sendcoinsdialog.cpp" line="+381"/>
+ <location line="+81"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
<message>
- <location line="+50"/>
+ <location line="+76"/>
+ <source>Coin Control Features</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+20"/>
+ <source>Inputs...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>automatically selected</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+19"/>
+ <source>Insufficient funds!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+89"/>
+ <source>Quantity:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+35"/>
+ <source>Bytes:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+48"/>
+ <source>Amount:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+32"/>
+ <source>Priority:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+48"/>
+ <source>Fee:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+32"/>
+ <source>Low Output:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+48"/>
+ <source>After Fee:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+32"/>
+ <source>Change:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+44"/>
+ <source>If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Custom change address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+115"/>
<source>Send to multiple recipients at once</source>
<translation>Send to multiple recipients at once</translation>
</message>
@@ -1665,12 +2127,7 @@ Address: %4
<translation>Balance:</translation>
</message>
<message>
- <location line="+10"/>
- <source>123.456 BTC</source>
- <translation>123.456 BTC</translation>
- </message>
- <message>
- <location line="+31"/>
+ <location line="+41"/>
<source>Confirm the send action</source>
<translation>Confirm the send action</translation>
</message>
@@ -1680,69 +2137,135 @@ Address: %4
<translation>S&amp;end</translation>
</message>
<message>
- <location filename="../sendcoinsdialog.cpp" line="-154"/>
+ <location filename="../sendcoinsdialog.cpp" line="-229"/>
<source>Confirm send coins</source>
<translation>Confirm send coins</translation>
</message>
<message>
- <location line="-90"/>
+ <location line="-74"/>
<location line="+5"/>
<location line="+5"/>
+ <location line="+4"/>
<source>%1 to %2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+26"/>
+ <location line="-136"/>
+ <source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
+ <translation type="unfinished">Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
+ </message>
+ <message>
+ <location line="+15"/>
+ <source>Copy quantity</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy amount</source>
+ <translation type="unfinished">Copy amount</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy fee</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy after fee</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy bytes</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy priority</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy low output</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Copy change</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+170"/>
+ <source>Total Amount %1 (= %2)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>or</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+202"/>
<source>The recipient address is not valid, please recheck.</source>
<translation>The recipient address is not valid, please recheck.</translation>
</message>
<message>
- <location line="+4"/>
+ <location line="+3"/>
<source>The amount to pay must be larger than 0.</source>
<translation>The amount to pay must be larger than 0.</translation>
</message>
<message>
- <location line="+4"/>
+ <location line="+3"/>
<source>The amount exceeds your balance.</source>
<translation>The amount exceeds your balance.</translation>
</message>
<message>
- <location line="+4"/>
+ <location line="+3"/>
<source>The total exceeds your balance when the %1 transaction fee is included.</source>
<translation>The total exceeds your balance when the %1 transaction fee is included.</translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+3"/>
<source>Duplicate address found, can only send to each address once per send operation.</source>
<translation>Duplicate address found, can only send to each address once per send operation.</translation>
</message>
<message>
+ <location line="+3"/>
+ <source>Transaction creation failed!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+4"/>
- <source>Error: Transaction creation failed!</source>
- <translation>Error: Transaction creation failed!</translation>
+ <source>The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location line="+15"/>
- <source>Are you sure you want to send?</source>
+ <location line="+113"/>
+ <source>Warning: Invalid Bitcoin address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+9"/>
- <source>added as transaction fee</source>
+ <location line="+13"/>
+ <source>(no label)</source>
+ <translation type="unfinished">(no label)</translation>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Warning: Unknown change address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
- <source>Total Amount %1</source>
+ <location line="-378"/>
+ <source>Are you sure you want to send?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+20"/>
- <source>Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</source>
- <translation>Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.</translation>
+ <location line="+9"/>
+ <source>added as transaction fee</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location line="+144"/>
+ <location line="+170"/>
<source>Payment request expired</source>
<translation type="unfinished"></translation>
</message>
@@ -1755,39 +2278,44 @@ Address: %4
<context>
<name>SendCoinsEntry</name>
<message>
- <location filename="../forms/sendcoinsentry.ui" line="+33"/>
- <location line="+585"/>
+ <location filename="../forms/sendcoinsentry.ui" line="+131"/>
+ <location line="+501"/>
+ <location line="+536"/>
<source>A&amp;mount:</source>
<translation>A&amp;mount:</translation>
</message>
<message>
- <location line="-572"/>
- <location line="+585"/>
+ <location line="-1132"/>
<source>Pay &amp;To:</source>
<translation>Pay &amp;To:</translation>
</message>
<message>
- <location line="-551"/>
+ <location line="+18"/>
<source>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
<translation>The address to send the payment to (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
</message>
<message>
- <location filename="../sendcoinsentry.cpp" line="+28"/>
+ <location filename="../sendcoinsentry.cpp" line="+30"/>
<source>Enter a label for this address to add it to your address book</source>
<translation>Enter a label for this address to add it to your address book</translation>
</message>
<message>
- <location filename="../forms/sendcoinsentry.ui" line="-18"/>
+ <location filename="../forms/sendcoinsentry.ui" line="+57"/>
<source>&amp;Label:</source>
<translation>&amp;Label:</translation>
</message>
<message>
- <location line="+28"/>
+ <location line="-50"/>
<source>Choose previously used address</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="-40"/>
+ <source>This is a normal payment.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+50"/>
<source>Alt+A</source>
<translation>Alt+A</translation>
</message>
@@ -1803,16 +2331,35 @@ Address: %4
</message>
<message>
<location line="+7"/>
- <source>Remove this recipient</source>
- <translation>Remove this recipient</translation>
+ <location line="+504"/>
+ <location line="+536"/>
+ <source>Remove this entry</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location line="+16"/>
+ <location line="-40"/>
+ <source>This is a verified payment request.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-971"/>
<source>Enter a label for this address to add it to the list of used addresses</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+465"/>
+ <location line="+439"/>
+ <source>This is an unverified payment request.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+18"/>
+ <location line="+532"/>
+ <source>Pay To:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-498"/>
+ <location line="+536"/>
<source>Memo:</source>
<translation type="unfinished"></translation>
</message>
@@ -1933,7 +2480,7 @@ Address: %4
<translation>Reset all verify message fields</translation>
</message>
<message>
- <location filename="../signverifymessagedialog.cpp" line="+27"/>
+ <location filename="../signverifymessagedialog.cpp" line="+29"/>
<location line="+3"/>
<source>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</source>
<translation>Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)</translation>
@@ -1949,7 +2496,7 @@ Address: %4
<translation>Enter Bitcoin signature</translation>
</message>
<message>
- <location line="+85"/>
+ <location line="+84"/>
<location line="+81"/>
<source>The entered address is invalid.</source>
<translation>The entered address is invalid.</translation>
@@ -2018,9 +2565,14 @@ Address: %4
<context>
<name>SplashScreen</name>
<message>
- <location filename="../splashscreen.cpp" line="+23"/>
- <source>The Bitcoin developers</source>
- <translation>The Bitcoin developers</translation>
+ <location filename="../splashscreen.cpp" line="+26"/>
+ <source>Bitcoin Core</source>
+ <translation type="unfinished">Bitcoin Core</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>The Bitcoin Core developers</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
@@ -2031,7 +2583,7 @@ Address: %4
<context>
<name>TrafficGraphWidget</name>
<message>
- <location filename="../trafficgraphwidget.cpp" line="+75"/>
+ <location filename="../trafficgraphwidget.cpp" line="+79"/>
<source>KB/s</source>
<translation type="unfinished"></translation>
</message>
@@ -2039,7 +2591,7 @@ Address: %4
<context>
<name>TransactionDesc</name>
<message>
- <location filename="../transactiondesc.cpp" line="+22"/>
+ <location filename="../transactiondesc.cpp" line="+28"/>
<source>Open until %1</source>
<translation>Open until %1</translation>
</message>
@@ -2240,7 +2792,7 @@ Address: %4
<context>
<name>TransactionTableModel</name>
<message>
- <location filename="../transactiontablemodel.cpp" line="+227"/>
+ <location filename="../transactiontablemodel.cpp" line="+234"/>
<source>Date</source>
<translation>Date</translation>
</message>
@@ -2364,7 +2916,7 @@ Address: %4
<context>
<name>TransactionView</name>
<message>
- <location filename="../transactionview.cpp" line="+52"/>
+ <location filename="../transactionview.cpp" line="+57"/>
<location line="+16"/>
<source>All</source>
<translation>All</translation>
@@ -2425,12 +2977,12 @@ Address: %4
<translation>Other</translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+6"/>
<source>Enter address or label to search</source>
<translation>Enter address or label to search</translation>
</message>
<message>
- <location line="+7"/>
+ <location line="+6"/>
<source>Min amount</source>
<translation>Min amount</translation>
</message>
@@ -2465,17 +3017,37 @@ Address: %4
<translation>Show transaction details</translation>
</message>
<message>
- <location line="+143"/>
- <source>Export Transaction Data</source>
- <translation>Export Transaction Data</translation>
+ <location line="+142"/>
+ <source>Export Transaction History</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+19"/>
+ <source>Exporting Failed</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>There was an error trying to save the transaction history to %1.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Exporting Successful</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>The transaction history was successfully saved to %1.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="-22"/>
<source>Comma separated file (*.csv)</source>
<translation>Comma separated file (*.csv)</translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+9"/>
<source>Confirmed</source>
<translation>Confirmed</translation>
</message>
@@ -2510,17 +3082,7 @@ Address: %4
<translation>ID</translation>
</message>
<message>
- <location line="+4"/>
- <source>Error exporting</source>
- <translation>Error exporting</translation>
- </message>
- <message>
- <location line="+0"/>
- <source>Could not write to file %1.</source>
- <translation>Could not write to file %1.</translation>
- </message>
- <message>
- <location line="+100"/>
+ <location line="+107"/>
<source>Range:</source>
<translation>Range:</translation>
</message>
@@ -2531,9 +3093,17 @@ Address: %4
</message>
</context>
<context>
+ <name>WalletFrame</name>
+ <message>
+ <location filename="../walletframe.cpp" line="+26"/>
+ <source>No wallet has been loaded.</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>WalletModel</name>
<message>
- <location filename="../walletmodel.cpp" line="+218"/>
+ <location filename="../walletmodel.cpp" line="+245"/>
<source>Send Coins</source>
<translation>Send Coins</translation>
</message>
@@ -2541,7 +3111,7 @@ Address: %4
<context>
<name>WalletView</name>
<message>
- <location filename="../walletview.cpp" line="+46"/>
+ <location filename="../walletview.cpp" line="+43"/>
<source>&amp;Export</source>
<translation>&amp;Export</translation>
</message>
@@ -2551,65 +3121,60 @@ Address: %4
<translation>Export the data in the current tab to a file</translation>
</message>
<message>
- <location line="+183"/>
+ <location line="+181"/>
<source>Backup Wallet</source>
<translation>Backup Wallet</translation>
</message>
<message>
- <location line="+0"/>
+ <location line="+1"/>
<source>Wallet Data (*.dat)</source>
<translation>Wallet Data (*.dat)</translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+6"/>
<source>Backup Failed</source>
<translation>Backup Failed</translation>
</message>
<message>
<location line="+0"/>
- <source>There was an error trying to save the wallet data to the new location.</source>
- <translation>There was an error trying to save the wallet data to the new location.</translation>
+ <source>There was an error trying to save the wallet data to %1.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
- <source>Backup Successful</source>
- <translation>Backup Successful</translation>
+ <source>The wallet data was successfully saved to %1.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
<location line="+0"/>
- <source>The wallet data was successfully saved to the new location.</source>
- <translation>The wallet data was successfully saved to the new location.</translation>
+ <source>Backup Successful</source>
+ <translation>Backup Successful</translation>
</message>
</context>
<context>
<name>bitcoin-core</name>
<message>
- <location filename="../bitcoinstrings.cpp" line="+102"/>
- <source>Bitcoin version</source>
- <translation>Bitcoin version</translation>
- </message>
- <message>
- <location line="+107"/>
+ <location filename="../bitcoinstrings.cpp" line="+217"/>
<source>Usage:</source>
<translation>Usage:</translation>
</message>
<message>
- <location line="-55"/>
+ <location line="-54"/>
<source>List commands</source>
<translation>List commands</translation>
</message>
<message>
- <location line="-13"/>
+ <location line="-14"/>
<source>Get help for a command</source>
<translation>Get help for a command</translation>
</message>
<message>
- <location line="+25"/>
+ <location line="+26"/>
<source>Options:</source>
<translation>Options:</translation>
</message>
<message>
- <location line="+24"/>
+ <location line="+23"/>
<source>Specify configuration file (default: bitcoin.conf)</source>
<translation>Specify configuration file (default: bitcoin.conf)</translation>
</message>
@@ -2629,7 +3194,7 @@ Address: %4
<translation>Set database cache size in megabytes (default: 25)</translation>
</message>
<message>
- <location line="-28"/>
+ <location line="-27"/>
<source>Listen for connections on &lt;port&gt; (default: 8333 or testnet: 18333)</source>
<translation>Listen for connections on &lt;port&gt; (default: 8333 or testnet: 18333)</translation>
</message>
@@ -2639,7 +3204,7 @@ Address: %4
<translation>Maintain at most &lt;n&gt; connections to peers (default: 125)</translation>
</message>
<message>
- <location line="-49"/>
+ <location line="-50"/>
<source>Connect to a node to retrieve peer addresses, and disconnect</source>
<translation>Connect to a node to retrieve peer addresses, and disconnect</translation>
</message>
@@ -2654,7 +3219,7 @@ Address: %4
<translation>Threshold for disconnecting misbehaving peers (default: 100)</translation>
</message>
<message>
- <location line="-142"/>
+ <location line="-147"/>
<source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source>
<translation>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</translation>
</message>
@@ -2669,7 +3234,7 @@ Address: %4
<translation>Listen for JSON-RPC connections on &lt;port&gt; (default: 8332 or testnet: 18332)</translation>
</message>
<message>
- <location line="+40"/>
+ <location line="+45"/>
<source>Accept command line and JSON-RPC commands</source>
<translation>Accept command line and JSON-RPC commands</translation>
</message>
@@ -2679,17 +3244,17 @@ Address: %4
<translation>Run in the background as a daemon and accept commands</translation>
</message>
<message>
- <location line="+40"/>
+ <location line="+39"/>
<source>Use the test network</source>
<translation>Use the test network</translation>
</message>
<message>
- <location line="-118"/>
+ <location line="-117"/>
<source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
<translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation>
</message>
<message>
- <location line="-87"/>
+ <location line="-92"/>
<source>%s, you must set a rpcpassword in the configuration file:
%s
It is recommended you use the following random password:
@@ -2754,17 +3319,17 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</translation>
</message>
<message>
- <location line="+11"/>
- <source>Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)</source>
- <translation>Set maximum size of high-priority/low-fee transactions in bytes (default: 27000)</translation>
- </message>
- <message>
- <location line="+6"/>
+ <location line="+18"/>
<source>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</source>
<translation>This is a pre-release test build - use at your own risk - do not use for mining or merchant applications</translation>
</message>
<message>
<location line="+5"/>
+ <source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: -proxy)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.</source>
<translation>Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.</translation>
</message>
@@ -2794,17 +3359,27 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Warning: wallet.dat corrupt, data salvaged! Original wallet.dat saved as wallet.{timestamp}.bak in %s; if your balance or transactions are incorrect you should restore from a backup.</translation>
</message>
<message>
- <location line="+14"/>
+ <location line="+9"/>
+ <source>&lt;category&gt; can be:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
<source>Attempt to recover private keys from a corrupt wallet.dat</source>
<translation>Attempt to recover private keys from a corrupt wallet.dat</translation>
</message>
<message>
<location line="+1"/>
+ <source>Bitcoin Core Daemon</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Bitcoin RPC client version</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+1"/>
<source>Block creation options:</source>
<translation>Block creation options:</translation>
</message>
@@ -2814,7 +3389,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Connect only to the specified node(s)</translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+1"/>
+ <source>Connect through SOCKS proxy</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Connect to JSON-RPC on &lt;port&gt; (default: 8332 or testnet: 18332)</source>
<translation type="unfinished"></translation>
</message>
@@ -2924,7 +3504,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Failed to write undo data</translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+1"/>
+ <source>Fee per kB to add to transactions you send</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Find peers using DNS lookup (default: 1 unless -connect)</source>
<translation>Find peers using DNS lookup (default: 1 unless -connect)</translation>
</message>
@@ -2944,6 +3529,11 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>How thorough the block verification is (0-4, default: 3)</translation>
</message>
<message>
+ <location line="+1"/>
+ <source>If &lt;category&gt; is not supplied, output all debugging information.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location line="+2"/>
<source>Incorrect or no genesis block found. Wrong datadir for network?</source>
<translation>Incorrect or no genesis block found. Wrong datadir for network?</translation>
@@ -2959,17 +3549,37 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Not enough file descriptors available.</translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+5"/>
+ <source>Prepend debug output with timestamp (default: 1)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>RPC client options:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Rebuild block chain index from current blk000??.dat files</source>
<translation>Rebuild block chain index from current blk000??.dat files</translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+5"/>
+ <source>Select SOCKS version for -proxy (4 or 5, default: 5)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Send command to Bitcoin server</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+8"/>
+ <source>Set maximum block size in bytes (default: %d)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
<source>Set the number of threads to service RPC calls (default: 4)</source>
<translation>Set the number of threads to service RPC calls (default: 4)</translation>
</message>
@@ -2989,7 +3599,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+7"/>
<source>Verifying blocks...</source>
<translation>Verifying blocks...</translation>
</message>
@@ -3000,11 +3610,21 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
</message>
<message>
<location line="+1"/>
+ <source>Wait for RPC server to start</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Wallet %s resides outside data directory %s</source>
<translation>Wallet %s resides outside data directory %s</translation>
</message>
<message>
- <location line="+4"/>
+ <location line="+3"/>
+ <source>Warning: Deprecated argument -debugnet ignored, use -debug=net</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
<source>You need to rebuild the database using -reindex to change -txindex</source>
<translation>You need to rebuild the database using -reindex to change -txindex</translation>
</message>
@@ -3014,17 +3634,27 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Imports blocks from external blk000??.dat file</translation>
</message>
<message>
- <location line="-98"/>
+ <location line="-104"/>
<source>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</source>
<translation>Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)</translation>
</message>
<message>
- <location line="+17"/>
+ <location line="+14"/>
+ <source>Output debugging information (default: 0, supplying &lt;category&gt; is optional)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Set maximum size of high-priority/low-fee transactions in bytes (default: %d)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
<source>Set the number of script verification threads (up to 16, 0 = auto, &lt;0 = leave that many cores free, default: 0)</source>
<translation>Set the number of script verification threads (up to 16, 0 = auto, &lt;0 = leave that many cores free, default: 0)</translation>
</message>
<message>
- <location line="+83"/>
+ <location line="+88"/>
<source>Information</source>
<translation>Information</translation>
</message>
@@ -3064,32 +3694,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Only connect to nodes in network &lt;net&gt; (IPv4, IPv6 or Tor)</translation>
</message>
<message>
- <location line="+2"/>
- <source>Output extra debugging information. Implies all other -debug* options</source>
- <translation>Output extra debugging information. Implies all other -debug* options</translation>
- </message>
- <message>
- <location line="+1"/>
- <source>Output extra network debugging information</source>
- <translation>Output extra network debugging information</translation>
- </message>
- <message>
- <location line="+2"/>
- <source>Prepend debug output with timestamp</source>
- <translation>Prepend debug output with timestamp</translation>
- </message>
- <message>
- <location line="+5"/>
+ <location line="+9"/>
<source>SSL options: (see the Bitcoin Wiki for SSL setup instructions)</source>
<translation>SSL options: (see the Bitcoin Wiki for SSL setup instructions)</translation>
</message>
<message>
- <location line="+1"/>
- <source>Select the version of socks proxy to use (4-5, default: 5)</source>
- <translation>Select the version of socks proxy to use (4-5, default: 5)</translation>
- </message>
- <message>
- <location line="+3"/>
+ <location line="+4"/>
<source>Send trace/debug info to console instead of debug.log file</source>
<translation>Send trace/debug info to console instead of debug.log file</translation>
</message>
@@ -3099,12 +3709,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Send trace/debug info to debugger</translation>
</message>
<message>
- <location line="+5"/>
- <source>Set maximum block size in bytes (default: 250000)</source>
- <translation>Set maximum block size in bytes (default: 250000)</translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+6"/>
<source>Set minimum block size in bytes (default: 0)</source>
<translation>Set minimum block size in bytes (default: 0)</translation>
</message>
@@ -3154,37 +3759,37 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Use UPnP to map the listening port (default: 1 when listening)</translation>
</message>
<message>
- <location line="+1"/>
- <source>Use proxy to reach tor hidden services (default: same as -proxy)</source>
- <translation>Use proxy to reach tor hidden services (default: same as -proxy)</translation>
- </message>
- <message>
<location line="+2"/>
<source>Username for JSON-RPC connections</source>
<translation>Username for JSON-RPC connections</translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+6"/>
<source>Warning</source>
<translation>Warning</translation>
</message>
<message>
- <location line="+1"/>
+ <location line="+2"/>
<source>Warning: This version is obsolete, upgrade required!</source>
<translation>Warning: This version is obsolete, upgrade required!</translation>
</message>
<message>
<location line="+2"/>
+ <source>version</source>
+ <translation type="unfinished">version</translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>wallet.dat corrupt, salvage failed</source>
<translation>wallet.dat corrupt, salvage failed</translation>
</message>
<message>
- <location line="-54"/>
+ <location line="-57"/>
<source>Password for JSON-RPC connections</source>
<translation>Password for JSON-RPC connections</translation>
</message>
<message>
- <location line="-70"/>
+ <location line="-69"/>
<source>Allow JSON-RPC connections from specified IP address</source>
<translation>Allow JSON-RPC connections from specified IP address</translation>
</message>
@@ -3194,12 +3799,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Send commands to node running on &lt;ip&gt; (default: 127.0.0.1)</translation>
</message>
<message>
- <location line="-126"/>
+ <location line="-131"/>
<source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
<translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation>
</message>
<message>
- <location line="+155"/>
+ <location line="+160"/>
<source>Upgrade wallet to latest format</source>
<translation>Upgrade wallet to latest format</translation>
</message>
@@ -3239,22 +3844,17 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Unable to bind to %s on this computer (bind returned error %d, %s)</translation>
</message>
<message>
- <location line="-95"/>
- <source>Connect through socks proxy</source>
- <translation>Connect through socks proxy</translation>
- </message>
- <message>
- <location line="-11"/>
+ <location line="-106"/>
<source>Allow DNS lookups for -addnode, -seednode and -connect</source>
<translation>Allow DNS lookups for -addnode, -seednode and -connect</translation>
</message>
<message>
- <location line="+58"/>
+ <location line="+59"/>
<source>Loading addresses...</source>
<translation>Loading addresses...</translation>
</message>
<message>
- <location line="-36"/>
+ <location line="-37"/>
<source>Error loading wallet.dat: Wallet corrupted</source>
<translation>Error loading wallet.dat: Wallet corrupted</translation>
</message>
@@ -3274,12 +3874,12 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Error loading wallet.dat</translation>
</message>
<message>
- <location line="+30"/>
+ <location line="+31"/>
<source>Invalid -proxy address: &apos;%s&apos;</source>
<translation>Invalid -proxy address: &apos;%s&apos;</translation>
</message>
<message>
- <location line="+57"/>
+ <location line="+56"/>
<source>Unknown network specified in -onlynet: &apos;%s&apos;</source>
<translation>Unknown network specified in -onlynet: &apos;%s&apos;</translation>
</message>
@@ -3299,7 +3899,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Cannot resolve -externalip address: &apos;%s&apos;</translation>
</message>
<message>
- <location line="+46"/>
+ <location line="+47"/>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
<translation>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
@@ -3319,27 +3919,22 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Loading block index...</translation>
</message>
<message>
- <location line="-60"/>
+ <location line="-61"/>
<source>Add a node to connect to and attempt to keep the connection open</source>
<translation>Add a node to connect to and attempt to keep the connection open</translation>
</message>
<message>
- <location line="-28"/>
+ <location line="-32"/>
<source>Unable to bind to %s on this computer. Bitcoin is probably already running.</source>
<translation>Unable to bind to %s on this computer. Bitcoin is probably already running.</translation>
</message>
<message>
- <location line="+69"/>
- <source>Fee per KB to add to transactions you send</source>
- <translation>Fee per KB to add to transactions you send</translation>
- </message>
- <message>
- <location line="+20"/>
+ <location line="+94"/>
<source>Loading wallet...</source>
<translation>Loading wallet...</translation>
</message>
<message>
- <location line="-54"/>
+ <location line="-55"/>
<source>Cannot downgrade wallet</source>
<translation>Cannot downgrade wallet</translation>
</message>
@@ -3369,7 +3964,7 @@ for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.
<translation>Error</translation>
</message>
<message>
- <location line="-33"/>
+ <location line="-34"/>
<source>You must set rpcpassword=&lt;password&gt; in the configuration file:
%s
If the file does not exist, create it with owner-readable-only file permissions.</source>
diff --git a/src/qt/macdockiconhandler.mm b/src/qt/macdockiconhandler.mm
index 86b8c834d4..64291c9188 100644
--- a/src/qt/macdockiconhandler.mm
+++ b/src/qt/macdockiconhandler.mm
@@ -1,9 +1,13 @@
+// Copyright (c) 2011-2013 The Bitcoin Core developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#include "macdockiconhandler.h"
+#include <QImageWriter>
#include <QMenu>
-#include <QWidget>
#include <QTemporaryFile>
-#include <QImageWriter>
+#include <QWidget>
#undef slots
#include <Cocoa/Cocoa.h>
diff --git a/src/qt/macnotificationhandler.mm b/src/qt/macnotificationhandler.mm
index 8bb9b887a1..8a4c94cc5c 100644
--- a/src/qt/macnotificationhandler.mm
+++ b/src/qt/macnotificationhandler.mm
@@ -1,3 +1,7 @@
+// Copyright (c) 2011-2013 The Bitcoin Core developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#include "macnotificationhandler.h"
#undef slots
diff --git a/src/qt/notificator.cpp b/src/qt/notificator.cpp
index c9f6834ec2..1cef397d12 100644
--- a/src/qt/notificator.cpp
+++ b/src/qt/notificator.cpp
@@ -4,7 +4,6 @@
#include "notificator.h"
-
#include <QApplication>
#include <QByteArray>
#include <QIcon>
@@ -32,7 +31,7 @@
// https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128
const int FREEDESKTOP_NOTIFICATION_ICON_SIZE = 128;
-Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon, QWidget *parent):
+Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon, QWidget *parent) :
QObject(parent),
parent(parent),
programName(programName),
@@ -48,7 +47,7 @@ Notificator::Notificator(const QString &programName, QSystemTrayIcon *trayicon,
}
#ifdef USE_DBUS
interface = new QDBusInterface("org.freedesktop.Notifications",
- "/org/freedesktop/Notifications", "org.freedesktop.Notifications");
+ "/org/freedesktop/Notifications", "org.freedesktop.Notifications");
if(interface->isValid())
{
mode = Freedesktop;
diff --git a/src/qt/notificator.h b/src/qt/notificator.h
index d6298c3c0d..abab986992 100644
--- a/src/qt/notificator.h
+++ b/src/qt/notificator.h
@@ -29,7 +29,7 @@ public:
/** Create a new notificator.
@note Ownership of trayIcon is not transferred to this object.
*/
- Notificator(const QString &programName=QString(), QSystemTrayIcon *trayIcon=0, QWidget *parent=0);
+ Notificator(const QString &programName, QSystemTrayIcon *trayIcon, QWidget *parent);
~Notificator();
// Message class
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 15a873d2bd..363f432d62 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -14,6 +14,7 @@
#include "init.h"
#include "main.h"
#include "net.h"
+#include "wallet.h"
#include "walletdb.h"
#include <QSettings>
diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp
index 45b2325299..075a16dabf 100644
--- a/src/qt/receivecoinsdialog.cpp
+++ b/src/qt/receivecoinsdialog.cpp
@@ -12,6 +12,7 @@
#include "guiutil.h"
#include "receiverequestdialog.h"
#include "addresstablemodel.h"
+#include "recentrequeststablemodel.h"
#include <QMessageBox>
#include <QTextDocument>
@@ -27,6 +28,8 @@ ReceiveCoinsDialog::ReceiveCoinsDialog(QWidget *parent) :
#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
ui->clearButton->setIcon(QIcon());
ui->receiveButton->setIcon(QIcon());
+ ui->showRequestButton->setIcon(QIcon());
+ ui->removeRequestButton->setIcon(QIcon());
#endif
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
}
@@ -39,6 +42,19 @@ void ReceiveCoinsDialog::setModel(WalletModel *model)
{
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
updateDisplayUnit();
+
+ ui->recentRequestsView->setModel(model->getRecentRequestsTableModel());
+ ui->recentRequestsView->setAlternatingRowColors(true);
+ ui->recentRequestsView->setSelectionBehavior(QAbstractItemView::SelectRows);
+ ui->recentRequestsView->setSelectionMode(QAbstractItemView::ContiguousSelection);
+ ui->recentRequestsView->horizontalHeader()->resizeSection(RecentRequestsTableModel::Date, 130);
+ ui->recentRequestsView->horizontalHeader()->resizeSection(RecentRequestsTableModel::Label, 120);
+#if QT_VERSION < 0x050000
+ ui->recentRequestsView->horizontalHeader()->setResizeMode(RecentRequestsTableModel::Message, QHeaderView::Stretch);
+#else
+ ui->recentRequestsView->horizontalHeader()->setSectionResizeMode(RecentRequestsTableModel::Message, QHeaderView::Stretch);
+#endif
+ ui->recentRequestsView->horizontalHeader()->resizeSection(RecentRequestsTableModel::Amount, 100);
}
}
@@ -76,7 +92,7 @@ void ReceiveCoinsDialog::updateDisplayUnit()
void ReceiveCoinsDialog::on_receiveButton_clicked()
{
- if(!model || !model->getOptionsModel() || !model->getAddressTableModel())
+ if(!model || !model->getOptionsModel() || !model->getAddressTableModel() || !model->getRecentRequestsTableModel())
return;
QString address;
@@ -101,11 +117,48 @@ void ReceiveCoinsDialog::on_receiveButton_clicked()
address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "");
}
SendCoinsRecipient info(address, label,
- ui->reqAmount->value(), ui->reqMessage->text());
+ ui->reqAmount->value(), ui->reqMessage->text());
ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setModel(model->getOptionsModel());
dialog->setInfo(info);
- dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
clear();
+
+ /* Store request for later reference */
+ model->getRecentRequestsTableModel()->addNewRequest(info);
+}
+
+void ReceiveCoinsDialog::on_recentRequestsView_doubleClicked(const QModelIndex &index)
+{
+ const RecentRequestsTableModel *submodel = model->getRecentRequestsTableModel();
+ ReceiveRequestDialog *dialog = new ReceiveRequestDialog(this);
+ dialog->setModel(model->getOptionsModel());
+ dialog->setInfo(submodel->entry(index.row()).recipient);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->show();
+}
+
+void ReceiveCoinsDialog::on_showRequestButton_clicked()
+{
+ if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
+ return;
+ QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
+
+ foreach (QModelIndex index, selection)
+ {
+ on_recentRequestsView_doubleClicked(index);
+ }
+}
+
+void ReceiveCoinsDialog::on_removeRequestButton_clicked()
+{
+ if(!model || !model->getRecentRequestsTableModel() || !ui->recentRequestsView->selectionModel())
+ return;
+ QModelIndexList selection = ui->recentRequestsView->selectionModel()->selectedRows();
+ if(selection.empty())
+ return;
+ // correct for selection mode ContiguousSelection
+ QModelIndex firstIndex = selection.at(0);
+ model->getRecentRequestsTableModel()->removeRows(firstIndex.row(), selection.length(), firstIndex.parent());
}
diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h
index 9980edd1f5..ed4b04d361 100644
--- a/src/qt/receivecoinsdialog.h
+++ b/src/qt/receivecoinsdialog.h
@@ -14,6 +14,10 @@ namespace Ui {
class WalletModel;
class OptionsModel;
+QT_BEGIN_NAMESPACE
+class QModelIndex;
+QT_END_NAMESPACE
+
/** Dialog for requesting payment of bitcoins */
class ReceiveCoinsDialog : public QDialog
{
@@ -36,6 +40,9 @@ private:
private slots:
void on_receiveButton_clicked();
+ void on_showRequestButton_clicked();
+ void on_removeRequestButton_clicked();
+ void on_recentRequestsView_doubleClicked(const QModelIndex &index);
void updateDisplayUnit();
};
diff --git a/src/qt/receiverequestdialog.cpp b/src/qt/receiverequestdialog.cpp
index 7e92715df8..b5e45341d9 100644
--- a/src/qt/receiverequestdialog.cpp
+++ b/src/qt/receiverequestdialog.cpp
@@ -85,12 +85,10 @@ ReceiveRequestDialog::ReceiveRequestDialog(QWidget *parent) :
#ifndef USE_QRCODE
ui->btnSaveAs->setVisible(false);
- ui->btnCopyImage->setVisible(false);
ui->lblQRCode->setVisible(false);
#endif
connect(ui->btnSaveAs, SIGNAL(clicked()), ui->lblQRCode, SLOT(saveImage()));
- connect(ui->btnCopyImage, SIGNAL(clicked()), ui->lblQRCode, SLOT(copyImage()));
}
ReceiveRequestDialog::~ReceiveRequestDialog()
diff --git a/src/qt/recentrequeststablemodel.cpp b/src/qt/recentrequeststablemodel.cpp
new file mode 100644
index 0000000000..86c29dd02b
--- /dev/null
+++ b/src/qt/recentrequeststablemodel.cpp
@@ -0,0 +1,129 @@
+// Copyright (c) 2011-2013 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "recentrequeststablemodel.h"
+
+#include "bitcoinunits.h"
+#include "guiutil.h"
+#include "optionsmodel.h"
+
+RecentRequestsTableModel::RecentRequestsTableModel(CWallet *wallet, WalletModel *parent) :
+ walletModel(parent)
+{
+ Q_UNUSED(wallet);
+
+ /* These columns must match the indices in the ColumnIndex enumeration */
+ columns << tr("Date") << tr("Label") << tr("Message") << tr("Amount");
+}
+
+RecentRequestsTableModel::~RecentRequestsTableModel()
+{
+ /* Intentionally left empty */
+}
+
+int RecentRequestsTableModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return list.length();
+}
+
+int RecentRequestsTableModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return columns.length();
+}
+
+QVariant RecentRequestsTableModel::data(const QModelIndex &index, int role) const
+{
+ if(!index.isValid() || index.row() >= list.length())
+ return QVariant();
+
+ const RecentRequestEntry *rec = &list[index.row()];
+
+ if(role == Qt::DisplayRole || role == Qt::EditRole)
+ {
+ switch(index.column())
+ {
+ case Date:
+ return GUIUtil::dateTimeStr(rec->date);
+ case Label:
+ if(rec->recipient.label.isEmpty() && role == Qt::DisplayRole)
+ {
+ return tr("(no label)");
+ }
+ else
+ {
+ return rec->recipient.label;
+ }
+ case Message:
+ if(rec->recipient.message.isEmpty() && role == Qt::DisplayRole)
+ {
+ return tr("(no message)");
+ }
+ else
+ {
+ return rec->recipient.message;
+ }
+ case Amount:
+ return BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), rec->recipient.amount);
+ }
+ }
+ return QVariant();
+}
+
+bool RecentRequestsTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ return true;
+}
+
+QVariant RecentRequestsTableModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if(orientation == Qt::Horizontal)
+ {
+ if(role == Qt::DisplayRole && section < columns.size())
+ {
+ return columns[section];
+ }
+ }
+ return QVariant();
+}
+
+QModelIndex RecentRequestsTableModel::index(int row, int column, const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return createIndex(row, column);
+}
+
+bool RecentRequestsTableModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ Q_UNUSED(parent);
+
+ if(count > 0 && row >= 0 && (row+count) <= list.size())
+ {
+ beginRemoveRows(parent, row, row + count - 1);
+ list.erase(list.begin() + row, list.begin() + row + count);
+ endRemoveRows();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Qt::ItemFlags RecentRequestsTableModel::flags(const QModelIndex &index) const
+{
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+}
+
+void RecentRequestsTableModel::addNewRequest(const SendCoinsRecipient &recipient)
+{
+ RecentRequestEntry newEntry;
+ newEntry.date = QDateTime::currentDateTime();
+ newEntry.recipient = recipient;
+ beginInsertRows(QModelIndex(), 0, 0);
+ list.prepend(newEntry);
+ endInsertRows();
+}
diff --git a/src/qt/recentrequeststablemodel.h b/src/qt/recentrequeststablemodel.h
new file mode 100644
index 0000000000..3aab7b0a48
--- /dev/null
+++ b/src/qt/recentrequeststablemodel.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2011-2013 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef RECENTREQUESTSTABLEMODEL_H
+#define RECENTREQUESTSTABLEMODEL_H
+
+#include "walletmodel.h"
+
+#include <QAbstractTableModel>
+#include <QStringList>
+#include <QDateTime>
+
+class CWallet;
+
+struct RecentRequestEntry
+{
+ QDateTime date;
+ SendCoinsRecipient recipient;
+};
+
+/** Model for list of recently generated payment requests / bitcoin URIs.
+ * Part of wallet model.
+ */
+class RecentRequestsTableModel: public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ explicit RecentRequestsTableModel(CWallet *wallet, WalletModel *parent);
+ ~RecentRequestsTableModel();
+
+ enum ColumnIndex {
+ Date = 0,
+ Label = 1,
+ Message = 2,
+ Amount = 3
+ };
+
+ /** @name Methods overridden from QAbstractTableModel
+ @{*/
+ int rowCount(const QModelIndex &parent) const;
+ int columnCount(const QModelIndex &parent) const;
+ QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ QModelIndex index(int row, int column, const QModelIndex &parent) const;
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ /*@}*/
+
+ const RecentRequestEntry &entry(int row) const { return list[row]; }
+ void addNewRequest(const SendCoinsRecipient &recipient);
+
+private:
+ WalletModel *walletModel;
+ QStringList columns;
+ QList<RecentRequestEntry> list;
+};
+
+#endif
diff --git a/src/qt/res/bitcoin-qt-res.rc b/src/qt/res/bitcoin-qt-res.rc
index 3e3672a835..ee23ae9b78 100644
--- a/src/qt/res/bitcoin-qt-res.rc
+++ b/src/qt/res/bitcoin-qt-res.rc
@@ -21,13 +21,13 @@ BEGIN
BLOCK "040904E4" // U.S. English - multilingual (hex)
BEGIN
VALUE "CompanyName", "Bitcoin"
- VALUE "FileDescription", "Bitcoin-Qt (OSS GUI client for Bitcoin)"
+ VALUE "FileDescription", "Bitcoin Core (OSS GUI client for Bitcoin)"
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "InternalName", "bitcoin-qt"
VALUE "LegalCopyright", COPYRIGHT_STR
VALUE "LegalTrademarks1", "Distributed under the MIT/X11 software license, see the accompanying file COPYING or http://www.opensource.org/licenses/mit-license.php."
VALUE "OriginalFilename", "bitcoin-qt.exe"
- VALUE "ProductName", "Bitcoin-Qt"
+ VALUE "ProductName", "Bitcoin Core"
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index d43cdc7e5f..a8470572dd 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -284,7 +284,7 @@ void RPCConsole::setClientModel(ClientModel *model)
ui->buildDate->setText(model->formatBuildDate());
ui->startupTime->setText(model->formatClientStartupTime());
- ui->isTestNet->setChecked(model->isTestNet());
+ ui->networkName->setText(model->getNetworkName());
}
}
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 0a4e80811f..4bf5c3c479 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -306,12 +306,14 @@ void SendCoinsDialog::updateTabsAndLabels()
void SendCoinsDialog::removeEntry(SendCoinsEntry* entry)
{
- entry->deleteLater();
+ entry->hide();
- // If the last entry was removed add an empty one
- if (!ui->entries->count())
+ // If the last entry is about to be removed add an empty one
+ if (ui->entries->count() == 1)
addEntry();
+ entry->deleteLater();
+
updateTabsAndLabels();
}
@@ -450,9 +452,8 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn
msgParams.first = tr("The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
msgParams.second = CClientUIInterface::MSG_ERROR;
break;
- // OK and Aborted are included to prevent a compiler warning.
+ // included to prevent a compiler warning.
case WalletModel::OK:
- case WalletModel::Aborted:
default:
return;
}
@@ -543,7 +544,7 @@ void SendCoinsDialog::coinControlChangeChecked(int state)
}
// Coin Control: custom change address changed
-void SendCoinsDialog::coinControlChangeEdited(const QString & text)
+void SendCoinsDialog::coinControlChangeEdited(const QString& text)
{
if (model)
{
diff --git a/src/qt/splashscreen.cpp b/src/qt/splashscreen.cpp
index 12280bb702..6fb834c045 100644
--- a/src/qt/splashscreen.cpp
+++ b/src/qt/splashscreen.cpp
@@ -4,14 +4,13 @@
#include "splashscreen.h"
-#include "chainparams.h"
#include "clientversion.h"
#include "util.h"
#include <QApplication>
#include <QPainter>
-SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) :
+SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTestNet) :
QSplashScreen(pixmap, f)
{
// set reference point, paddings
@@ -23,16 +22,16 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) :
float fontFactor = 1.0;
// define text to place
- QString titleText = QString(QApplication::applicationName()).replace(QString("-testnet"), QString(""), Qt::CaseSensitive); // cut of testnet, place it as single object further down
+ QString titleText = tr("Bitcoin Core");
QString versionText = QString("Version %1").arg(QString::fromStdString(FormatFullVersion()));
- QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin developers"));
+ QString copyrightText = QChar(0xA9)+QString(" 2009-%1 ").arg(COPYRIGHT_YEAR) + QString(tr("The Bitcoin Core developers"));
QString testnetAddText = QString(tr("[testnet]")); // define text to place as single text object
QString font = "Arial";
// load the bitmap for writing some text over it
QPixmap newPixmap;
- if(TestNet()) {
+ if(isTestNet) {
newPixmap = QPixmap(":/images/splash_testnet");
}
else {
@@ -72,7 +71,7 @@ SplashScreen::SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f) :
pixPaint.drawText(newPixmap.width()-titleTextWidth-paddingRight,paddingTop+titleCopyrightVSpace,copyrightText);
// draw testnet string if testnet is on
- if(TestNet()) {
+ if(isTestNet) {
QFont boldFont = QFont(font, 10*fontFactor);
boldFont.setWeight(QFont::Bold);
pixPaint.setFont(boldFont);
diff --git a/src/qt/splashscreen.h b/src/qt/splashscreen.h
index ddf040593d..070e376c95 100644
--- a/src/qt/splashscreen.h
+++ b/src/qt/splashscreen.h
@@ -14,7 +14,7 @@ class SplashScreen : public QSplashScreen
Q_OBJECT
public:
- explicit SplashScreen(const QPixmap &pixmap = QPixmap(), Qt::WindowFlags f = 0);
+ explicit SplashScreen(const QPixmap &pixmap, Qt::WindowFlags f, bool isTestNet);
};
#endif // SPLASHSCREEN_H
diff --git a/src/qt/test/Makefile.am b/src/qt/test/Makefile.am
index 29247a79a1..cb6874700e 100644
--- a/src/qt/test/Makefile.am
+++ b/src/qt/test/Makefile.am
@@ -17,7 +17,7 @@ BUILT_SOURCES = $(TEST_QT_MOC_CPP)
test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(QT_INCLUDES) $(QT_TEST_INCLUDES)
test_bitcoin_qt_SOURCES = test_main.cpp uritests.cpp paymentservertests.cpp $(TEST_QT_H)
nodist_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP)
-test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) \
+test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) $(LIBBITCOIN_WALLET) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) \
$(LIBMEMENV) $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) \
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS)
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 2470af41a0..f08342b83e 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -6,6 +6,7 @@
#include "addresstablemodel.h"
#include "guiconstants.h"
+#include "recentrequeststablemodel.h"
#include "transactiontablemodel.h"
#include "base58.h"
@@ -26,6 +27,7 @@
WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0),
transactionTableModel(0),
+ recentRequestsTableModel(0),
cachedBalance(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0),
cachedNumTransactions(0),
cachedEncryptionStatus(Unencrypted),
@@ -33,6 +35,7 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p
{
addressTableModel = new AddressTableModel(wallet, this);
transactionTableModel = new TransactionTableModel(wallet, this);
+ recentRequestsTableModel = new RecentRequestsTableModel(wallet, this);
// This timer will be fired repeatedly to update the balance
pollTimer = new QTimer(this);
@@ -325,6 +328,11 @@ TransactionTableModel *WalletModel::getTransactionTableModel()
return transactionTableModel;
}
+RecentRequestsTableModel *WalletModel::getRecentRequestsTableModel()
+{
+ return recentRequestsTableModel;
+}
+
WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const
{
if(!wallet->IsCrypted())
diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h
index 32ddbbc6f6..1a4d25615a 100644
--- a/src/qt/walletmodel.h
+++ b/src/qt/walletmodel.h
@@ -17,6 +17,7 @@
class AddressTableModel;
class OptionsModel;
+class RecentRequestsTableModel;
class TransactionTableModel;
class WalletModelTransaction;
@@ -74,8 +75,7 @@ public:
AmountWithFeeExceedsBalance,
DuplicateAddress,
TransactionCreationFailed, // Error returned when wallet is still locked
- TransactionCommitFailed,
- Aborted
+ TransactionCommitFailed
};
enum EncryptionStatus
@@ -88,6 +88,7 @@ public:
OptionsModel *getOptionsModel();
AddressTableModel *getAddressTableModel();
TransactionTableModel *getTransactionTableModel();
+ RecentRequestsTableModel *getRecentRequestsTableModel();
qint64 getBalance(const CCoinControl *coinControl = NULL) const;
qint64 getUnconfirmedBalance() const;
@@ -101,7 +102,7 @@ public:
// Return status record for SendCoins, contains error id + information
struct SendCoinsReturn
{
- SendCoinsReturn(StatusCode status = Aborted):
+ SendCoinsReturn(StatusCode status = OK):
status(status) {}
StatusCode status;
};
@@ -160,6 +161,7 @@ private:
AddressTableModel *addressTableModel;
TransactionTableModel *transactionTableModel;
+ RecentRequestsTableModel *recentRequestsTableModel;
// Cache some values to be able to detect changes
qint64 cachedBalance;
diff --git a/src/qt/walletmodeltransaction.h b/src/qt/walletmodeltransaction.h
index a948808a75..b7e85bcd11 100644
--- a/src/qt/walletmodeltransaction.h
+++ b/src/qt/walletmodeltransaction.h
@@ -39,9 +39,6 @@ private:
CWalletTx *walletTransaction;
CReserveKey *keyChange;
qint64 fee;
-
-public slots:
-
};
#endif // WALLETMODELTRANSACTION_H
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index ea71d58aa6..1a9c7866db 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -263,8 +263,8 @@ void WalletView::usedSendingAddresses()
if(!walletModel)
return;
AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
- dlg->setModel(walletModel->getAddressTableModel());
dlg->setAttribute(Qt::WA_DeleteOnClose);
+ dlg->setModel(walletModel->getAddressTableModel());
dlg->show();
}
@@ -273,7 +273,7 @@ void WalletView::usedReceivingAddresses()
if(!walletModel)
return;
AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);
- dlg->setModel(walletModel->getAddressTableModel());
dlg->setAttribute(Qt::WA_DeleteOnClose);
+ dlg->setModel(walletModel->getAddressTableModel());
dlg->show();
}
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index d951691621..ecfa06ac5a 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -96,6 +96,7 @@ public slots:
/** Re-emit encryption status signal */
void updateEncryptionStatus();
+
signals:
/** Signal that we want to show the main window */
void showNormalIfMinimized();
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 34ae6e0543..661deffb19 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -127,30 +127,6 @@ Value getdifficulty(const Array& params, bool fHelp)
}
-Value settxfee(const Array& params, bool fHelp)
-{
- if (fHelp || params.size() < 1 || params.size() > 1)
- throw runtime_error(
- "settxfee amount\n"
- "\nSet the transaction fee. 'amount' is a real and is rounded to the nearest 0.00000001\n"
- "\nArguments:\n"
- "1. amount (numeric, required) The transaction fee in btc rounded to the nearest 0.00000001\n"
- "\nResult\n"
- "true|false (boolean) Returns true if successful\n"
- "\nExamples:\n"
- + HelpExampleCli("settxfee", "0.00001")
- + HelpExampleRpc("settxfee", "0.00001")
- );
-
- // Amount
- int64_t nAmount = 0;
- if (params[0].get_real() != 0.0)
- nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
-
- nTransactionFee = nAmount;
- return true;
-}
-
Value getrawmempool(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 1)
diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp
index a3168917fc..c404ac274b 100644
--- a/src/rpcclient.cpp
+++ b/src/rpcclient.cpp
@@ -257,7 +257,7 @@ std::string HelpMessageCli(bool mainProgram)
strUsage += " -datadir=<dir> " + _("Specify data directory") + "\n";
strUsage += " -testnet " + _("Use the test network") + "\n";
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be "
- "solved instantly. This is intended for regression testing tools and app development.") + "\n";
+ "solved instantly. This is intended for regression testing tools and app development.") + "\n";
} else {
strUsage += _("RPC client options:") + "\n";
}
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index 131a258c84..1a8462fdea 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -5,13 +5,14 @@
#include "rpcserver.h"
#include "chainparams.h"
-#include "db.h"
#include "init.h"
#include "net.h"
#include "main.h"
#include "miner.h"
+#ifdef ENABLE_WALLET
+#include "db.h"
#include "wallet.h"
-
+#endif
#include <stdint.h>
#include "json/json_spirit_utils.h"
@@ -20,7 +21,8 @@
using namespace json_spirit;
using namespace std;
-// Key used by getwork/getblocktemplate miners.
+#ifdef ENABLE_WALLET
+// Key used by getwork miners.
// Allocated in InitRPCMining, free'd in ShutdownRPCMining
static CReserveKey* pMiningKey = NULL;
@@ -40,6 +42,14 @@ void ShutdownRPCMining()
delete pMiningKey; pMiningKey = NULL;
}
+#else
+void InitRPCMining()
+{
+}
+void ShutdownRPCMining()
+{
+}
+#endif
// Return average network hashes per second based on the last 'lookup' blocks,
// or from the last difficulty change if 'lookup' is nonpositive.
@@ -99,7 +109,7 @@ Value getnetworkhashps(const Array& params, bool fHelp)
return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
}
-
+#ifdef ENABLE_WALLET
Value getgenerate(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -197,7 +207,6 @@ Value setgenerate(const Array& params, bool fHelp)
return Value::null;
}
-
Value gethashespersec(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@@ -216,6 +225,7 @@ Value gethashespersec(const Array& params, bool fHelp)
return (boost::int64_t)0;
return (boost::int64_t)dHashesPerSec;
}
+#endif
Value getmininginfo(const Array& params, bool fHelp)
@@ -248,16 +258,19 @@ Value getmininginfo(const Array& params, bool fHelp)
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
- obj.push_back(Pair("generate", getgenerate(params, false)));
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
- obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
obj.push_back(Pair("networkhashps", getnetworkhashps(params, false)));
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
obj.push_back(Pair("testnet", TestNet()));
+#ifdef ENABLE_WALLET
+ obj.push_back(Pair("generate", getgenerate(params, false)));
+ obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
+#endif
return obj;
}
+#ifdef ENABLE_WALLET
Value getwork(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 1)
@@ -381,7 +394,7 @@ Value getwork(const Array& params, bool fHelp)
return CheckWork(pblock, *pwalletMain, *pMiningKey);
}
}
-
+#endif
Value getblocktemplate(const Array& params, bool fHelp)
{
diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp
new file mode 100644
index 0000000000..c61cc4192b
--- /dev/null
+++ b/src/rpcmisc.cpp
@@ -0,0 +1,326 @@
+// Copyright (c) 2010 Satoshi Nakamoto
+// Copyright (c) 2009-2013 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "base58.h"
+#include "rpcserver.h"
+#include "init.h"
+#include "main.h"
+#include "net.h"
+#include "netbase.h"
+#include "util.h"
+#ifdef ENABLE_WALLET
+#include "wallet.h"
+#include "walletdb.h"
+#endif
+
+#include <stdint.h>
+
+#include <boost/assign/list_of.hpp>
+#include "json/json_spirit_utils.h"
+#include "json/json_spirit_value.h"
+
+using namespace std;
+using namespace boost;
+using namespace boost::assign;
+using namespace json_spirit;
+
+Value getinfo(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 0)
+ throw runtime_error(
+ "getinfo\n"
+ "Returns an object containing various state info.\n"
+ "\nResult:\n"
+ "{\n"
+ " \"version\": xxxxx, (numeric) the server version\n"
+ " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
+ " \"walletversion\": xxxxx, (numeric) the wallet version\n"
+ " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
+ " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
+ " \"timeoffset\": xxxxx, (numeric) the time offset\n"
+ " \"connections\": xxxxx, (numeric) the number of connections\n"
+ " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
+ " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
+ " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
+ " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
+ " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
+ " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc\n"
+ " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
+ " \"errors\": \"...\" (string) any error messages\n"
+ "}\n"
+ "\nExamples:\n"
+ + HelpExampleCli("getinfo", "")
+ + HelpExampleRpc("getinfo", "")
+ );
+
+ proxyType proxy;
+ GetProxy(NET_IPV4, proxy);
+
+ Object obj;
+ obj.push_back(Pair("version", (int)CLIENT_VERSION));
+ obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
+#ifdef ENABLE_WALLET
+ if (pwalletMain) {
+ obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
+ obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
+ }
+#endif
+ obj.push_back(Pair("blocks", (int)chainActive.Height()));
+ obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset()));
+ obj.push_back(Pair("connections", (int)vNodes.size()));
+ obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
+ obj.push_back(Pair("difficulty", (double)GetDifficulty()));
+ obj.push_back(Pair("testnet", TestNet()));
+#ifdef ENABLE_WALLET
+ if (pwalletMain) {
+ obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
+ obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
+ }
+ obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
+ if (pwalletMain && pwalletMain->IsCrypted())
+ obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
+#endif
+ obj.push_back(Pair("errors", GetWarnings("statusbar")));
+ return obj;
+}
+
+#ifdef ENABLE_WALLET
+class DescribeAddressVisitor : public boost::static_visitor<Object>
+{
+public:
+ Object operator()(const CNoDestination &dest) const { return Object(); }
+
+ Object operator()(const CKeyID &keyID) const {
+ Object obj;
+ CPubKey vchPubKey;
+ pwalletMain->GetPubKey(keyID, vchPubKey);
+ obj.push_back(Pair("isscript", false));
+ obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
+ obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
+ return obj;
+ }
+
+ Object operator()(const CScriptID &scriptID) const {
+ Object obj;
+ obj.push_back(Pair("isscript", true));
+ CScript subscript;
+ pwalletMain->GetCScript(scriptID, subscript);
+ std::vector<CTxDestination> addresses;
+ txnouttype whichType;
+ int nRequired;
+ ExtractDestinations(subscript, whichType, addresses, nRequired);
+ obj.push_back(Pair("script", GetTxnOutputType(whichType)));
+ obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
+ Array a;
+ BOOST_FOREACH(const CTxDestination& addr, addresses)
+ a.push_back(CBitcoinAddress(addr).ToString());
+ obj.push_back(Pair("addresses", a));
+ if (whichType == TX_MULTISIG)
+ obj.push_back(Pair("sigsrequired", nRequired));
+ return obj;
+ }
+};
+#endif
+
+Value validateaddress(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "validateaddress \"bitcoinaddress\"\n"
+ "\nReturn information about the given bitcoin address.\n"
+ "\nArguments:\n"
+ "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
+ "\nResult:\n"
+ "{\n"
+ " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
+ " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
+ " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
+ " \"isscript\" : true|false, (boolean) If the key is a script\n"
+ " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
+ " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
+ " \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\n"
+ "}\n"
+ "\nExamples:\n"
+ + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
+ + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
+ );
+
+ CBitcoinAddress address(params[0].get_str());
+ bool isValid = address.IsValid();
+
+ Object ret;
+ ret.push_back(Pair("isvalid", isValid));
+ if (isValid)
+ {
+ CTxDestination dest = address.Get();
+ string currentAddress = address.ToString();
+ ret.push_back(Pair("address", currentAddress));
+#ifdef ENABLE_WALLET
+ bool fMine = pwalletMain ? IsMine(*pwalletMain, dest) : false;
+ ret.push_back(Pair("ismine", fMine));
+ if (fMine) {
+ Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
+ ret.insert(ret.end(), detail.begin(), detail.end());
+ }
+ if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
+ ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
+#endif
+ }
+ return ret;
+}
+
+//
+// Used by addmultisigaddress / createmultisig:
+//
+CScript _createmultisig(const Array& params)
+{
+ int nRequired = params[0].get_int();
+ const Array& keys = params[1].get_array();
+
+ // Gather public keys
+ if (nRequired < 1)
+ throw runtime_error("a multisignature address must require at least one key to redeem");
+ if ((int)keys.size() < nRequired)
+ throw runtime_error(
+ strprintf("not enough keys supplied "
+ "(got %"PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired));
+ std::vector<CPubKey> pubkeys;
+ pubkeys.resize(keys.size());
+ for (unsigned int i = 0; i < keys.size(); i++)
+ {
+ const std::string& ks = keys[i].get_str();
+#ifdef ENABLE_WALLET
+ // Case 1: Bitcoin address and we have full public key:
+ CBitcoinAddress address(ks);
+ if (pwalletMain && address.IsValid())
+ {
+ CKeyID keyID;
+ if (!address.GetKeyID(keyID))
+ throw runtime_error(
+ strprintf("%s does not refer to a key",ks.c_str()));
+ CPubKey vchPubKey;
+ if (!pwalletMain->GetPubKey(keyID, vchPubKey))
+ throw runtime_error(
+ strprintf("no full public key for address %s",ks.c_str()));
+ if (!vchPubKey.IsFullyValid())
+ throw runtime_error(" Invalid public key: "+ks);
+ pubkeys[i] = vchPubKey;
+ }
+
+ // Case 2: hex public key
+ else
+#endif
+ if (IsHex(ks))
+ {
+ CPubKey vchPubKey(ParseHex(ks));
+ if (!vchPubKey.IsFullyValid())
+ throw runtime_error(" Invalid public key: "+ks);
+ pubkeys[i] = vchPubKey;
+ }
+ else
+ {
+ throw runtime_error(" Invalid public key: "+ks);
+ }
+ }
+ CScript result;
+ result.SetMultisig(nRequired, pubkeys);
+ return result;
+}
+
+Value createmultisig(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() < 2 || params.size() > 2)
+ {
+ string msg = "createmultisig nrequired [\"key\",...]\n"
+ "\nCreates a multi-signature address with n signature of m keys required.\n"
+ "It returns a json object with the address and redeemScript.\n"
+
+ "\nArguments:\n"
+ "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
+ "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
+ " [\n"
+ " \"key\" (string) bitcoin address or hex-encoded public key\n"
+ " ,...\n"
+ " ]\n"
+
+ "\nResult:\n"
+ "{\n"
+ " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
+ " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
+ "}\n"
+
+ "\nExamples:\n"
+ "\nCreate a multisig address from 2 addresses\n"
+ + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
+ "\nAs a json rpc call\n"
+ + HelpExampleRpc("icreatemultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
+ ;
+ throw runtime_error(msg);
+ }
+
+ // Construct using pay-to-script-hash:
+ CScript inner = _createmultisig(params);
+ CScriptID innerID = inner.GetID();
+ CBitcoinAddress address(innerID);
+
+ Object result;
+ result.push_back(Pair("address", address.ToString()));
+ result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
+
+ return result;
+}
+
+Value verifymessage(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 3)
+ throw runtime_error(
+ "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
+ "\nVerify a signed message\n"
+ "\nArguments:\n"
+ "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
+ "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
+ "3. \"message\" (string, required) The message that was signed.\n"
+ "\nResult:\n"
+ "true|false (boolean) If the signature is verified or not.\n"
+ "\nExamples:\n"
+ "\nUnlock the wallet for 30 seconds\n"
+ + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
+ "\nCreate the signature\n"
+ + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
+ "\nVerify the signature\n"
+ + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
+ "\nAs json rpc\n"
+ + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
+ );
+
+ string strAddress = params[0].get_str();
+ string strSign = params[1].get_str();
+ string strMessage = params[2].get_str();
+
+ CBitcoinAddress addr(strAddress);
+ if (!addr.IsValid())
+ throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
+
+ CKeyID keyID;
+ if (!addr.GetKeyID(keyID))
+ throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
+
+ bool fInvalid = false;
+ vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
+
+ if (fInvalid)
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
+
+ CHashWriter ss(SER_GETHASH, 0);
+ ss << strMessageMagic;
+ ss << strMessage;
+
+ CPubKey pubkey;
+ if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
+ return false;
+
+ return (pubkey.GetID() == keyID);
+}
+
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index b492b57ded..06ae7070c3 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -3,11 +3,17 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "rpcserver.h"
+
+#include "main.h"
#include "net.h"
#include "netbase.h"
#include "protocol.h"
#include "sync.h"
#include "util.h"
+#ifdef ENABLE_WALLET
+#include "init.h" // for getinfo
+#include "wallet.h" // for getinfo
+#endif
#include <inttypes.h>
@@ -110,7 +116,8 @@ Value getpeerinfo(const Array& params, bool fHelp)
BOOST_FOREACH(const CNodeStats& stats, vstats) {
Object obj;
-
+ CNodeStateStats statestats;
+ bool fStateStats = GetNodeStateStats(stats.nodeid, statestats);
obj.push_back(Pair("addr", stats.addrName));
if (!(stats.addrLocal.empty()))
obj.push_back(Pair("addrlocal", stats.addrLocal));
@@ -130,7 +137,9 @@ Value getpeerinfo(const Array& params, bool fHelp)
obj.push_back(Pair("subver", stats.cleanSubVer));
obj.push_back(Pair("inbound", stats.fInbound));
obj.push_back(Pair("startingheight", stats.nStartingHeight));
- obj.push_back(Pair("banscore", stats.nMisbehavior));
+ if (fStateStats) {
+ obj.push_back(Pair("banscore", statestats.nMisbehavior));
+ }
if (stats.fSyncNode)
obj.push_back(Pair("syncnode", true));
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index a45c2cc1f3..86025918ef 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -8,7 +8,12 @@
#include "init.h"
#include "net.h"
#include "uint256.h"
+#include "core.h"
+#include "main.h"
+#include "keystore.h"
+#ifdef ENABLE_WALLET
#include "wallet.h"
+#endif
#include <stdint.h>
@@ -190,6 +195,7 @@ Value getrawtransaction(const Array& params, bool fHelp)
return result;
}
+#ifdef ENABLE_WALLET
Value listunspent(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 3)
@@ -303,6 +309,7 @@ Value listunspent(const Array& params, bool fHelp)
return results;
}
+#endif
Value createrawtransaction(const Array& params, bool fHelp)
{
@@ -508,7 +515,9 @@ Value signrawtransaction(const Array& params, bool fHelp)
"this transaction depends on but may not yet be in the block chain.\n"
"The third optional argument (may be null) is an array of base58-encoded private\n"
"keys that, if given, will be the only keys used to sign the transaction.\n"
+#ifdef ENABLE_WALLET
+ HelpRequiringPassphrase() + "\n"
+#endif
"\nArguments:\n"
"1. \"hexstring\" (string, required) The transaction hex string\n"
@@ -605,8 +614,10 @@ Value signrawtransaction(const Array& params, bool fHelp)
tempKeystore.AddKey(key);
}
}
+#ifdef ENABLE_WALLET
else
EnsureWalletIsUnlocked();
+#endif
// Add previous txouts given in the RPC call:
if (params.size() > 1 && params[1].type() != null_type)
@@ -662,7 +673,11 @@ Value signrawtransaction(const Array& params, bool fHelp)
}
}
+#ifdef ENABLE_WALLET
const CKeyStore& keystore = ((fGivenKeys || !pwalletMain) ? tempKeystore : *pwalletMain);
+#else
+ const CKeyStore& keystore = tempKeystore;
+#endif
int nHashType = SIGHASH_ALL;
if (params.size() > 3 && params[3].type() != null_type)
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 403567203c..9f2100a8d7 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -9,7 +9,10 @@
#include "init.h"
#include "main.h"
#include "util.h"
+#include "ui_interface.h"
+#ifdef ENABLE_WALLET
#include "wallet.h"
+#endif
#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
@@ -149,8 +152,10 @@ string CRPCTable::help(string strCommand) const
continue;
if (strCommand != "" && strMethod != strCommand)
continue;
+#ifdef ENABLE_WALLET
if (pcmd->reqWallet && !pwalletMain)
continue;
+#endif
try
{
@@ -228,12 +233,31 @@ static const CRPCCommand vRPCCommands[] =
{ "getaddednodeinfo", &getaddednodeinfo, true, true, false },
{ "getnettotals", &getnettotals, true, true, false },
{ "getdifficulty", &getdifficulty, true, false, false },
- { "getnetworkhashps", &getnetworkhashps, true, false, false },
- { "getgenerate", &getgenerate, true, false, false },
- { "setgenerate", &setgenerate, true, true, false },
- { "gethashespersec", &gethashespersec, true, false, false },
{ "getinfo", &getinfo, true, false, false },
+ { "getrawmempool", &getrawmempool, true, false, false },
+ { "getblock", &getblock, false, false, false },
+ { "getblockhash", &getblockhash, false, false, false },
+ { "getrawtransaction", &getrawtransaction, false, false, false },
+ { "createrawtransaction", &createrawtransaction, false, false, false },
+ { "decoderawtransaction", &decoderawtransaction, false, false, false },
+ { "decodescript", &decodescript, false, false, false },
+ { "signrawtransaction", &signrawtransaction, false, false, false },
+ { "sendrawtransaction", &sendrawtransaction, false, false, false },
+ { "gettxoutsetinfo", &gettxoutsetinfo, true, false, false },
+ { "gettxout", &gettxout, true, false, false },
+ { "verifychain", &verifychain, true, false, false },
+
+ /* Mining */
+ { "getnetworkhashps", &getnetworkhashps, true, false, false },
{ "getmininginfo", &getmininginfo, true, false, false },
+ { "getblocktemplate", &getblocktemplate, true, false, false },
+ { "submitblock", &submitblock, false, false, false },
+ { "validateaddress", &validateaddress, true, false, false },
+ { "createmultisig", &createmultisig, true, true , false },
+ { "verifymessage", &verifymessage, false, false, false },
+
+#ifdef ENABLE_WALLET
+ /* Wallet */
{ "getnewaddress", &getnewaddress, true, false, true },
{ "getaccountaddress", &getaccountaddress, true, false, true },
{ "getrawchangeaddress", &getrawchangeaddress, true, false, true },
@@ -251,44 +275,33 @@ static const CRPCCommand vRPCCommands[] =
{ "walletpassphrasechange", &walletpassphrasechange, false, false, true },
{ "walletlock", &walletlock, true, false, true },
{ "encryptwallet", &encryptwallet, false, false, true },
- { "validateaddress", &validateaddress, true, false, false },
{ "getbalance", &getbalance, false, false, true },
{ "getunconfirmedbalance", &getunconfirmedbalance, false, false, true },
{ "move", &movecmd, false, false, true },
{ "sendfrom", &sendfrom, false, false, true },
{ "sendmany", &sendmany, false, false, true },
{ "addmultisigaddress", &addmultisigaddress, false, false, true },
- { "createmultisig", &createmultisig, true, true , false },
- { "getrawmempool", &getrawmempool, true, false, false },
- { "getblock", &getblock, false, false, false },
- { "getblockhash", &getblockhash, false, false, false },
{ "gettransaction", &gettransaction, false, false, true },
{ "listtransactions", &listtransactions, false, false, true },
{ "listaddressgroupings", &listaddressgroupings, false, false, true },
{ "signmessage", &signmessage, false, false, true },
- { "verifymessage", &verifymessage, false, false, false },
- { "getwork", &getwork, true, false, true },
{ "listaccounts", &listaccounts, false, false, true },
- { "settxfee", &settxfee, false, false, true },
- { "getblocktemplate", &getblocktemplate, true, false, false },
- { "submitblock", &submitblock, false, false, false },
{ "listsinceblock", &listsinceblock, false, false, true },
{ "dumpprivkey", &dumpprivkey, true, false, true },
{ "dumpwallet", &dumpwallet, true, false, true },
{ "importprivkey", &importprivkey, false, false, true },
{ "importwallet", &importwallet, false, false, true },
{ "listunspent", &listunspent, false, false, true },
- { "getrawtransaction", &getrawtransaction, false, false, false },
- { "createrawtransaction", &createrawtransaction, false, false, false },
- { "decoderawtransaction", &decoderawtransaction, false, false, false },
- { "decodescript", &decodescript, false, false, false },
- { "signrawtransaction", &signrawtransaction, false, false, false },
- { "sendrawtransaction", &sendrawtransaction, false, false, false },
- { "gettxoutsetinfo", &gettxoutsetinfo, true, false, false },
- { "gettxout", &gettxout, true, false, false },
{ "lockunspent", &lockunspent, false, false, true },
{ "listlockunspent", &listlockunspent, false, false, true },
- { "verifychain", &verifychain, true, false, false },
+ { "settxfee", &settxfee, false, false, true },
+
+ /* Wallet-enabled mining */
+ { "getgenerate", &getgenerate, true, false, false },
+ { "setgenerate", &setgenerate, true, true, false },
+ { "gethashespersec", &gethashespersec, true, false, false },
+ { "getwork", &getwork, true, false, true },
+#endif // ENABLE_WALLET
};
CRPCTable::CRPCTable()
@@ -789,8 +802,10 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
const CRPCCommand *pcmd = tableRPC[strMethod];
if (!pcmd)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found");
+#ifdef ENABLE_WALLET
if (pcmd->reqWallet && !pwalletMain)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
+#endif
// Observe safe mode
string strWarning = GetWarnings("rpc");
@@ -805,6 +820,7 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
{
if (pcmd->threadSafe)
result = pcmd->actor(params, false);
+#ifdef ENABLE_WALLET
else if (!pwalletMain) {
LOCK(cs_main);
result = pcmd->actor(params, false);
@@ -812,6 +828,12 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
LOCK2(cs_main, pwalletMain->cs_wallet);
result = pcmd->actor(params, false);
}
+#else // ENABLE_WALLET
+ else {
+ LOCK(cs_main);
+ result = pcmd->actor(params, false);
+ }
+#endif // !ENABLE_WALLET
}
return result;
}
@@ -821,4 +843,13 @@ json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_s
}
}
+std::string HelpExampleCli(string methodname, string args){
+ return "> bitcoin-cli " + methodname + " " + args + "\n";
+}
+
+std::string HelpExampleRpc(string methodname, string args){
+ return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
+ "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
+}
+
const CRPCTable tableRPC;
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index fe42b74dea..8ad5c9c51d 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -33,15 +33,6 @@ std::string HelpRequiringPassphrase()
: "";
}
-std::string HelpExampleCli(string methodname, string args){
- return "> bitcoin-cli " + methodname + " " + args + "\n";
-}
-
-std::string HelpExampleRpc(string methodname, string args){
- return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", "
- "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
-}
-
void EnsureWalletIsUnlocked()
{
if (pwalletMain->IsLocked())
@@ -75,64 +66,6 @@ string AccountFromValue(const Value& value)
return strAccount;
}
-Value getinfo(const Array& params, bool fHelp)
-{
- if (fHelp || params.size() != 0)
- throw runtime_error(
- "getinfo\n"
- "Returns an object containing various state info.\n"
- "\nResult:\n"
- "{\n"
- " \"version\": xxxxx, (numeric) the server version\n"
- " \"protocolversion\": xxxxx, (numeric) the protocol version\n"
- " \"walletversion\": xxxxx, (numeric) the wallet version\n"
- " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n"
- " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n"
- " \"timeoffset\": xxxxx, (numeric) the time offset\n"
- " \"connections\": xxxxx, (numeric) the number of connections\n"
- " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n"
- " \"difficulty\": xxxxxx, (numeric) the current difficulty\n"
- " \"testnet\": true|false, (boolean) if the server is using testnet or not\n"
- " \"keypoololdest\": xxxxxx, (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
- " \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
- " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc\n"
- " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
- " \"errors\": \"...\" (string) any error messages\n"
- "}\n"
- "\nExamples:\n"
- + HelpExampleCli("getinfo", "")
- + HelpExampleRpc("getinfo", "")
- );
-
- proxyType proxy;
- GetProxy(NET_IPV4, proxy);
-
- Object obj;
- obj.push_back(Pair("version", (int)CLIENT_VERSION));
- obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION));
- if (pwalletMain) {
- obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
- obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
- }
- obj.push_back(Pair("blocks", (int)chainActive.Height()));
- obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset()));
- obj.push_back(Pair("connections", (int)vNodes.size()));
- obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
- obj.push_back(Pair("difficulty", (double)GetDifficulty()));
- obj.push_back(Pair("testnet", TestNet()));
- if (pwalletMain) {
- obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
- obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
- }
- obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
- if (pwalletMain && pwalletMain->IsCrypted())
- obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime));
- obj.push_back(Pair("errors", GetWarnings("statusbar")));
- return obj;
-}
-
-
-
Value getnewaddress(const Array& params, bool fHelp)
{
if (fHelp || params.size() > 1)
@@ -401,8 +334,7 @@ Value sendtoaddress(const Array& params, bool fHelp)
if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
wtx.mapValue["to"] = params[3].get_str();
- if (pwalletMain->IsLocked())
- throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
+ EnsureWalletIsUnlocked();
string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx);
if (strError != "")
@@ -509,59 +441,6 @@ Value signmessage(const Array& params, bool fHelp)
return EncodeBase64(&vchSig[0], vchSig.size());
}
-Value verifymessage(const Array& params, bool fHelp)
-{
- if (fHelp || params.size() != 3)
- throw runtime_error(
- "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n"
- "\nVerify a signed message\n"
- "\nArguments:\n"
- "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n"
- "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n"
- "3. \"message\" (string, required) The message that was signed.\n"
- "\nResult:\n"
- "true|false (boolean) If the signature is verified or not.\n"
- "\nExamples:\n"
- "\nUnlock the wallet for 30 seconds\n"
- + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
- "\nCreate the signature\n"
- + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
- "\nVerify the signature\n"
- + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
- "\nAs json rpc\n"
- + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"")
- );
-
- string strAddress = params[0].get_str();
- string strSign = params[1].get_str();
- string strMessage = params[2].get_str();
-
- CBitcoinAddress addr(strAddress);
- if (!addr.IsValid())
- throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
-
- CKeyID keyID;
- if (!addr.GetKeyID(keyID))
- throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
-
- bool fInvalid = false;
- vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);
-
- if (fInvalid)
- throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
-
- CHashWriter ss(SER_GETHASH, 0);
- ss << strMessageMagic;
- ss << strMessage;
-
- CPubKey pubkey;
- if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
- return false;
-
- return (pubkey.GetID() == keyID);
-}
-
-
Value getreceivedbyaddress(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
@@ -984,61 +863,8 @@ Value sendmany(const Array& params, bool fHelp)
return wtx.GetHash().GetHex();
}
-//
-// Used by addmultisigaddress / createmultisig:
-//
-static CScript _createmultisig(const Array& params)
-{
- int nRequired = params[0].get_int();
- const Array& keys = params[1].get_array();
-
- // Gather public keys
- if (nRequired < 1)
- throw runtime_error("a multisignature address must require at least one key to redeem");
- if ((int)keys.size() < nRequired)
- throw runtime_error(
- strprintf("not enough keys supplied "
- "(got %"PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired));
- std::vector<CPubKey> pubkeys;
- pubkeys.resize(keys.size());
- for (unsigned int i = 0; i < keys.size(); i++)
- {
- const std::string& ks = keys[i].get_str();
-
- // Case 1: Bitcoin address and we have full public key:
- CBitcoinAddress address(ks);
- if (pwalletMain && address.IsValid())
- {
- CKeyID keyID;
- if (!address.GetKeyID(keyID))
- throw runtime_error(
- strprintf("%s does not refer to a key",ks.c_str()));
- CPubKey vchPubKey;
- if (!pwalletMain->GetPubKey(keyID, vchPubKey))
- throw runtime_error(
- strprintf("no full public key for address %s",ks.c_str()));
- if (!vchPubKey.IsFullyValid())
- throw runtime_error(" Invalid public key: "+ks);
- pubkeys[i] = vchPubKey;
- }
-
- // Case 2: hex public key
- else if (IsHex(ks))
- {
- CPubKey vchPubKey(ParseHex(ks));
- if (!vchPubKey.IsFullyValid())
- throw runtime_error(" Invalid public key: "+ks);
- pubkeys[i] = vchPubKey;
- }
- else
- {
- throw runtime_error(" Invalid public key: "+ks);
- }
- }
- CScript result;
- result.SetMultisig(nRequired, pubkeys);
- return result;
-}
+// Defined in rpcmisc.cpp
+extern CScript _createmultisig(const Array& params);
Value addmultisigaddress(const Array& params, bool fHelp)
{
@@ -1083,49 +909,6 @@ Value addmultisigaddress(const Array& params, bool fHelp)
return CBitcoinAddress(innerID).ToString();
}
-Value createmultisig(const Array& params, bool fHelp)
-{
- if (fHelp || params.size() < 2 || params.size() > 2)
- {
- string msg = "createmultisig nrequired [\"key\",...]\n"
- "\nCreates a multi-signature address with n signature of m keys required.\n"
- "It returns a json object with the address and redeemScript.\n"
-
- "\nArguments:\n"
- "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n"
- "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
- " [\n"
- " \"key\" (string) bitcoin address or hex-encoded public key\n"
- " ,...\n"
- " ]\n"
-
- "\nResult:\n"
- "{\n"
- " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n"
- " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n"
- "}\n"
-
- "\nExamples:\n"
- "\nCreate a multisig address from 2 addresses\n"
- + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
- "\nAs a json rpc call\n"
- + HelpExampleRpc("icreatemultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
- ;
- throw runtime_error(msg);
- }
-
- // Construct using pay-to-script-hash:
- CScript inner = _createmultisig(params);
- CScriptID innerID = inner.GetID();
- CBitcoinAddress address(innerID);
-
- Object result;
- result.push_back(Pair("address", address.ToString()));
- result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end())));
-
- return result;
-}
-
struct tallyitem
{
@@ -1733,15 +1516,15 @@ Value keypoolrefill(const Array& params, bool fHelp)
+ HelpExampleRpc("keypoolrefill", "")
);
- unsigned int kpSize = max(GetArg("-keypool", 100), (int64_t) 0);
+ // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
+ unsigned int kpSize = 0;
if (params.size() > 0) {
if (params[0].get_int() < 0)
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size");
- kpSize = (unsigned int) params[0].get_int();
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
+ kpSize = (unsigned int)params[0].get_int();
}
EnsureWalletIsUnlocked();
-
pwalletMain->TopUpKeyPool(kpSize);
if (pwalletMain->GetKeyPoolSize() < kpSize)
@@ -1939,87 +1722,6 @@ Value encryptwallet(const Array& params, bool fHelp)
return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
}
-class DescribeAddressVisitor : public boost::static_visitor<Object>
-{
-public:
- Object operator()(const CNoDestination &dest) const { return Object(); }
-
- Object operator()(const CKeyID &keyID) const {
- Object obj;
- CPubKey vchPubKey;
- pwalletMain->GetPubKey(keyID, vchPubKey);
- obj.push_back(Pair("isscript", false));
- obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
- obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
- return obj;
- }
-
- Object operator()(const CScriptID &scriptID) const {
- Object obj;
- obj.push_back(Pair("isscript", true));
- CScript subscript;
- pwalletMain->GetCScript(scriptID, subscript);
- std::vector<CTxDestination> addresses;
- txnouttype whichType;
- int nRequired;
- ExtractDestinations(subscript, whichType, addresses, nRequired);
- obj.push_back(Pair("script", GetTxnOutputType(whichType)));
- obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
- Array a;
- BOOST_FOREACH(const CTxDestination& addr, addresses)
- a.push_back(CBitcoinAddress(addr).ToString());
- obj.push_back(Pair("addresses", a));
- if (whichType == TX_MULTISIG)
- obj.push_back(Pair("sigsrequired", nRequired));
- return obj;
- }
-};
-
-Value validateaddress(const Array& params, bool fHelp)
-{
- if (fHelp || params.size() != 1)
- throw runtime_error(
- "validateaddress \"bitcoinaddress\"\n"
- "\nReturn information about the given bitcoin address.\n"
- "\nArguments:\n"
- "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n"
- "\nResult:\n"
- "{\n"
- " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n"
- " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n"
- " \"ismine\" : true|false, (boolean) If the address is yours or not\n"
- " \"isscript\" : true|false, (boolean) If the key is a script\n"
- " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n"
- " \"iscompressed\" : true|false, (boolean) If the address is compressed\n"
- " \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\n"
- "}\n"
- "\nExamples:\n"
- + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
- + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"")
- );
-
- CBitcoinAddress address(params[0].get_str());
- bool isValid = address.IsValid();
-
- Object ret;
- ret.push_back(Pair("isvalid", isValid));
- if (isValid)
- {
- CTxDestination dest = address.Get();
- string currentAddress = address.ToString();
- ret.push_back(Pair("address", currentAddress));
- bool fMine = pwalletMain ? IsMine(*pwalletMain, dest) : false;
- ret.push_back(Pair("ismine", fMine));
- if (fMine) {
- Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest);
- ret.insert(ret.end(), detail.begin(), detail.end());
- }
- if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
- ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
- }
- return ret;
-}
-
Value lockunspent(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
@@ -2143,3 +1845,28 @@ Value listlockunspent(const Array& params, bool fHelp)
return ret;
}
+Value settxfee(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() < 1 || params.size() > 1)
+ throw runtime_error(
+ "settxfee amount\n"
+ "\nSet the transaction fee. 'amount' is a real and is rounded to the nearest 0.00000001\n"
+ "\nArguments:\n"
+ "1. amount (numeric, required) The transaction fee in btc rounded to the nearest 0.00000001\n"
+ "\nResult\n"
+ "true|false (boolean) Returns true if successful\n"
+ "\nExamples:\n"
+ + HelpExampleCli("settxfee", "0.00001")
+ + HelpExampleRpc("settxfee", "0.00001")
+ );
+
+ // Amount
+ int64_t nAmount = 0;
+ if (params[0].get_real() != 0.0)
+ nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts
+
+ nTransactionFee = nAmount;
+ return true;
+}
+
+
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index f0fb84bc54..fbca09b4dc 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -21,6 +21,7 @@
// Tests this internal-to-main.cpp method:
extern bool AddOrphanTx(const CTransaction& tx);
extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
+extern void Misbehaving(NodeId nodeid, int howmuch);
extern std::map<uint256, CTransaction> mapOrphanTransactions;
extern std::map<uint256, std::set<uint256> > mapOrphanTransactionsByPrev;
@@ -38,16 +39,21 @@ BOOST_AUTO_TEST_CASE(DoS_banning)
CNode::ClearBanned();
CAddress addr1(ip(0xa0b0c001));
CNode dummyNode1(INVALID_SOCKET, addr1, "", true);
- dummyNode1.Misbehaving(100); // Should get banned
+ dummyNode1.nVersion = 1;
+ Misbehaving(dummyNode1.GetId(), 100); // Should get banned
+ SendMessages(&dummyNode1, false);
BOOST_CHECK(CNode::IsBanned(addr1));
BOOST_CHECK(!CNode::IsBanned(ip(0xa0b0c001|0x0000ff00))); // Different IP, not banned
CAddress addr2(ip(0xa0b0c002));
CNode dummyNode2(INVALID_SOCKET, addr2, "", true);
- dummyNode2.Misbehaving(50);
+ dummyNode2.nVersion = 1;
+ Misbehaving(dummyNode2.GetId(), 50);
+ SendMessages(&dummyNode2, false);
BOOST_CHECK(!CNode::IsBanned(addr2)); // 2 not banned yet...
BOOST_CHECK(CNode::IsBanned(addr1)); // ... but 1 still should be
- dummyNode2.Misbehaving(50);
+ Misbehaving(dummyNode2.GetId(), 50);
+ SendMessages(&dummyNode2, false);
BOOST_CHECK(CNode::IsBanned(addr2));
}
@@ -57,11 +63,15 @@ BOOST_AUTO_TEST_CASE(DoS_banscore)
mapArgs["-banscore"] = "111"; // because 11 is my favorite number
CAddress addr1(ip(0xa0b0c001));
CNode dummyNode1(INVALID_SOCKET, addr1, "", true);
- dummyNode1.Misbehaving(100);
+ dummyNode1.nVersion = 1;
+ Misbehaving(dummyNode1.GetId(), 100);
+ SendMessages(&dummyNode1, false);
BOOST_CHECK(!CNode::IsBanned(addr1));
- dummyNode1.Misbehaving(10);
+ Misbehaving(dummyNode1.GetId(), 10);
+ SendMessages(&dummyNode1, false);
BOOST_CHECK(!CNode::IsBanned(addr1));
- dummyNode1.Misbehaving(1);
+ Misbehaving(dummyNode1.GetId(), 1);
+ SendMessages(&dummyNode1, false);
BOOST_CHECK(CNode::IsBanned(addr1));
mapArgs.erase("-banscore");
}
@@ -74,8 +84,10 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
CAddress addr(ip(0xa0b0c001));
CNode dummyNode(INVALID_SOCKET, addr, "", true);
+ dummyNode.nVersion = 1;
- dummyNode.Misbehaving(100);
+ Misbehaving(dummyNode.GetId(), 100);
+ SendMessages(&dummyNode, false);
BOOST_CHECK(CNode::IsBanned(addr));
SetMockTime(nStartTime+60*60);
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 39f2c6a385..ccc8da1690 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -21,8 +21,13 @@ BUILT_SOURCES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
# test_bitcoin binary #
test_bitcoin_CPPFLAGS = $(AM_CPPFLAGS) $(TESTDEFS)
test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBLEVELDB) $(LIBMEMENV) \
- $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(BDB_LIBS)
-test_bitcoin_SOURCES = accounting_tests.cpp alert_tests.cpp \
+ $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB)
+if ENABLE_WALLET
+test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
+endif
+test_bitcoin_LDADD += $(BDB_LIBS)
+
+test_bitcoin_SOURCES = alert_tests.cpp \
allocator_tests.cpp base32_tests.cpp base58_tests.cpp base64_tests.cpp \
bignum_tests.cpp bloom_tests.cpp canonical_tests.cpp checkblock_tests.cpp \
Checkpoints_tests.cpp compress_tests.cpp DoS_tests.cpp getarg_tests.cpp \
@@ -30,7 +35,11 @@ test_bitcoin_SOURCES = accounting_tests.cpp alert_tests.cpp \
netbase_tests.cpp pmt_tests.cpp rpc_tests.cpp script_P2SH_tests.cpp \
script_tests.cpp serialize_tests.cpp sigopcount_tests.cpp test_bitcoin.cpp \
transaction_tests.cpp uint160_tests.cpp uint256_tests.cpp util_tests.cpp \
- wallet_tests.cpp sighash_tests.cpp $(JSON_TEST_FILES) $(RAW_TEST_FILES)
+ sighash_tests.cpp $(JSON_TEST_FILES) $(RAW_TEST_FILES)
+
+if ENABLE_WALLET
+test_bitcoin_SOURCES += accounting_tests.cpp wallet_tests.cpp rpc_wallet_tests.cpp
+endif
nodist_test_bitcoin_SOURCES = $(BUILT_SOURCES)
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index a26f4a87db..e386f81fe6 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -65,5 +65,10 @@
["Same as the transactions in valid with one input SIGHASH_ALL and one SIGHASH_ANYONECANPAY, but we set the _ANYONECANPAY sequence number, invalidating the SIGHASH_ALL signature"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
- "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", true]
+ "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", true],
+
+["Incorrect signature order"],
+["Note the input is just required to make the tester happy"],
+[[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]],
+"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe000048304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f401483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", true]
]
diff --git a/src/test/data/tx_valid.json b/src/test/data/tx_valid.json
index 63e7074a32..c33a7a035a 100644
--- a/src/test/data/tx_valid.json
+++ b/src/test/data/tx_valid.json
@@ -87,5 +87,10 @@
["ddc454a1c0c35c188c98976b17670f69e586d9c0f3593ea879928332f0a069e7, which spends an input that pushes using a PUSHDATA1 that is negative when read as signed"],
[[["c5510a5dd97a25f43175af1fe649b707b1df8e1a41489bac33a23087027a2f48", 0, "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG"]],
- "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", true]
+ "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", true],
+
+["Correct signature order"],
+["Note the input is just required to make the tester happy"],
+[[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]],
+"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", true]
]
diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
index 46c9ae021d..8e3091d555 100644
--- a/src/test/miner_tests.cpp
+++ b/src/test/miner_tests.cpp
@@ -4,11 +4,9 @@
#include "miner.h"
#include "uint256.h"
#include "util.h"
-#include "wallet.h"
#include <boost/test/unit_test.hpp>
-extern CWallet* pwalletMain;
extern void SHA256Transform(void* pstate, void* pinput, const void* pinit);
BOOST_AUTO_TEST_SUITE(miner_tests)
@@ -51,7 +49,7 @@ struct {
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
{
- CReserveKey reservekey(pwalletMain);
+ CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
CBlockTemplate *pblocktemplate;
CTransaction tx;
CScript script;
@@ -60,7 +58,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
LOCK(cs_main);
// Simple block creation, nothing special yet:
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
// We can't make transactions until we have inputs
// Therefore, load 100 blocks :)
@@ -86,7 +84,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
delete pblocktemplate;
// Just to make sure we can still make simple blocks
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
delete pblocktemplate;
// block sigops > limit: 1000 CHECKMULTISIG + 1
@@ -104,7 +102,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
tx.vin[0].prevout.hash = hash;
}
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
delete pblocktemplate;
mempool.clear();
@@ -124,14 +122,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
tx.vin[0].prevout.hash = hash;
}
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
delete pblocktemplate;
mempool.clear();
// orphan in mempool
hash = tx.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
delete pblocktemplate;
mempool.clear();
@@ -149,7 +147,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue = 5900000000LL;
hash = tx.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
delete pblocktemplate;
mempool.clear();
@@ -160,7 +158,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue = 0;
hash = tx.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
delete pblocktemplate;
mempool.clear();
@@ -178,7 +176,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].nValue -= 1000000;
hash = tx.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
delete pblocktemplate;
mempool.clear();
@@ -192,17 +190,17 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
tx.vout[0].scriptPubKey = CScript() << OP_2;
hash = tx.GetHash();
mempool.addUnchecked(hash, CTxMemPoolEntry(tx, 11, GetTime(), 111.0, 11));
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
delete pblocktemplate;
mempool.clear();
// subsidy changing
int nHeight = chainActive.Height();
chainActive.Tip()->nHeight = 209999;
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
delete pblocktemplate;
chainActive.Tip()->nHeight = 210000;
- BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
+ BOOST_CHECK(pblocktemplate = CreateNewBlock(scriptPubKey));
delete pblocktemplate;
chainActive.Tip()->nHeight = nHeight;
diff --git a/src/test/rpc_tests.cpp b/src/test/rpc_tests.cpp
index 76580bae43..29195545da 100644
--- a/src/test/rpc_tests.cpp
+++ b/src/test/rpc_tests.cpp
@@ -9,9 +9,7 @@
using namespace std;
using namespace json_spirit;
-BOOST_AUTO_TEST_SUITE(rpc_tests)
-
-static Array
+Array
createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL)
{
Array result;
@@ -23,44 +21,7 @@ createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL)
return result;
}
-BOOST_AUTO_TEST_CASE(rpc_addmultisig)
-{
- rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;
-
- // old, 65-byte-long:
- const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
- // new, compressed:
- const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
-
- Value v;
- CBitcoinAddress address;
- BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
- address.SetString(v.get_str());
- BOOST_CHECK(address.IsValid() && address.IsScript());
-
- BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
- address.SetString(v.get_str());
- BOOST_CHECK(address.IsValid() && address.IsScript());
-
- BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
- address.SetString(v.get_str());
- BOOST_CHECK(address.IsValid() && address.IsScript());
-
- BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
- BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
- BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error);
-
- BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error);
- BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error);
-
- string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing
- BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error);
-
- string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing
- BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
-}
-
-static Value CallRPC(string args)
+Value CallRPC(string args)
{
vector<string> vArgs;
boost::split(vArgs, args, boost::is_any_of(" \t"));
@@ -79,34 +40,8 @@ static Value CallRPC(string args)
}
}
-BOOST_AUTO_TEST_CASE(rpc_wallet)
-{
- // Test RPC calls for various wallet statistics
- Value r;
-
- BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
- BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
- BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
- BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
- BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error);
- BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []"));
- BOOST_CHECK(r.get_array().empty());
-
- BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress"));
- BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0"));
- BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error);
- BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error);
- BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true"));
- BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error);
-
- BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount"));
- BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0"));
- BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error);
- BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error);
- BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true"));
- BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error);
-}
+BOOST_AUTO_TEST_SUITE(rpc_tests)
BOOST_AUTO_TEST_CASE(rpc_rawparams)
{
diff --git a/src/test/rpc_wallet_tests.cpp b/src/test/rpc_wallet_tests.cpp
new file mode 100644
index 0000000000..2cf0fb350b
--- /dev/null
+++ b/src/test/rpc_wallet_tests.cpp
@@ -0,0 +1,82 @@
+#include "rpcserver.h"
+#include "rpcclient.h"
+
+#include "base58.h"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/test/unit_test.hpp>
+
+using namespace std;
+using namespace json_spirit;
+
+extern Array createArgs(int nRequired, const char* address1=NULL, const char* address2=NULL);
+extern Value CallRPC(string args);
+
+BOOST_AUTO_TEST_SUITE(rpc_wallet_tests)
+
+BOOST_AUTO_TEST_CASE(rpc_addmultisig)
+{
+ rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;
+
+ // old, 65-byte-long:
+ const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
+ // new, compressed:
+ const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
+
+ Value v;
+ CBitcoinAddress address;
+ BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
+ address.SetString(v.get_str());
+ BOOST_CHECK(address.IsValid() && address.IsScript());
+
+ BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
+ address.SetString(v.get_str());
+ BOOST_CHECK(address.IsValid() && address.IsScript());
+
+ BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
+ address.SetString(v.get_str());
+ BOOST_CHECK(address.IsValid() && address.IsScript());
+
+ BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
+ BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
+ BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error);
+
+ BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error);
+ BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error);
+
+ string short1(address1Hex, address1Hex+sizeof(address1Hex)-2); // last byte missing
+ BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error);
+
+ string short2(address1Hex+1, address1Hex+sizeof(address1Hex)); // first byte missing
+ BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
+}
+
+BOOST_AUTO_TEST_CASE(rpc_wallet)
+{
+ // Test RPC calls for various wallet statistics
+ Value r;
+
+ BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
+ BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error);
+ BOOST_CHECK_NO_THROW(r=CallRPC("listunspent 0 1 []"));
+ BOOST_CHECK(r.get_array().empty());
+
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress"));
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error);
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error);
+
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount"));
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error);
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index afcdd118bc..415f957811 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -61,9 +61,16 @@ BOOST_AUTO_TEST_CASE(compactsize)
static bool isCanonicalException(const std::ios_base::failure& ex)
{
- return std::string("non-canonical ReadCompactSize()") == ex.what();
+ std::ios_base::failure expectedException("non-canonical ReadCompactSize()");
+
+ // The string returned by what() can be different for different platforms.
+ // Instead of directly comparing the ex.what() with an expected string,
+ // create an instance of exception to see if ex.what() matches
+ // the expected explanatory string returned by the exception instance.
+ return strcmp(expectedException.what(), ex.what()) == 0;
}
+
BOOST_AUTO_TEST_CASE(noncanonical)
{
// Write some non-canonical CompactSize encodings, and
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 443e7735d7..667bdfb62e 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -2,12 +2,14 @@
-#include "db.h"
#include "main.h"
#include "txdb.h"
#include "ui_interface.h"
#include "util.h"
+#ifdef ENABLE_WALLET
+#include "db.h"
#include "wallet.h"
+#endif
#include <boost/filesystem.hpp>
#include <boost/test/unit_test.hpp>
@@ -26,7 +28,9 @@ struct TestingSetup {
TestingSetup() {
fPrintToDebugger = true; // don't want to write to debug.log file
noui_connect();
+#ifdef ENABLE_WALLET
bitdb.MakeMock();
+#endif
pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000)));
boost::filesystem::create_directories(pathTemp);
mapArgs["-datadir"] = pathTemp.string();
@@ -34,24 +38,32 @@ struct TestingSetup {
pcoinsdbview = new CCoinsViewDB(1 << 23, true);
pcoinsTip = new CCoinsViewCache(*pcoinsdbview);
InitBlockIndex();
+#ifdef ENABLE_WALLET
bool fFirstRun;
pwalletMain = new CWallet("wallet.dat");
pwalletMain->LoadWallet(fFirstRun);
RegisterWallet(pwalletMain);
+#endif
nScriptCheckThreads = 3;
for (int i=0; i < nScriptCheckThreads-1; i++)
threadGroup.create_thread(&ThreadScriptCheck);
+ RegisterNodeSignals(GetNodeSignals());
}
~TestingSetup()
{
threadGroup.interrupt_all();
threadGroup.join_all();
+ UnregisterNodeSignals(GetNodeSignals());
+#ifdef ENABLE_WALLET
delete pwalletMain;
pwalletMain = NULL;
+#endif
delete pcoinsTip;
delete pcoinsdbview;
delete pblocktree;
+#ifdef ENABLE_WALLET
bitdb.Flush(true);
+#endif
boost::filesystem::remove_all(pathTemp);
}
};
diff --git a/src/ui_interface.h b/src/ui_interface.h
index 2378d5dfbb..a14ed67814 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -72,12 +72,6 @@ public:
/** Show message box. */
boost::signals2::signal<bool (const std::string& message, const std::string& caption, unsigned int style), boost::signals2::last_value<bool> > ThreadSafeMessageBox;
- /** Ask the user whether they want to pay a fee or not. */
- boost::signals2::signal<bool (int64_t nFeeRequired), boost::signals2::last_value<bool> > ThreadSafeAskFee;
-
- /** Handle a URL passed at the command line. */
- boost::signals2::signal<void (const std::string& strURI)> ThreadSafeHandleURI;
-
/** Progress message during initialization. */
boost::signals2::signal<void (const std::string &message)> InitMessage;
diff --git a/src/util.cpp b/src/util.cpp
index a8c591cc7a..bedf59767b 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -242,17 +242,23 @@ int LogPrint(const char* category, const char* pszFormat, ...)
if (!fDebug)
return 0;
- const vector<string>& categories = mapMultiArgs["-debug"];
- bool allCategories = count(categories.begin(), categories.end(), string(""));
-
- // Only look for categories, if not -debug/-debug=1 was passed,
- // as that implies every category should be logged.
- if (!allCategories)
+ // Give each thread quick access to -debug settings.
+ // This helps prevent issues debugging global destructors,
+ // where mapMultiArgs might be deleted before another
+ // global destructor calls LogPrint()
+ static boost::thread_specific_ptr<set<string> > ptrCategory;
+ if (ptrCategory.get() == NULL)
{
- // Category was not found (not supplied via -debug=<category>)
- if (find(categories.begin(), categories.end(), string(category)) == categories.end())
- return 0;
+ const vector<string>& categories = mapMultiArgs["-debug"];
+ ptrCategory.reset(new set<string>(categories.begin(), categories.end()));
+ // thread_specific_ptr automatically deletes the set when the thread ends.
}
+ const set<string>& setCategories = *ptrCategory.get();
+
+ // if not debugging everything and not debugging specific category, LogPrint does nothing.
+ if (setCategories.count(string("")) == 0 &&
+ setCategories.count(string(category)) == 0)
+ return 0;
}
int ret = 0; // Returns total number of characters written
@@ -299,27 +305,24 @@ int LogPrint(const char* category, const char* pszFormat, ...)
#ifdef WIN32
if (fPrintToDebugger)
{
- static CCriticalSection cs_OutputDebugStringF;
-
// accumulate and output a line at a time
- {
- LOCK(cs_OutputDebugStringF);
- static std::string buffer;
+ static std::string buffer;
- va_list arg_ptr;
- va_start(arg_ptr, pszFormat);
- buffer += vstrprintf(pszFormat, arg_ptr);
- va_end(arg_ptr);
+ boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
- int line_start = 0, line_end;
- while((line_end = buffer.find('\n', line_start)) != -1)
- {
- OutputDebugStringA(buffer.substr(line_start, line_end - line_start).c_str());
- line_start = line_end + 1;
- ret += line_end-line_start;
- }
- buffer.erase(0, line_start);
+ va_list arg_ptr;
+ va_start(arg_ptr, pszFormat);
+ buffer += vstrprintf(pszFormat, arg_ptr);
+ va_end(arg_ptr);
+
+ int line_start = 0, line_end;
+ while((line_end = buffer.find('\n', line_start)) != -1)
+ {
+ OutputDebugStringA(buffer.substr(line_start, line_end - line_start).c_str());
+ line_start = line_end + 1;
+ ret += line_end-line_start;
}
+ buffer.erase(0, line_start);
}
#endif
return ret;
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 241e937b1b..76a83082ae 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -16,6 +16,8 @@
using namespace std;
+// Settings
+int64_t nTransactionFee = 0;
//////////////////////////////////////////////////////////////////////////////
//
@@ -1434,7 +1436,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
-string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, bool fAskFee)
+string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew)
{
CReserveKey reservekey(this);
int64_t nFeeRequired;
@@ -1454,9 +1456,6 @@ string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNe
return strError;
}
- if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired))
- return "ABORTED";
-
if (!CommitTransaction(wtxNew, reservekey))
return _("Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
@@ -1465,7 +1464,7 @@ string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNe
-string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew, bool fAskFee)
+string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew)
{
// Check amount
if (nValue <= 0)
@@ -1477,7 +1476,7 @@ string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nV
CScript scriptPubKey;
scriptPubKey.SetDestination(address);
- return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
+ return SendMoney(scriptPubKey, nValue, wtxNew);
}
diff --git a/src/wallet.h b/src/wallet.h
index 90209122fd..99f6293b1e 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -23,6 +23,9 @@
#include <utility>
#include <vector>
+// Settings
+extern int64_t nTransactionFee;
+
class CAccountingEntry;
class CCoinControl;
class COutput;
@@ -217,8 +220,8 @@ public:
bool CreateTransaction(CScript scriptPubKey, int64_t nValue,
CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
- std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false);
- std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false);
+ std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew);
+ std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew);
bool NewKeyPool();
bool TopUpKeyPool(unsigned int kpSize = 0);