aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--.tx/config2
-rw-r--r--Makefile.am21
-rw-r--r--build-aux/m4/bitcoin_qt.m42
-rw-r--r--configure.ac17
-rw-r--r--contrib/gitian-downloader/sipa-key.pgpbin109468 -> 137597 bytes
-rw-r--r--contrib/init/README.md1
-rw-r--r--contrib/init/org.bitcoin.bitcoind.plist15
-rw-r--r--contrib/verify-commits/allow-revsig-commits2
-rwxr-xr-xcontrib/verify-commits/gpg.sh22
-rwxr-xr-xcontrib/verify-commits/pre-push-hook.sh2
-rw-r--r--contrib/verify-commits/trusted-keys1
-rwxr-xr-xcontrib/verify-commits/verify-commits.sh12
-rwxr-xr-xdepends/config.guess4
-rw-r--r--doc/README.md2
-rw-r--r--doc/bips.md1
-rw-r--r--doc/build-unix.md44
-rw-r--r--doc/build-windows.md40
-rw-r--r--doc/developer-notes.md33
-rw-r--r--doc/init.md23
-rw-r--r--doc/release-notes.md27
-rw-r--r--doc/translation_strings_policy.md2
-rwxr-xr-xqa/pull-tester/rpc-tests.py3
-rwxr-xr-xqa/rpc-tests/bip65-cltv-p2p.py23
-rwxr-xr-xqa/rpc-tests/blockchain.py2
-rwxr-xr-xqa/rpc-tests/maxuploadtarget.py248
-rw-r--r--src/Makefile.am16
-rw-r--r--src/bench/bench.cpp2
-rw-r--r--src/bench/bench.h23
-rw-r--r--src/bitcoin-cli.cpp2
-rw-r--r--src/bitcoin-tx.cpp2
-rw-r--r--src/bitcoind.cpp2
-rw-r--r--src/dbwrapper.h4
-rw-r--r--src/init.cpp62
-rw-r--r--src/leveldb/util/env_win.cc236
-rw-r--r--src/main.cpp10
-rw-r--r--src/main.h3
-rw-r--r--src/memusage.h2
-rw-r--r--src/miner.h2
-rw-r--r--src/net.cpp94
-rw-r--r--src/net.h27
-rw-r--r--src/policy/policy.h6
-rw-r--r--src/qt/addresstablemodel.cpp2
-rw-r--r--src/qt/bitcoinstrings.cpp42
-rw-r--r--src/qt/coincontroldialog.cpp2
-rw-r--r--src/qt/guiutil.cpp4
-rw-r--r--src/qt/guiutil.h4
-rw-r--r--src/qt/locale/bitcoin_en.ts179
-rw-r--r--src/qt/rpcconsole.cpp12
-rw-r--r--src/qt/rpcconsole.h1
-rw-r--r--src/qt/sendcoinsentry.cpp2
-rw-r--r--src/qt/signverifymessagedialog.cpp4
-rw-r--r--src/rpcblockchain.cpp11
-rw-r--r--src/rpcmining.cpp4
-rw-r--r--src/rpcnet.cpp13
-rw-r--r--src/rpcserver.cpp2
-rw-r--r--src/test/alert_tests.cpp4
-rw-r--r--src/test/data/tx_invalid.json10
-rw-r--r--src/test/test_bitcoin.cpp1
-rw-r--r--src/txdb.cpp2
-rw-r--r--src/txmempool.cpp21
-rw-r--r--src/txmempool.h5
-rw-r--r--src/util.cpp11
-rw-r--r--src/util.h3
-rw-r--r--src/utiltime.cpp8
-rw-r--r--src/utiltime.h1
-rw-r--r--src/wallet/db.cpp2
-rw-r--r--src/wallet/db.h2
-rw-r--r--src/wallet/test/wallet_tests.cpp113
-rw-r--r--src/wallet/wallet.cpp16
-rw-r--r--src/wallet/wallet.h29
-rw-r--r--src/wallet/walletdb.cpp7
-rw-r--r--src/zmq/zmqnotificationinterface.cpp11
-rw-r--r--src/zmq/zmqnotificationinterface.h3
74 files changed, 1095 insertions, 485 deletions
diff --git a/.gitignore b/.gitignore
index a8035731d1..a8722aa593 100644
--- a/.gitignore
+++ b/.gitignore
@@ -85,15 +85,13 @@ src/test/buildenv.py
# Resources cpp
qrc_*.cpp
-# Qt creator
-*.pro.user
-
# Mac specific
.DS_Store
build
#lcov
*.gcno
+*.gcda
/*.info
test_bitcoin.coverage/
total.coverage/
@@ -107,6 +105,9 @@ qa/pull-tester/run-bitcoind-for-test.sh
qa/pull-tester/tests_config.py
qa/pull-tester/cache/*
qa/pull-tester/test.*/*
+qa/tmp
+cache/
+share/BitcoindComparisonTool.jar
!src/leveldb*/Makefile
diff --git a/.tx/config b/.tx/config
index 6c534f06e4..d6cc3aab88 100644
--- a/.tx/config
+++ b/.tx/config
@@ -1,7 +1,7 @@
[main]
host = https://www.transifex.com
-[bitcoin.qt-translation-011x]
+[bitcoin.qt-translation-012x]
file_filter = src/qt/locale/bitcoin_<lang>.ts
source_file = src/qt/locale/bitcoin_en.ts
source_lang = en
diff --git a/Makefile.am b/Makefile.am
index 8a7140398f..303ad3b06f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,7 +39,7 @@ OSX_PACKAGING = $(OSX_DEPLOY_SCRIPT) $(OSX_FANCY_PLIST) $(OSX_INSTALLER_ICONS) $
COVERAGE_INFO = baseline_filtered_combined.info baseline.info block_test.info \
leveldb_baseline.info test_bitcoin_filtered.info total_coverage.info \
- baseline_filtered.info block_test_filtered.info \
+ baseline_filtered.info block_test_filtered.info rpc_test.info rpc_test_filtered.info \
leveldb_baseline_filtered.info test_bitcoin_coverage.info test_bitcoin.info
dist-hook:
@@ -170,7 +170,7 @@ test_bitcoin_filtered.info: test_bitcoin.info
block_test.info: test_bitcoin_filtered.info
$(MKDIR_P) qa/tmp
- -@TIMEOUT=15 qa/pull-tester/run-bitcoind-for-test.sh $(JAVA) -jar $(JAVA_COMPARISON_TOOL) qa/tmp/compTool 0
+ -@TIMEOUT=15 qa/pull-tester/run-bitcoind-for-test.sh $(JAVA) -jar $(JAVA_COMPARISON_TOOL) qa/tmp/compTool $(COMPARISON_TOOL_REORG_TESTS)
$(LCOV) -c -d $(abs_builddir)/src --t BitcoinJBlockTest -o $@
$(LCOV) -z -d $(abs_builddir)/src
$(LCOV) -z -d $(abs_builddir)/src/leveldb
@@ -178,11 +178,20 @@ block_test.info: test_bitcoin_filtered.info
block_test_filtered.info: block_test.info
$(LCOV) -r $< "/usr/include/*" -o $@
+rpc_test.info: test_bitcoin_filtered.info
+ -@TIMEOUT=15 python qa/pull-tester/rpc-tests.py $(EXTENDED_RPC_TESTS)
+ $(LCOV) -c -d $(abs_builddir)/src --t rpc-tests -o $@
+ $(LCOV) -z -d $(abs_builddir)/src
+ $(LCOV) -z -d $(abs_builddir)/src/leveldb
+
+rpc_test_filtered.info: rpc_test.info
+ $(LCOV) -r $< "/usr/include/*" -o $@
+
test_bitcoin_coverage.info: baseline_filtered_combined.info test_bitcoin_filtered.info
$(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoin_filtered.info -o $@
-total_coverage.info: baseline_filtered_combined.info test_bitcoin_filtered.info block_test_filtered.info
- $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoin_filtered.info -a block_test_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt
+total_coverage.info: baseline_filtered_combined.info test_bitcoin_filtered.info block_test_filtered.info rpc_test_filtered.info
+ $(LCOV) -a baseline_filtered.info -a leveldb_baseline_filtered.info -a test_bitcoin_filtered.info -a block_test_filtered.info -a rpc_test_filtered.info -o $@ | $(GREP) "\%" | $(AWK) '{ print substr($$3,2,50) "/" $$5 }' > coverage_percent.txt
test_bitcoin.coverage/.dirstamp: test_bitcoin_coverage.info
$(GENHTML) -s $< -o $(@D)
@@ -204,11 +213,11 @@ endif
dist_noinst_SCRIPTS = autogen.sh
-EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/pull-tester/tests_config.py qa/rpc-tests $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING)
+EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/rpc-tests $(DIST_DOCS) $(WINDOWS_PACKAGING) $(OSX_PACKAGING)
CLEANFILES = $(OSX_DMG) $(BITCOIN_WIN_INSTALLER)
.INTERMEDIATE: $(COVERAGE_INFO)
clean-local:
- rm -rf test_bitcoin.coverage/ total.coverage/ $(OSX_APP)
+ rm -rf coverage_percent.txt test_bitcoin.coverage/ total.coverage/ qa/tmp/ cache/ $(OSX_APP)
diff --git a/build-aux/m4/bitcoin_qt.m4 b/build-aux/m4/bitcoin_qt.m4
index 121e10bd37..4ea2e734e8 100644
--- a/build-aux/m4/bitcoin_qt.m4
+++ b/build-aux/m4/bitcoin_qt.m4
@@ -50,7 +50,7 @@ AC_DEFUN([BITCOIN_QT_INIT],[
dnl enable qt support
AC_ARG_WITH([gui],
[AS_HELP_STRING([--with-gui@<:@=no|qt4|qt5|auto@:>@],
- [build bitcoin-qt GUI (default=auto, qt4 tried first)])],
+ [build bitcoin-qt GUI (default=auto, qt5 tried first)])],
[
bitcoin_qt_want_version=$withval
if test x$bitcoin_qt_want_version = xyes; then
diff --git a/configure.ac b/configure.ac
index 4318aafa55..d94dd0c3dc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,6 +58,7 @@ AC_PATH_TOOL(STRIP, strip)
AC_PATH_TOOL(GCOV, gcov)
AC_PATH_PROG(LCOV, lcov)
AC_PATH_PROG(JAVA, java)
+AC_PATH_PROG(PYTHON, python)
AC_PATH_PROG(GENHTML, genhtml)
AC_PATH_PROG([GIT], [git])
AC_PATH_PROG(CCACHE,ccache)
@@ -92,7 +93,7 @@ AC_ARG_ENABLE(tests,
[use_tests=yes])
AC_ARG_ENABLE(bench,
- AS_HELP_STRING([--enable-bench],[compile benchmarks (default is yes)]),
+ AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
[use_bench=$enableval],
[use_bench=yes])
@@ -106,6 +107,11 @@ AC_ARG_ENABLE([comparison-tool-reorg-tests],
[use_comparison_tool_reorg_tests=$enableval],
[use_comparison_tool_reorg_tests=no])
+AC_ARG_ENABLE([extended-rpc-tests],
+ AS_HELP_STRING([--enable-extended-rpc-tests],[enable expensive RPC tests when using lcov (default no)]),
+ [use_extended_rpc_tests=$enableval],
+ [use_extended_rpc_tests=no])
+
AC_ARG_WITH([qrencode],
[AS_HELP_STRING([--with-qrencode],
[enable QR code support (default is yes if qt is enabled and libqrencode is found)])],
@@ -341,6 +347,10 @@ else
AC_SUBST(COMPARISON_TOOL_REORG_TESTS, 0)
fi
+if test x$use_extended_rpc_tests != xno; then
+ AC_SUBST(EXTENDED_RPC_TESTS, -extended)
+fi
+
if test x$use_lcov = xyes; then
if test x$LCOV = x; then
AC_MSG_ERROR("lcov testing requested but lcov not found")
@@ -351,6 +361,9 @@ if test x$use_lcov = xyes; then
if test x$JAVA = x; then
AC_MSG_ERROR("lcov testing requested but java not found")
fi
+ if test x$PYTHON = x; then
+ AC_MSG_ERROR("lcov testing requested but python not found")
+ fi
if test x$GENHTML = x; then
AC_MSG_ERROR("lcov testing requested but genhtml not found")
fi
@@ -525,7 +538,7 @@ fi
BITCOIN_QT_INIT
dnl sets $bitcoin_enable_qt, $bitcoin_enable_qt_test, $bitcoin_enable_qt_dbus
-BITCOIN_QT_CONFIGURE([$use_pkgconfig], [qt4])
+BITCOIN_QT_CONFIGURE([$use_pkgconfig], [qt5])
if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests = xnononono; then
use_boost=no
diff --git a/contrib/gitian-downloader/sipa-key.pgp b/contrib/gitian-downloader/sipa-key.pgp
index ffa09bb4ad..a1930ddee9 100644
--- a/contrib/gitian-downloader/sipa-key.pgp
+++ b/contrib/gitian-downloader/sipa-key.pgp
Binary files differ
diff --git a/contrib/init/README.md b/contrib/init/README.md
index 0d19da3039..eb5d30acce 100644
--- a/contrib/init/README.md
+++ b/contrib/init/README.md
@@ -5,6 +5,7 @@ Upstart: bitcoind.conf
OpenRC: bitcoind.openrc
bitcoind.openrcconf
CentOS: bitcoind.init
+OS X: org.bitcoin.bitcoind.plist
have been made available to assist packagers in creating node packages here.
diff --git a/contrib/init/org.bitcoin.bitcoind.plist b/contrib/init/org.bitcoin.bitcoind.plist
new file mode 100644
index 0000000000..e94cd4466d
--- /dev/null
+++ b/contrib/init/org.bitcoin.bitcoind.plist
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>org.bitcoin.bitcoind</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/local/bin/bitcoind</string>
+ <string>-daemon</string>
+ </array>
+ <key>RunAtLoad</key>
+ <true/>
+</dict>
+</plist>
diff --git a/contrib/verify-commits/allow-revsig-commits b/contrib/verify-commits/allow-revsig-commits
new file mode 100644
index 0000000000..31aeb8f3d3
--- /dev/null
+++ b/contrib/verify-commits/allow-revsig-commits
@@ -0,0 +1,2 @@
+586a29253dabec3ca0f1ccba9091daabd16b8411
+eddaba7b5692288087a926da5733e86b47274e4e
diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh
index 6b5137e7b5..0218b82e11 100755
--- a/contrib/verify-commits/gpg.sh
+++ b/contrib/verify-commits/gpg.sh
@@ -1,15 +1,33 @@
#!/bin/sh
INPUT=$(</dev/stdin)
VALID=false
+REVSIG=false
IFS=$'\n'
for LINE in $(echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null); do
- case "$LINE" in "[GNUPG:] VALIDSIG"*)
+ case "$LINE" in
+ "[GNUPG:] VALIDSIG "*)
while read KEY; do
case "$LINE" in "[GNUPG:] VALIDSIG $KEY "*) VALID=true;; esac
done < ./contrib/verify-commits/trusted-keys
+ ;;
+ "[GNUPG:] REVKEYSIG "*)
+ [ "$BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG" != 1 ] && exit 1
+ while read KEY; do
+ case "$LINE" in "[GNUPG:] REVKEYSIG ${KEY:24:40} "*)
+ REVSIG=true
+ GOODREVSIG="[GNUPG:] GOODSIG ${KEY:24:40} "
+ ;;
+ esac
+ done < ./contrib/verify-commits/trusted-keys
+ ;;
esac
done
if ! $VALID; then
exit 1
fi
-echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null
+if $VALID && $REVSIG; then
+ echo "$INPUT" | gpg --trust-model always "$@" | grep "\[GNUPG:\] \(NEWSIG\|SIG_ID\|VALIDSIG\)" 2>/dev/null
+ echo "$GOODREVSIG"
+else
+ echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null
+fi
diff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh
index 607c0cac45..c57222818a 100755
--- a/contrib/verify-commits/pre-push-hook.sh
+++ b/contrib/verify-commits/pre-push-hook.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-if ! [[ "$2" =~ [git@]?[www.]?github.com[:|/]bitcoin/bitcoin[.git]? ]]; then
+if ! [[ "$2" =~ ^(git@)?(www.)?github.com(:|/)bitcoin/bitcoin(.git)?$ ]]; then
exit 0
fi
diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys
index 658ad0375b..a0dce7a8a5 100644
--- a/contrib/verify-commits/trusted-keys
+++ b/contrib/verify-commits/trusted-keys
@@ -3,3 +3,4 @@
01CDF4627A3B88AAE4A571C87588242FBE38D3A8
AF8BE07C7049F3A26B239D5325B3083201782B2F
81291FA67D2C379A006A053FEAB5AF94D9E9ABE7
+133EAC179436F14A5CF1B794860FEB804E669320
diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh
index 5841fa2077..9ba781008a 100755
--- a/contrib/verify-commits/verify-commits.sh
+++ b/contrib/verify-commits/verify-commits.sh
@@ -7,11 +7,23 @@ git log "$DIR"
VERIFIED_ROOT=$(cat "${DIR}/trusted-git-root")
+IS_REVSIG_ALLOWED () {
+ while read LINE; do
+ [ "$LINE" = "$1" ] && return 0
+ done < "${DIR}/allow-revsig-commits"
+ return 1
+}
+
HAVE_FAILED=false
IS_SIGNED () {
if [ $1 = $VERIFIED_ROOT ]; then
return 0;
fi
+ if IS_REVSIG_ALLOWED "$1"; then
+ export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=1
+ else
+ export BITCOIN_VERIFY_COMMITS_ALLOW_REVSIG=0
+ fi
if ! git -c "gpg.program=${DIR}/gpg.sh" verify-commit $1 > /dev/null 2>&1; then
return 1;
fi
diff --git a/depends/config.guess b/depends/config.guess
index 3c022c5bb8..b3f905370a 100755
--- a/depends/config.guess
+++ b/depends/config.guess
@@ -2,7 +2,7 @@
# Attempt to guess a canonical system name.
# Copyright 1992-2015 Free Software Foundation, Inc.
-timestamp='2015-09-14'
+timestamp='2015-10-21'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -1123,7 +1123,7 @@ EOF
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
- # prints for the "djgpp" host, or else GDB configury will decide that
+ # prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
diff --git a/doc/README.md b/doc/README.md
index 08fd724355..0594d20dd4 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -43,6 +43,8 @@ The following are developer notes on how to build Bitcoin on your native platfor
- [OS X Build Notes](build-osx.md)
- [Unix Build Notes](build-unix.md)
+- [Windows Build Notes](build-windows.md)
+- [OpenBSD Build Notes](build-openbsd.md)
- [Gitian Building Guide](gitian-building.md)
Development
diff --git a/doc/bips.md b/doc/bips.md
index c84bd966f5..c780e2dde0 100644
--- a/doc/bips.md
+++ b/doc/bips.md
@@ -14,6 +14,7 @@ BIPs that are implemented by Bitcoin Core (up-to-date up to **v0.12.0**):
* [`BIP 37`](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki): The bloom filtering for transaction relaying, partial merkle trees for blocks, and the protocol version bump to 70001 (enabling low-bandwidth SPV clients) has been implemented since **v0.8.0** ([PR #1795](https://github.com/bitcoin/bitcoin/pull/1795)).
* [`BIP 42`](https://github.com/bitcoin/bips/blob/master/bip-0042.mediawiki): The bug that would have caused the subsidy schedule to resume after block 13440000 was fixed in **v0.9.2** ([PR #3842](https://github.com/bitcoin/bitcoin/pull/3842)).
* [`BIP 61`](https://github.com/bitcoin/bips/blob/master/bip-0061.mediawiki): The 'reject' protocol message (and the protocol version bump to 70002) was added in **v0.9.0** ([PR #3185](https://github.com/bitcoin/bitcoin/pull/3185)).
+* [`BIP 65`](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki): The CHECKLOCKTIMEVERIFY softfork was merged in **v0.12.0** ([PR #6351](https://github.com/bitcoin/bitcoin/pull/6351)), and backported to **v0.11.2** and **v0.10.4**. Mempool-only CLTV was added in [PR #6124](https://github.com/bitcoin/bitcoin/pull/6124).
* [`BIP 66`](https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki): The strict DER rules and associated version 3 blocks have been implemented since **v0.10.0** ([PR #5713](https://github.com/bitcoin/bitcoin/pull/5713)).
* [`BIP 70`](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki) [`71`](https://github.com/bitcoin/bips/blob/master/bip-0071.mediawiki) [`72`](https://github.com/bitcoin/bips/blob/master/bip-0072.mediawiki): Payment Protocol support has been available in Bitcoin Core GUI since **v0.9.0** ([PR #5216](https://github.com/bitcoin/bitcoin/pull/5216)).
* [`BIP 111`](https://github.com/bitcoin/bips/blob/master/bip-0111.mediawiki): `NODE_BLOOM` service bit added, but only enforced for peer versions `>=70011` as of **v0.12.0** ([PR #6579](https://github.com/bitcoin/bitcoin/pull/6579)).
diff --git a/doc/build-unix.md b/doc/build-unix.md
index a9a0028c4a..2102bbc830 100644
--- a/doc/build-unix.md
+++ b/doc/build-unix.md
@@ -1,6 +1,6 @@
UNIX BUILD NOTES
====================
-Some notes on how to build Bitcoin in Unix.
+Some notes on how to build Bitcoin Core in Unix.
(for OpenBSD specific instructions, see [build-openbsd.md](build-openbsd.md))
@@ -61,49 +61,55 @@ Dependency Build Instructions: Ubuntu & Debian
----------------------------------------------
Build requirements:
- sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libevent-dev
+ sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libevent-dev
-For Ubuntu 12.04 and later or Debian 7 and later libboost-all-dev has to be installed:
+On Ubuntu 15.10+ there are generic names for the individual boost development
+packages, so the following can be used to only install necessary parts of
+boost:
- sudo apt-get install libboost-all-dev
+ apt-get install libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libboost-base-dev
- db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin).
- You can add the repository using the following command:
+For Ubuntu before 15.10, or Debian 7 and later libboost-all-dev has to be installed:
+
+ sudo apt-get install libboost-all-dev
+
+BerkeleyDB is required for the wallet. db4.8 packages are available [here](https://launchpad.net/~bitcoin/+archive/bitcoin).
+You can add the repository and install using the following commands:
sudo add-apt-repository ppa:bitcoin/bitcoin
sudo apt-get update
+ sudo apt-get install libdb4.8-dev libdb4.8++-dev
- Ubuntu 12.04 and later have packages for libdb5.1-dev and libdb5.1++-dev,
- but using these will break binary wallet compatibility, and is not recommended.
+Ubuntu and Debian have their own libdb-dev and libdb++-dev packages, but these will install
+BerkeleyDB 5.1 or later, which break binary wallet compatibility with the distributed executables which
+are based on BerkeleyDB 4.8. If you do not care about wallet compatibility,
+pass `--with-incompatible-bdb` to configure.
-For other Debian & Ubuntu (with ppa):
-
- sudo apt-get install libdb4.8-dev libdb4.8++-dev
+See the section "Disable-wallet mode" to build Bitcoin Core without wallet.
Optional:
- sudo apt-get install libminiupnpc-dev (see --with-miniupnpc and --enable-upnp-default)
+ sudo apt-get install libminiupnpc-dev (see --with-miniupnpc and --enable-upnp-default)
ZMQ dependencies:
sudo apt-get install libzmq3-dev (provides ZMQ API 4.x)
-
Dependencies for the GUI: Ubuntu & Debian
-----------------------------------------
If you want to build Bitcoin-Qt, make sure that the required packages for Qt development
-are installed. Either Qt 4 or Qt 5 are necessary to build the GUI.
-If both Qt 4 and Qt 5 are installed, Qt 4 will be used. Pass `--with-gui=qt5` to configure to choose Qt5.
+are installed. Either Qt 5 or Qt 4 are necessary to build the GUI.
+If both Qt 4 and Qt 5 are installed, Qt 5 will be used. Pass `--with-gui=qt4` to configure to choose Qt4.
To build without GUI pass `--without-gui`.
-To build with Qt 4 you need the following:
+To build with Qt 5 (recommended) you need the following:
- sudo apt-get install libqt4-dev libprotobuf-dev protobuf-compiler
+ sudo apt-get install libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler
-For Qt 5 you need the following:
+Alternatively, to build with Qt 4 you need the following:
- sudo apt-get install libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler
+ sudo apt-get install libqt4-dev libprotobuf-dev protobuf-compiler
libqrencode (optional) can be installed with:
diff --git a/doc/build-windows.md b/doc/build-windows.md
new file mode 100644
index 0000000000..2b9233d1e1
--- /dev/null
+++ b/doc/build-windows.md
@@ -0,0 +1,40 @@
+WINDOWS BUILD NOTES
+====================
+
+Some notes on how to build Bitcoin Core for Windows.
+
+Most developers use cross-compilation from Ubuntu to build executables for
+Windows. This is also used to build the release binaries.
+
+Building on Windows itself is possible (for example using msys / mingw-w64),
+but no one documented the steps to do this. If you are doing this, please contribute them.
+
+Cross-compilation
+-------------------
+
+These steps can be performed on, for example, an Ubuntu VM. The depends system
+will also work on other Linux distributions, however the commands for
+installing the toolchain will be different.
+
+First install the toolchains:
+
+ sudo apt-get install g++-mingw-w64-i686 mingw-w64-i686-dev g++-mingw-w64-x86-64 mingw-w64-x86-64-dev
+
+To build executables for Windows 32-bit:
+
+ cd depends
+ make HOST=i686-w64-mingw32 -j4
+ cd ..
+ ./configure --prefix=`pwd`/depends/i686-w64-mingw32
+ make
+
+To build executables for Windows 64-bit:
+
+ cd depends
+ make HOST=x86_64-w64-mingw32 -j4
+ cd ..
+ ./configure --prefix=`pwd`/depends/x86_64-w64-mingw32
+ make
+
+For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory.
+
diff --git a/doc/developer-notes.md b/doc/developer-notes.md
index 4189d22187..7fe292f1f8 100644
--- a/doc/developer-notes.md
+++ b/doc/developer-notes.md
@@ -171,3 +171,36 @@ Threads
- BitcoinMiner : Generates bitcoins (if wallet is enabled).
- Shutdown : Does an orderly shutdown of everything.
+
+Ignoring IDE/editor files
+--------------------------
+
+In closed-source environments in which everyone uses the same IDE it is common
+to add temporary files it produces to the project-wide `.gitignore` file.
+
+However, in open source software such as Bitcoin Core, where everyone uses
+their own editors/IDE/tools, it is less common. Only you know what files your
+editor produces and this may change from version to version. The canonical way
+to do this is thus to create your local gitignore. Add this to `~/.gitconfig`:
+
+```
+[core]
+ excludesfile = /home/.../.gitignore_global
+```
+
+(alternatively, type the command `git config --global core.excludesfile ~/.gitignore_global`
+on a terminal)
+
+Then put your favourite tool's temporary filenames in that file, e.g.
+```
+# NetBeans
+nbproject/
+```
+
+Another option is to create a per-repository excludes file `.git/info/exclude`.
+These are not committed but apply only to one repository.
+
+If a set of tools is used by the build system or scripts the repository (for
+example, lcov) it is perfectly acceptable to add its files to `.gitignore`
+and commit them.
+
diff --git a/doc/init.md b/doc/init.md
index d24c2d1dbf..e3db5b05ef 100644
--- a/doc/init.md
+++ b/doc/init.md
@@ -13,8 +13,9 @@ can be found in the contrib/init folder.
1. Service User
---------------------------------
-All three startup configurations assume the existence of a "bitcoin" user
+All three Linux startup configurations assume the existence of a "bitcoin" user
and group. They must be created before attempting to use these scripts.
+The OS X configuration assumes bitcoind will be set up for the current user.
2. Configuration
---------------------------------
@@ -48,6 +49,8 @@ see `contrib/debian/examples/bitcoin.conf`.
3. Paths
---------------------------------
+3a) Linux
+
All three configurations assume several paths that might need to be adjusted.
Binary: `/usr/bin/bitcoind`
@@ -62,6 +65,13 @@ reasons to make the configuration file and data directory only readable by the
bitcoin user and group. Access to bitcoin-cli and other bitcoind rpc clients
can then be controlled by group membership.
+3b) Mac OS X
+
+Binary: `/usr/local/bin/bitcoind`
+Configuration file: `~/Library/Application Support/Bitcoin/bitcoin.conf`
+Data directory: `~/Library/Application Support/Bitcoin`
+Lock file: `~/Library/Application Support/Bitcoin/.lock`
+
4. Installing Service Configuration
-----------------------------------
@@ -97,6 +107,17 @@ Using this script, you can adjust the path and flags to the bitcoind program by
setting the BITCOIND and FLAGS environment variables in the file
/etc/sysconfig/bitcoind. You can also use the DAEMONOPTS environment variable here.
+4e) Mac OS X
+
+Copy org.bitcoin.bitcoind.plist into ~/Library/LaunchAgents. Load the launch agent by
+running `launchctl load ~/Library/LaunchAgents/org.bitcoin.bitcoind.plist`.
+
+This Launch Agent will cause bitcoind to start whenever the user logs in.
+
+NOTE: This approach is intended for those wanting to run bitcoind as the current user.
+You will need to modify org.bitcoin.bitcoind.plist if you intend to use it as a
+Launch Daemon with a dedicated bitcoin user.
+
5. Auto-respawn
-----------------------------------
diff --git a/doc/release-notes.md b/doc/release-notes.md
index e9b2d75a76..fd034743e6 100644
--- a/doc/release-notes.md
+++ b/doc/release-notes.md
@@ -124,6 +124,33 @@ sanity check. Since 0.12, these are no longer stored. When loading a
0.12 wallet into an older version, it will automatically rescan to avoid
failed checks.
+BIP65 - CHECKLOCKTIMEVERIFY
+---------------------------
+
+Previously it was impossible to create a transaction output that was guaranteed
+to be unspendable until a specific date in the future. CHECKLOCKTIMEVERIFY is a
+new opcode that allows a script to check if a specific block height or time has
+been reached, failing the script otherwise. This enables a wide variety of new
+functionality such as time-locked escrows, secure payment channels, etc.
+
+BIP65 implements CHECKLOCKTIMEVERIFY by introducing block version 4, which adds
+additional restrictions to the NOP2 opcode. The same miner-voting mechanism as
+in BIP34 and BIP66 is used: when 751 out of a sequence of 1001 blocks have
+version number 4 or higher, the new consensus rule becomes active for those
+blocks. When 951 out of a sequence of 1001 blocks have version number 4 or
+higher, it becomes mandatory for all blocks and blocks with versions less than
+4 are rejected.
+
+Bitcoin Core's block templates are now for version 4 blocks only, and any
+mining software relying on its `getblocktemplate` must be updated in parallel
+to use either libblkmaker version FIXME or any version from 0.5.1 onward. If
+you are solo mining, this will affect you the moment you upgrade Bitcoin Core,
+which must be done prior to BIP65 achieving its 951/1001 status. If you are
+mining with the stratum mining protocol: this does not affect you. If you are
+mining with the getblocktemplate protocol to a pool: this will affect you at
+the pool operator's discretion, which must be no later than BIP65 achieving its
+951/1001 status.
+
0.12.0 Change log
=================
diff --git a/doc/translation_strings_policy.md b/doc/translation_strings_policy.md
index 936a6112c6..b95259cdc9 100644
--- a/doc/translation_strings_policy.md
+++ b/doc/translation_strings_policy.md
@@ -52,7 +52,7 @@ Try to write translation strings in an understandable way, for both the user and
### Do not translate internal errors
Do not translate internal errors, or log messages, or messages that appear on the RPC interface. If an error is to be shown to the user,
-use a generic message, then log the detailed message to the log. E.g. "Error: A fatal internal error occurred, see debug.log for details".
+use a translatable generic message, then log the detailed message to the log. E.g. "A fatal internal error occurred, see debug.log for details".
This helps troubleshooting; if the error is the same for everyone, the likelihood is increased that it can be found using a search engine.
### Avoid fragments
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index 7e682d530a..3059fee426 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -84,12 +84,13 @@ testScriptsExt = [
'keypool.py',
'receivedby.py',
# 'rpcbind_test.py', #temporary, bug in libevent, see #6655
-# 'script_test.py', #used for manual comparison of 2 binaries
+# 'script_test.py', #used for manual comparison of 2 binaries
'smartfees.py',
'maxblocksinflight.py',
'invalidblockrequest.py',
'p2p-acceptblock.py',
'mempool_packages.py',
+ 'maxuploadtarget.py',
]
#Enable ZMQ tests
diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py
index 1f8548c219..9ca5c69f16 100755
--- a/qa/rpc-tests/bip65-cltv-p2p.py
+++ b/qa/rpc-tests/bip65-cltv-p2p.py
@@ -67,6 +67,7 @@ class BIP65Test(ComparisonTestFramework):
def get_tests(self):
self.coinbase_blocks = self.nodes[0].generate(2)
+ height = 3 # height of the next block to build
self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
self.nodeaddress = self.nodes[0].getnewaddress()
self.last_block_time = time.time()
@@ -74,25 +75,27 @@ class BIP65Test(ComparisonTestFramework):
''' 98 more version 3 blocks '''
test_blocks = []
for i in xrange(98):
- block = create_block(self.tip, create_coinbase(2), self.last_block_time + 1)
+ block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 3
block.rehash()
block.solve()
test_blocks.append([block, True])
self.last_block_time += 1
self.tip = block.sha256
+ height += 1
yield TestInstance(test_blocks, sync_every_block=False)
''' Mine 749 version 4 blocks '''
test_blocks = []
for i in xrange(749):
- block = create_block(self.tip, create_coinbase(2), self.last_block_time + 1)
+ block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 4
block.rehash()
block.solve()
test_blocks.append([block, True])
self.last_block_time += 1
self.tip = block.sha256
+ height += 1
yield TestInstance(test_blocks, sync_every_block=False)
'''
@@ -104,7 +107,7 @@ class BIP65Test(ComparisonTestFramework):
cltv_invalidate(spendtx)
spendtx.rehash()
- block = create_block(self.tip, create_coinbase(2), self.last_block_time + 1)
+ block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 4
block.vtx.append(spendtx)
block.hashMerkleRoot = block.calc_merkle_root()
@@ -113,6 +116,7 @@ class BIP65Test(ComparisonTestFramework):
self.last_block_time += 1
self.tip = block.sha256
+ height += 1
yield TestInstance([[block, True]])
'''
@@ -124,7 +128,7 @@ class BIP65Test(ComparisonTestFramework):
cltv_invalidate(spendtx)
spendtx.rehash()
- block = create_block(self.tip, create_coinbase(1), self.last_block_time + 1)
+ block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 4
block.vtx.append(spendtx)
block.hashMerkleRoot = block.calc_merkle_root()
@@ -136,35 +140,38 @@ class BIP65Test(ComparisonTestFramework):
''' Mine 199 new version blocks on last valid tip '''
test_blocks = []
for i in xrange(199):
- block = create_block(self.tip, create_coinbase(1), self.last_block_time + 1)
+ block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 4
block.rehash()
block.solve()
test_blocks.append([block, True])
self.last_block_time += 1
self.tip = block.sha256
+ height += 1
yield TestInstance(test_blocks, sync_every_block=False)
''' Mine 1 old version block '''
- block = create_block(self.tip, create_coinbase(1), self.last_block_time + 1)
+ block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 3
block.rehash()
block.solve()
self.last_block_time += 1
self.tip = block.sha256
+ height += 1
yield TestInstance([[block, True]])
''' Mine 1 new version block '''
- block = create_block(self.tip, create_coinbase(1), self.last_block_time + 1)
+ block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 4
block.rehash()
block.solve()
self.last_block_time += 1
self.tip = block.sha256
+ height += 1
yield TestInstance([[block, True]])
''' Mine 1 old version block, should be invalid '''
- block = create_block(self.tip, create_coinbase(1), self.last_block_time + 1)
+ block = create_block(self.tip, create_coinbase(height), self.last_block_time + 1)
block.nVersion = 3
block.rehash()
block.solve()
diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py
index a5c98b777e..b7bfe36285 100755
--- a/qa/rpc-tests/blockchain.py
+++ b/qa/rpc-tests/blockchain.py
@@ -43,7 +43,7 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(res[u'transactions'], 200)
assert_equal(res[u'height'], 200)
assert_equal(res[u'txouts'], 200)
- assert_equal(res[u'bytes_serialized'], 13000),
+ assert_equal(res[u'bytes_serialized'], 13924),
assert_equal(len(res[u'bestblock']), 64)
assert_equal(len(res[u'hash_serialized']), 64)
diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py
new file mode 100755
index 0000000000..67c4a50985
--- /dev/null
+++ b/qa/rpc-tests/maxuploadtarget.py
@@ -0,0 +1,248 @@
+#!/usr/bin/env python2
+#
+# Distributed under the MIT/X11 software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#
+
+from test_framework.mininode import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+from test_framework.comptool import wait_until
+import time
+
+'''
+Test behavior of -maxuploadtarget.
+
+* Verify that getdata requests for old blocks (>1week) are dropped
+if uploadtarget has been reached.
+* Verify that getdata requests for recent blocks are respecteved even
+if uploadtarget has been reached.
+* Verify that the upload counters are reset after 24 hours.
+'''
+
+# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending
+# p2p messages to a node, generating the messages in the main testing logic.
+class TestNode(NodeConnCB):
+ def __init__(self):
+ NodeConnCB.__init__(self)
+ self.create_callback_map()
+ self.connection = None
+ self.ping_counter = 1
+ self.last_pong = msg_pong()
+ self.block_receive_map = {}
+
+ def add_connection(self, conn):
+ self.connection = conn
+ self.peer_disconnected = False
+
+ def on_inv(self, conn, message):
+ pass
+
+ # Track the last getdata message we receive (used in the test)
+ def on_getdata(self, conn, message):
+ self.last_getdata = message
+
+ def on_block(self, conn, message):
+ message.block.calc_sha256()
+ try:
+ self.block_receive_map[message.block.sha256] += 1
+ except KeyError as e:
+ self.block_receive_map[message.block.sha256] = 1
+
+ # Spin until verack message is received from the node.
+ # We use this to signal that our test can begin. This
+ # is called from the testing thread, so it needs to acquire
+ # the global lock.
+ def wait_for_verack(self):
+ def veracked():
+ return self.verack_received
+ return wait_until(veracked, timeout=10)
+
+ def wait_for_disconnect(self):
+ def disconnected():
+ return self.peer_disconnected
+ return wait_until(disconnected, timeout=10)
+
+ # Wrapper for the NodeConn's send_message function
+ def send_message(self, message):
+ self.connection.send_message(message)
+
+ def on_pong(self, conn, message):
+ self.last_pong = message
+
+ def on_close(self, conn):
+ self.peer_disconnected = True
+
+ # Sync up with the node after delivery of a block
+ def sync_with_ping(self, timeout=30):
+ def received_pong():
+ return (self.last_pong.nonce == self.ping_counter)
+ self.connection.send_message(msg_ping(nonce=self.ping_counter))
+ success = wait_until(received_pong, timeout)
+ self.ping_counter += 1
+ return success
+
+class MaxUploadTest(BitcoinTestFramework):
+ def __init__(self):
+ self.utxo = []
+
+ # Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create
+ # So we have big transactions and full blocks to fill up our block files
+ # create one script_pubkey
+ script_pubkey = "6a4d0200" #OP_RETURN OP_PUSH2 512 bytes
+ for i in xrange (512):
+ script_pubkey = script_pubkey + "01"
+ # concatenate 128 txouts of above script_pubkey which we'll insert before the txout for change
+ self.txouts = "81"
+ for k in xrange(128):
+ # add txout value
+ self.txouts = self.txouts + "0000000000000000"
+ # add length of script_pubkey
+ self.txouts = self.txouts + "fd0402"
+ # add script_pubkey
+ self.txouts = self.txouts + script_pubkey
+
+ def add_options(self, parser):
+ parser.add_option("--testbinary", dest="testbinary",
+ default=os.getenv("BITCOIND", "bitcoind"),
+ help="bitcoind binary to test")
+
+ def setup_chain(self):
+ initialize_chain_clean(self.options.tmpdir, 2)
+
+ def setup_network(self):
+ # Start a node with maxuploadtarget of 200 MB (/24h)
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-maxuploadtarget=200", "-blockmaxsize=999000"]))
+
+ def mine_full_block(self, node, address):
+ # Want to create a full block
+ # We'll generate a 66k transaction below, and 14 of them is close to the 1MB block limit
+ for j in xrange(14):
+ if len(self.utxo) < 14:
+ self.utxo = node.listunspent()
+ inputs=[]
+ outputs = {}
+ t = self.utxo.pop()
+ inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
+ remchange = t["amount"] - Decimal("0.001000")
+ outputs[address]=remchange
+ # Create a basic transaction that will send change back to ourself after account for a fee
+ # And then insert the 128 generated transaction outs in the middle rawtx[92] is where the #
+ # of txouts is stored and is the only thing we overwrite from the original transaction
+ rawtx = node.createrawtransaction(inputs, outputs)
+ newtx = rawtx[0:92]
+ newtx = newtx + self.txouts
+ newtx = newtx + rawtx[94:]
+ # Appears to be ever so slightly faster to sign with SIGHASH_NONE
+ signresult = node.signrawtransaction(newtx,None,None,"NONE")
+ txid = node.sendrawtransaction(signresult["hex"], True)
+ # Mine a full sized block which will be these transactions we just created
+ node.generate(1)
+
+ def run_test(self):
+ # Before we connect anything, we first set the time on the node
+ # to be in the past, otherwise things break because the CNode
+ # time counters can't be reset backward after initialization
+ old_time = int(time.time() - 2*60*60*24*7)
+ self.nodes[0].setmocktime(old_time)
+
+ # Generate some old blocks
+ self.nodes[0].generate(130)
+
+ # test_nodes[0] will only request old blocks
+ # test_nodes[1] will only request new blocks
+ # test_nodes[2] will test resetting the counters
+ test_nodes = []
+ connections = []
+
+ for i in xrange(3):
+ test_nodes.append(TestNode())
+ connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_nodes[i]))
+ test_nodes[i].add_connection(connections[i])
+
+ NetworkThread().start() # Start up network handling in another thread
+ [x.wait_for_verack() for x in test_nodes]
+
+ # Test logic begins here
+
+ # Now mine a big block
+ self.mine_full_block(self.nodes[0], self.nodes[0].getnewaddress())
+
+ # Store the hash; we'll request this later
+ big_old_block = self.nodes[0].getbestblockhash()
+ old_block_size = self.nodes[0].getblock(big_old_block, True)['size']
+ big_old_block = int(big_old_block, 16)
+
+ # Advance to two days ago
+ self.nodes[0].setmocktime(int(time.time()) - 2*60*60*24)
+
+ # Mine one more block, so that the prior block looks old
+ self.mine_full_block(self.nodes[0], self.nodes[0].getnewaddress())
+
+ # We'll be requesting this new block too
+ big_new_block = self.nodes[0].getbestblockhash()
+ new_block_size = self.nodes[0].getblock(big_new_block)['size']
+ big_new_block = int(big_new_block, 16)
+
+ # test_nodes[0] will test what happens if we just keep requesting the
+ # the same big old block too many times (expect: disconnect)
+
+ getdata_request = msg_getdata()
+ getdata_request.inv.append(CInv(2, big_old_block))
+
+ max_bytes_per_day = 200*1024*1024
+ max_bytes_available = max_bytes_per_day - 144*1000000
+ success_count = max_bytes_available / old_block_size
+
+ # 144MB will be reserved for relaying new blocks, so expect this to
+ # succeed for ~70 tries.
+ for i in xrange(success_count):
+ test_nodes[0].send_message(getdata_request)
+ test_nodes[0].sync_with_ping()
+ assert_equal(test_nodes[0].block_receive_map[big_old_block], i+1)
+
+ assert_equal(len(self.nodes[0].getpeerinfo()), 3)
+ # At most a couple more tries should succeed (depending on how long
+ # the test has been running so far).
+ for i in xrange(3):
+ test_nodes[0].send_message(getdata_request)
+ test_nodes[0].wait_for_disconnect()
+ assert_equal(len(self.nodes[0].getpeerinfo()), 2)
+ print "Peer 0 disconnected after downloading old block too many times"
+
+ # Requesting the current block on test_nodes[1] should succeed indefinitely,
+ # even when over the max upload target.
+ # We'll try 200 times
+ getdata_request.inv = [CInv(2, big_new_block)]
+ for i in xrange(200):
+ test_nodes[1].send_message(getdata_request)
+ test_nodes[1].sync_with_ping()
+ assert_equal(test_nodes[1].block_receive_map[big_new_block], i+1)
+
+ print "Peer 1 able to repeatedly download new block"
+
+ # But if test_nodes[1] tries for an old block, it gets disconnected too.
+ getdata_request.inv = [CInv(2, big_old_block)]
+ test_nodes[1].send_message(getdata_request)
+ test_nodes[1].wait_for_disconnect()
+ assert_equal(len(self.nodes[0].getpeerinfo()), 1)
+
+ print "Peer 1 disconnected after trying to download old block"
+
+ print "Advancing system time on node to clear counters..."
+
+ # If we advance the time by 24 hours, then the counters should reset,
+ # and test_nodes[2] should be able to retrieve the old block.
+ self.nodes[0].setmocktime(int(time.time()))
+ test_nodes[2].sync_with_ping()
+ test_nodes[2].send_message(getdata_request)
+ test_nodes[2].sync_with_ping()
+ assert_equal(test_nodes[2].block_receive_map[big_old_block], 1)
+
+ print "Peer 2 able to download old block"
+
+ [c.disconnect_node() for c in connections]
+
+if __name__ == '__main__':
+ MaxUploadTest().main()
diff --git a/src/Makefile.am b/src/Makefile.am
index 312643cec3..f35b9dc898 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -412,7 +412,19 @@ libbitcoinconsensus_la_CPPFLAGS = $(CRYPTO_CFLAGS) -I$(builddir)/obj -DBUILD_BIT
endif
#
-CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno
+CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a
+CLEANFILES += *.gcda *.gcno
+CLEANFILES += compat/*.gcda compat/*.gcno
+CLEANFILES += consensus/*.gcda consensus/*.gcno
+CLEANFILES += crypto/*.gcda crypto/*.gcno
+CLEANFILES += policy/*.gcda policy/*.gcno
+CLEANFILES += primitives/*.gcda primitives/*.gcno
+CLEANFILES += script/*.gcda script/*.gcno
+CLEANFILES += support/*.gcda support/*.gcno
+CLEANFILES += univalue/*.gcda univalue/*.gcno
+CLEANFILES += wallet/*.gcda wallet/*.gcno
+CLEANFILES += wallet/test/*.gcda wallet/test/*.gcno
+CLEANFILES += zmq/*.gcda zmq/*.gcno
DISTCLEANFILES = obj/build.h
@@ -422,7 +434,7 @@ clean-local:
-$(MAKE) -C leveldb clean
-$(MAKE) -C secp256k1 clean
-$(MAKE) -C univalue clean
- rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
+ -rm -f leveldb/*/*.gcda leveldb/*/*.gcno leveldb/helpers/memenv/*.gcda leveldb/helpers/memenv/*.gcno
-rm -f config.h
.rc.o:
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
index 89c3b0cc2a..6ee3cdc27a 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -1,7 +1,9 @@
// Copyright (c) 2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#include "bench.h"
+
#include <iostream>
#include <sys/time.h>
diff --git a/src/bench/bench.h b/src/bench/bench.h
index bf591a2be6..5ce13c642b 100644
--- a/src/bench/bench.h
+++ b/src/bench/bench.h
@@ -1,8 +1,16 @@
// Copyright (c) 2015 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_BENCH_H
-#define BITCOIN_BENCH_H
+
+#ifndef BITCOIN_BENCH_BENCH_H
+#define BITCOIN_BENCH_BENCH_H
+
+#include <map>
+#include <string>
+
+#include <boost/function.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/stringize.hpp>
// Simple micro-benchmarking framework; API mostly matches a subset of the Google Benchmark
// framework (see https://github.com/google/benchmark)
@@ -25,14 +33,7 @@ static void CODE_TO_TIME(benchmark::State& state)
BENCHMARK(CODE_TO_TIME);
*/
-
-
-#include <boost/function.hpp>
-#include <boost/preprocessor/cat.hpp>
-#include <boost/preprocessor/stringize.hpp>
-#include <map>
-#include <string>
-
+
namespace benchmark {
class State {
@@ -68,4 +69,4 @@ namespace benchmark {
#define BENCHMARK(n) \
benchmark::BenchRunner BOOST_PP_CAT(bench_, BOOST_PP_CAT(__LINE__, n))(BOOST_PP_STRINGIZE(n), n);
-#endif // BITCOIN_BENCH_H
+#endif // BITCOIN_BENCH_BENCH_H
diff --git a/src/bitcoin-cli.cpp b/src/bitcoin-cli.cpp
index 6f22c70494..9564573657 100644
--- a/src/bitcoin-cli.cpp
+++ b/src/bitcoin-cli.cpp
@@ -94,7 +94,7 @@ static bool AppInitRPC(int argc, char* argv[])
// Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
try {
SelectBaseParams(ChainNameFromCommandLine());
- } catch(std::exception &e) {
+ } catch (const std::exception& e) {
fprintf(stderr, "Error: %s\n", e.what());
return false;
}
diff --git a/src/bitcoin-tx.cpp b/src/bitcoin-tx.cpp
index 3330fe5d12..48033cd8ad 100644
--- a/src/bitcoin-tx.cpp
+++ b/src/bitcoin-tx.cpp
@@ -37,7 +37,7 @@ static bool AppInitRawTx(int argc, char* argv[])
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
try {
SelectParams(ChainNameFromCommandLine());
- } catch(std::exception &e) {
+ } catch (const std::exception& e) {
fprintf(stderr, "Error: %s\n", e.what());
return false;
}
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index d2af897242..addf0e6a26 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -109,7 +109,7 @@ bool AppInit(int argc, char* argv[])
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
try {
SelectParams(ChainNameFromCommandLine());
- } catch(std::exception &e) {
+ } catch (const std::exception& e) {
fprintf(stderr, "Error: %s\n", e.what());
return false;
}
diff --git a/src/dbwrapper.h b/src/dbwrapper.h
index aa28767508..1d31ab8ae5 100644
--- a/src/dbwrapper.h
+++ b/src/dbwrapper.h
@@ -104,7 +104,7 @@ public:
try {
CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
ssKey >> key;
- } catch(std::exception &e) {
+ } catch (const std::exception&) {
return false;
}
return true;
@@ -120,7 +120,7 @@ public:
CDataStream ssValue(slValue.data(), slValue.data() + slValue.size(), SER_DISK, CLIENT_VERSION);
ssValue.Xor(*obfuscate_key);
ssValue >> value;
- } catch(std::exception &e) {
+ } catch (const std::exception&) {
return false;
}
return true;
diff --git a/src/init.cpp b/src/init.cpp
index 5fd06b3444..cc055900f5 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -222,7 +222,6 @@ void Shutdown()
#if ENABLE_ZMQ
if (pzmqNotificationInterface) {
UnregisterValidationInterface(pzmqNotificationInterface);
- pzmqNotificationInterface->Shutdown();
delete pzmqNotificationInterface;
pzmqNotificationInterface = NULL;
}
@@ -307,8 +306,8 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS));
strUsage += HelpMessageOpt("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)"));
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
- strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288));
- strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3));
+ strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), DEFAULT_CHECKBLOCKS));
+ strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), DEFAULT_CHECKLEVEL));
strUsage += HelpMessageOpt("-conf=<file>", strprintf(_("Specify configuration file (default: %s)"), "bitcoin.conf"));
if (mode == HMM_BITCOIND)
{
@@ -369,6 +368,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-whitebind=<addr>", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6"));
strUsage += HelpMessageOpt("-whitelist=<netmask>", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") +
" " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway"));
+ strUsage += HelpMessageOpt("-maxuploadtarget=<n>", strprintf(_("Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)"), 0));
#ifdef ENABLE_WALLET
strUsage += HelpMessageGroup(_("Wallet options:"));
@@ -376,7 +376,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), 100));
if (showDebug)
strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)",
- CURRENCY_UNIT, FormatMoney(CWallet::minTxFee.GetFeePerK())));
+ CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
CURRENCY_UNIT, FormatMoney(payTxFee.GetFeePerK())));
strUsage += HelpMessageOpt("-rescan", _("Rescan the block chain for missing wallet transactions") + " " + _("on startup"));
@@ -406,12 +406,16 @@ std::string HelpMessage(HelpMessageMode mode)
if (showDebug)
{
strUsage += HelpMessageOpt("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", 1));
- strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush database activity from memory pool to disk log every <n> megabytes (default: %u)", 100));
+#ifdef ENABLE_WALLET
+ strUsage += HelpMessageOpt("-dblogsize=<n>", strprintf("Flush wallet database activity from memory to disk log every <n> megabytes (default: %u)", DEFAULT_WALLET_DBLOGSIZE));
+#endif
strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", 0));
strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", 0));
strUsage += HelpMessageOpt("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages");
strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", "Randomly fuzz 1 of every <n> network messages");
+#ifdef ENABLE_WALLET
strUsage += HelpMessageOpt("-flushwallet", strprintf("Run a thread to flush wallet periodically (default: %u)", 1));
+#endif
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", 0));
strUsage += HelpMessageOpt("-limitancestorcount=<n>", strprintf("Do not accept transactions if number of in-mempool ancestors is <n> or more (default: %u)", DEFAULT_ANCESTOR_LIMIT));
strUsage += HelpMessageOpt("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT));
@@ -424,12 +428,13 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + _("<category> can be:") + " " + debugCategories + ".");
strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), 0));
- strUsage += HelpMessageOpt("-genproclimit=<n>", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1));
+ strUsage += HelpMessageOpt("-genproclimit=<n>", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), DEFAULT_GENERATE_THREADS));
strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)"));
strUsage += HelpMessageOpt("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), 0));
strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), 1));
if (showDebug)
{
+ strUsage += HelpMessageOpt("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS));
strUsage += HelpMessageOpt("-limitfreerelay=<n>", strprintf("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default: %u)", 15));
strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", 1));
strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf("Limit size of signature cache to <n> entries (default: %u)", 50000));
@@ -690,13 +695,13 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
#endif
if (!SetupNetworking())
- return InitError("Error: Initializing networking failed");
+ return InitError("Initializing networking failed");
#ifndef WIN32
if (GetBoolArg("-sysperms", false)) {
#ifdef ENABLE_WALLET
if (!GetBoolArg("-disablewallet", false))
- return InitError("Error: -sysperms is not allowed in combination with enabled wallet functionality");
+ return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
#endif
} else {
umask(077);
@@ -727,6 +732,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// Set this early so that parameter interactions go to console
fPrintToConsole = GetBoolArg("-printtoconsole", false);
fLogTimestamps = GetBoolArg("-logtimestamps", true);
+ fLogTimeMicros = GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
fLogIPs = GetBoolArg("-logips", false);
LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
@@ -826,19 +832,22 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// Check for -debugnet
if (GetBoolArg("-debugnet", false))
- InitWarning(_("Warning: Unsupported argument -debugnet ignored, use -debug=net."));
+ InitWarning(_("Unsupported argument -debugnet ignored, use -debug=net."));
// Check for -socks - as this is a privacy risk to continue, exit here
if (mapArgs.count("-socks"))
- return InitError(_("Error: Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported."));
+ return InitError(_("Unsupported argument -socks found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported."));
// Check for -tor - as this is a privacy risk to continue, exit here
if (GetBoolArg("-tor", false))
- return InitError(_("Error: Unsupported argument -tor found, use -onion."));
+ return InitError(_("Unsupported argument -tor found, use -onion."));
if (GetBoolArg("-benchmark", false))
- InitWarning(_("Warning: Unsupported argument -benchmark ignored, use -debug=bench."));
+ InitWarning(_("Unsupported argument -benchmark ignored, use -debug=bench."));
// Checkmempool and checkblockindex default to true in regtest mode
- mempool.setSanityCheck(GetBoolArg("-checkmempool", chainparams.DefaultConsistencyChecks()));
+ int ratio = std::min<int>(std::max<int>(GetArg("-checkmempool", chainparams.DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
+ if (ratio != 0) {
+ mempool.setSanityCheck(1.0 / ratio);
+ }
fCheckBlockIndex = GetBoolArg("-checkblockindex", chainparams.DefaultConsistencyChecks());
fCheckpointsEnabled = GetBoolArg("-checkpoints", true);
@@ -846,7 +855,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
int64_t nMempoolSizeLimit = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
int64_t nMempoolDescendantSizeLimit = GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000;
if (nMempoolSizeLimit < 0 || nMempoolSizeLimit < nMempoolDescendantSizeLimit * 40)
- return InitError(strprintf(_("Error: -maxmempool must be at least %d MB"), GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) / 25));
+ return InitError(strprintf(_("-maxmempool must be at least %d MB"), GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) / 25));
// -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
nScriptCheckThreads = GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
@@ -915,7 +924,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK))
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"]));
if (nFeePerK > nHighTransactionFeeWarning)
- InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
+ InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
payTxFee = CFeeRate(nFeePerK, 1000);
if (payTxFee < ::minRelayTxFee)
{
@@ -929,7 +938,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee))
return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s'"), mapArgs["-maptxfee"]));
if (nMaxFee > nHighTransactionMaxFeeWarning)
- InitWarning(_("Warning: -maxtxfee is set very high! Fees this large could be paid on a single transaction."));
+ InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
maxTxFee = nMaxFee;
if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
{
@@ -1056,12 +1065,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
BOOST_FOREACH(string cmt, mapMultiArgs["-uacomment"])
{
if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
- return InitError(strprintf("User Agent comment (%s) contains unsafe characters.", cmt));
+ return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt));
uacomments.push_back(SanitizeString(cmt, SAFE_CHARS_UA_COMMENT));
}
strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments);
if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {
- return InitError(strprintf("Total length of network version string %i exceeds maximum of %i characters. Reduce the number and/or size of uacomments.",
+ return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments."),
strSubVersion.size(), MAX_SUBVERSION_LENGTH));
}
@@ -1170,10 +1179,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
pzmqNotificationInterface = CZMQNotificationInterface::CreateWithArguments(mapArgs);
if (pzmqNotificationInterface) {
- pzmqNotificationInterface->Initialize();
RegisterValidationInterface(pzmqNotificationInterface);
}
#endif
+ if (mapArgs.count("-maxuploadtarget")) {
+ CNode::SetMaxOutboundTarget(GetArg("-maxuploadtarget", 0)*1024*1024);
+ }
// ********************************************************* Step 7: load block chain
@@ -1280,9 +1291,9 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
uiInterface.InitMessage(_("Verifying blocks..."));
- if (fHavePruned && GetArg("-checkblocks", 288) > MIN_BLOCKS_TO_KEEP) {
+ if (fHavePruned && GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
LogPrintf("Prune: pruned datadir may not have more than %d blocks; -checkblocks=%d may fail\n",
- MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", 288));
+ MIN_BLOCKS_TO_KEEP, GetArg("-checkblocks", DEFAULT_CHECKBLOCKS));
}
{
@@ -1296,8 +1307,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
}
}
- if (!CVerifyDB().VerifyDB(pcoinsdbview, GetArg("-checklevel", 3),
- GetArg("-checkblocks", 288))) {
+ if (!CVerifyDB().VerifyDB(pcoinsdbview, GetArg("-checklevel", DEFAULT_CHECKLEVEL),
+ GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
strLoadError = _("Corrupted block database detected");
break;
}
@@ -1382,9 +1393,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
strErrors << _("Error loading wallet.dat: Wallet corrupted") << "\n";
else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
{
- string msg(_("Warning: error reading wallet.dat! All keys read correctly, but transaction data"
+ InitWarning(_("Error reading wallet.dat! All keys read correctly, but transaction data"
" or address book entries might be missing or incorrect."));
- InitWarning(msg);
}
else if (nLoadWalletRet == DB_TOO_NEW)
strErrors << _("Error loading wallet.dat: Wallet requires newer version of Bitcoin Core") << "\n";
@@ -1565,7 +1575,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
scheduler.scheduleEvery(f, nPowTargetSpacing);
// Generate coins in the background
- GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 1), Params());
+ GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", DEFAULT_GENERATE_THREADS), Params());
// ********************************************************* Step 12: finished
diff --git a/src/leveldb/util/env_win.cc b/src/leveldb/util/env_win.cc
index ef2ecae830..e11a96b791 100644
--- a/src/leveldb/util/env_win.cc
+++ b/src/leveldb/util/env_win.cc
@@ -103,39 +103,20 @@ private:
DISALLOW_COPY_AND_ASSIGN(Win32RandomAccessFile);
};
-class Win32MapFile : public WritableFile
+class Win32WritableFile : public WritableFile
{
public:
- Win32MapFile(const std::string& fname);
+ Win32WritableFile(const std::string& fname);
+ ~Win32WritableFile();
- ~Win32MapFile();
virtual Status Append(const Slice& data);
virtual Status Close();
virtual Status Flush();
virtual Status Sync();
BOOL isEnable();
private:
- std::string _filename;
- HANDLE _hFile;
- size_t _page_size;
- size_t _map_size; // How much extra memory to map at a time
- char* _base; // The mapped region
- HANDLE _base_handle;
- 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
- //LARGE_INTEGER file_offset_;
- // 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);
- size_t _TruncateToPageBoundary(size_t s);
- bool _UnmapCurrentRegion();
- bool _MapNewRegion();
- DISALLOW_COPY_AND_ASSIGN(Win32MapFile);
- BOOL _Init(LPCWSTR Path);
+ std::string filename_;
+ ::HANDLE _hFile;
};
class Win32FileLock : public FileLock
@@ -442,202 +423,63 @@ void Win32RandomAccessFile::_CleanUp()
}
}
-size_t Win32MapFile::_Roundup( size_t x, size_t y )
+Win32WritableFile::Win32WritableFile(const std::string& fname)
+ : filename_(fname)
{
- return ((x + y - 1) / y) * y;
+ std::wstring path;
+ ToWidePath(fname, path);
+ DWORD Flag = PathFileExistsW(path.c_str()) ? OPEN_EXISTING : CREATE_ALWAYS;
+ _hFile = CreateFileW(path.c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
+ NULL,
+ Flag,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ // CreateFileW returns INVALID_HANDLE_VALUE in case of error, always check isEnable() before use
}
-size_t Win32MapFile::_TruncateToPageBoundary( size_t s )
+Win32WritableFile::~Win32WritableFile()
{
- s -= (s & (_page_size - 1));
- assert((s % _page_size) == 0);
- return s;
+ if (_hFile != INVALID_HANDLE_VALUE)
+ Close();
}
-bool Win32MapFile::_UnmapCurrentRegion()
+Status Win32WritableFile::Append(const Slice& data)
{
- bool result = true;
- if (_base != NULL) {
- if (_last_sync < _limit) {
- // Defer syncing this data until next Sync() call, if any
- _pending_sync = true;
- }
- if (!UnmapViewOfFile(_base) || !CloseHandle(_base_handle))
- result = false;
- _file_offset += _limit - _base;
- _base = NULL;
- _base_handle = 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;
- }
+ DWORD r = 0;
+ if (!WriteFile(_hFile, data.data(), data.size(), &r, NULL) || r != data.size()) {
+ return Status::IOError("Win32WritableFile.Append::WriteFile: "+filename_, Win32::GetLastErrSz());
}
- return result;
-}
-
-bool Win32MapFile::_MapNewRegion()
-{
- assert(_base == NULL);
- //LONG newSizeHigh = (LONG)((file_offset_ + map_size_) >> 32);
- //LONG newSizeLow = (LONG)((file_offset_ + map_size_) & 0xFFFFFFFF);
- DWORD off_hi = (DWORD)(_file_offset >> 32);
- DWORD off_lo = (DWORD)(_file_offset & 0xFFFFFFFF);
- LARGE_INTEGER newSize;
- newSize.QuadPart = _file_offset + _map_size;
- SetFilePointerEx(_hFile, newSize, NULL, FILE_BEGIN);
- SetEndOfFile(_hFile);
-
- _base_handle = CreateFileMappingA(
- _hFile,
- NULL,
- PAGE_READWRITE,
- 0,
- 0,
- 0);
- if (_base_handle != NULL) {
- _base = (char*) MapViewOfFile(_base_handle,
- FILE_MAP_ALL_ACCESS,
- off_hi,
- off_lo,
- _map_size);
- if (_base != NULL) {
- _limit = _base + _map_size;
- _dst = _base;
- _last_sync = _base;
- return true;
- }
- }
- return false;
+ return Status::OK();
}
-Win32MapFile::Win32MapFile( const std::string& fname) :
- _filename(fname),
- _hFile(NULL),
- _page_size(Win32::g_PageSize),
- _map_size(_Roundup(65536, Win32::g_PageSize)),
- _base(NULL),
- _base_handle(NULL),
- _limit(NULL),
- _dst(NULL),
- _last_sync(NULL),
- _file_offset(0),
- _pending_sync(false)
+Status Win32WritableFile::Close()
{
- std::wstring path;
- ToWidePath(fname, path);
- _Init(path.c_str());
- assert((Win32::g_PageSize & (Win32::g_PageSize - 1)) == 0);
-}
-
-Status Win32MapFile::Append( const Slice& data )
-{
- const char* src = data.data();
- size_t left = data.size();
- Status s;
- while (left > 0) {
- assert(_base <= _dst);
- assert(_dst <= _limit);
- size_t avail = _limit - _dst;
- if (avail == 0) {
- if (!_UnmapCurrentRegion() ||
- !_MapNewRegion()) {
- return Status::IOError("WinMmapFile.Append::UnmapCurrentRegion or MapNewRegion: ", Win32::GetLastErrSz());
- }
- }
- size_t n = (left <= avail) ? left : avail;
- memcpy(_dst, src, n);
- _dst += n;
- src += n;
- left -= n;
- }
- return s;
-}
-
-Status Win32MapFile::Close()
-{
- Status s;
- size_t unused = _limit - _dst;
- if (!_UnmapCurrentRegion()) {
- s = Status::IOError("WinMmapFile.Close::UnmapCurrentRegion: ",Win32::GetLastErrSz());
- } else if (unused > 0) {
- // Trim the extra space at the end of the file
- LARGE_INTEGER newSize;
- newSize.QuadPart = _file_offset - unused;
- if (!SetFilePointerEx(_hFile, newSize, NULL, FILE_BEGIN)) {
- s = Status::IOError("WinMmapFile.Close::SetFilePointer: ",Win32::GetLastErrSz());
- } else
- SetEndOfFile(_hFile);
- }
if (!CloseHandle(_hFile)) {
- if (s.ok()) {
- s = Status::IOError("WinMmapFile.Close::CloseHandle: ", Win32::GetLastErrSz());
- }
+ return Status::IOError("Win32WritableFile.Close::CloseHandle: "+filename_, Win32::GetLastErrSz());
}
_hFile = INVALID_HANDLE_VALUE;
- _base = NULL;
- _base_handle = NULL;
- _limit = NULL;
-
- return s;
-}
-
-Status Win32MapFile::Sync()
-{
- Status s;
- if (_pending_sync) {
- // Some unmapped data was not synced
- _pending_sync = false;
- if (!FlushFileBuffers(_hFile)) {
- s = Status::IOError("WinMmapFile.Sync::FlushFileBuffers: ",Win32::GetLastErrSz());
- }
- }
- 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 (!FlushViewOfFile(_base + p1, p2 - p1 + _page_size)) {
- s = Status::IOError("WinMmapFile.Sync::FlushViewOfFile: ",Win32::GetLastErrSz());
- }
- }
- return s;
+ return Status::OK();
}
-Status Win32MapFile::Flush()
+Status Win32WritableFile::Flush()
{
+ // Nothing to do here, there are no application-side buffers
return Status::OK();
}
-Win32MapFile::~Win32MapFile()
+Status Win32WritableFile::Sync()
{
- if (_hFile != INVALID_HANDLE_VALUE) {
- Win32MapFile::Close();
+ if (!FlushFileBuffers(_hFile)) {
+ return Status::IOError("Win32WritableFile.Sync::FlushFileBuffers "+filename_, Win32::GetLastErrSz());
}
+ return Status::OK();
}
-BOOL Win32MapFile::_Init( LPCWSTR Path )
-{
- DWORD Flag = PathFileExistsW(Path) ? OPEN_EXISTING : CREATE_ALWAYS;
- _hFile = CreateFileW(Path,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_DELETE|FILE_SHARE_WRITE,
- NULL,
- Flag,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
- if(!_hFile || _hFile == INVALID_HANDLE_VALUE)
- return FALSE;
- else
- return TRUE;
-}
-
-BOOL Win32MapFile::isEnable()
+BOOL Win32WritableFile::isEnable()
{
- return _hFile ? TRUE : FALSE;
+ return _hFile != INVALID_HANDLE_VALUE;
}
Win32FileLock::Win32FileLock( const std::string& fname ) :
@@ -981,7 +823,7 @@ Status Win32Env::NewLogger( const std::string& fname, Logger** result )
{
Status sRet;
std::string path = fname;
- Win32MapFile* pMapFile = new Win32MapFile(ModifyPath(path));
+ Win32WritableFile* pMapFile = new Win32WritableFile(ModifyPath(path));
if(!pMapFile->isEnable()){
delete pMapFile;
*result = NULL;
@@ -995,7 +837,7 @@ Status Win32Env::NewWritableFile( const std::string& fname, WritableFile** resul
{
Status sRet;
std::string path = fname;
- Win32MapFile* pFile = new Win32MapFile(ModifyPath(path));
+ Win32WritableFile* pFile = new Win32WritableFile(ModifyPath(path));
if(!pFile->isEnable()){
*result = NULL;
sRet = Status::IOError(fname,Win32::GetLastErrSz());
diff --git a/src/main.cpp b/src/main.cpp
index c340bcd5c4..5a0406c771 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -3805,6 +3805,16 @@ void static ProcessGetData(CNode* pfrom)
}
}
}
+ // disconnect node in case we have reached the outbound limit for serving historical blocks
+ static const int nOneWeek = 7 * 24 * 60 * 60; // assume > 1 week = historical
+ if (send && CNode::OutboundTargetReached(true) && ( ((pindexBestHeader != NULL) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > nOneWeek)) || inv.type == MSG_FILTERED_BLOCK) )
+ {
+ LogPrint("net", "historical block serving limit reached, disconnect peer=%d\n", pfrom->GetId());
+
+ //disconnect node
+ pfrom->fDisconnect = true;
+ send = false;
+ }
// Pruned nodes may have deleted the block, so check whether
// it's available before trying to send.
if (send && (mi->second->nStatus & BLOCK_HAVE_DATA))
diff --git a/src/main.h b/src/main.h
index 202d2c772b..c3874be663 100644
--- a/src/main.h
+++ b/src/main.h
@@ -127,6 +127,9 @@ extern uint64_t nPruneTarget;
/** Block files containing a block-height within MIN_BLOCKS_TO_KEEP of chainActive.Tip() will not be pruned. */
static const unsigned int MIN_BLOCKS_TO_KEEP = 288;
+static const signed int DEFAULT_CHECKBLOCKS = MIN_BLOCKS_TO_KEEP;
+static const unsigned int DEFAULT_CHECKLEVEL = 3;
+
// Require that user allocate at least 550MB for block & undo files (blk???.dat and rev???.dat)
// At 1MB per block, 288 blocks = 288MB.
// Add 15% for Undo data = 331MB
diff --git a/src/memusage.h b/src/memusage.h
index b475c3313b..e96c5bf038 100644
--- a/src/memusage.h
+++ b/src/memusage.h
@@ -121,4 +121,4 @@ static inline size_t DynamicUsage(const boost::unordered_map<X, Y, Z>& m)
}
-#endif
+#endif // BITCOIN_MEMUSAGE_H
diff --git a/src/miner.h b/src/miner.h
index 7e0e58d540..ad13204818 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -17,6 +17,8 @@ class CScript;
class CWallet;
namespace Consensus { struct Params; };
+static const int DEFAULT_GENERATE_THREADS = 1;
+
struct CBlockTemplate
{
CBlock block;
diff --git a/src/net.cpp b/src/net.cpp
index 58b946f4a1..e18e8d0e29 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -12,6 +12,7 @@
#include "addrman.h"
#include "chainparams.h"
#include "clientversion.h"
+#include "consensus/consensus.h"
#include "crypto/common.h"
#include "hash.h"
#include "primitives/transaction.h"
@@ -326,6 +327,11 @@ uint64_t CNode::nTotalBytesSent = 0;
CCriticalSection CNode::cs_totalBytesRecv;
CCriticalSection CNode::cs_totalBytesSent;
+uint64_t CNode::nMaxOutboundLimit = 0;
+uint64_t CNode::nMaxOutboundTotalBytesSentInCycle = 0;
+uint64_t CNode::nMaxOutboundTimeframe = 60*60*24; //1 day
+uint64_t CNode::nMaxOutboundCycleStartTime = 0;
+
CNode* FindNode(const CNetAddr& ip)
{
LOCK(cs_vNodes);
@@ -2083,6 +2089,94 @@ void CNode::RecordBytesSent(uint64_t bytes)
{
LOCK(cs_totalBytesSent);
nTotalBytesSent += bytes;
+
+ uint64_t now = GetTime();
+ if (nMaxOutboundCycleStartTime + nMaxOutboundTimeframe < now)
+ {
+ // timeframe expired, reset cycle
+ nMaxOutboundCycleStartTime = now;
+ nMaxOutboundTotalBytesSentInCycle = 0;
+ }
+
+ // TODO, exclude whitebind peers
+ nMaxOutboundTotalBytesSentInCycle += bytes;
+}
+
+void CNode::SetMaxOutboundTarget(uint64_t limit)
+{
+ LOCK(cs_totalBytesSent);
+ uint64_t recommendedMinimum = (nMaxOutboundTimeframe / 600) * MAX_BLOCK_SIZE;
+ nMaxOutboundLimit = limit;
+
+ if (limit < recommendedMinimum)
+ LogPrintf("Max outbound target is very small (%s) and will be overshot. Recommended minimum is %s\n.", nMaxOutboundLimit, recommendedMinimum);
+}
+
+uint64_t CNode::GetMaxOutboundTarget()
+{
+ LOCK(cs_totalBytesSent);
+ return nMaxOutboundLimit;
+}
+
+uint64_t CNode::GetMaxOutboundTimeframe()
+{
+ LOCK(cs_totalBytesSent);
+ return nMaxOutboundTimeframe;
+}
+
+uint64_t CNode::GetMaxOutboundTimeLeftInCycle()
+{
+ LOCK(cs_totalBytesSent);
+ if (nMaxOutboundLimit == 0)
+ return 0;
+
+ if (nMaxOutboundCycleStartTime == 0)
+ return nMaxOutboundTimeframe;
+
+ uint64_t cycleEndTime = nMaxOutboundCycleStartTime + nMaxOutboundTimeframe;
+ uint64_t now = GetTime();
+ return (cycleEndTime < now) ? 0 : cycleEndTime - GetTime();
+}
+
+void CNode::SetMaxOutboundTimeframe(uint64_t timeframe)
+{
+ LOCK(cs_totalBytesSent);
+ if (nMaxOutboundTimeframe != timeframe)
+ {
+ // reset measure-cycle in case of changing
+ // the timeframe
+ nMaxOutboundCycleStartTime = GetTime();
+ }
+ nMaxOutboundTimeframe = timeframe;
+}
+
+bool CNode::OutboundTargetReached(bool historicalBlockServingLimit)
+{
+ LOCK(cs_totalBytesSent);
+ if (nMaxOutboundLimit == 0)
+ return false;
+
+ if (historicalBlockServingLimit)
+ {
+ // keep a large enought buffer to at least relay each block once
+ uint64_t timeLeftInCycle = GetMaxOutboundTimeLeftInCycle();
+ uint64_t buffer = timeLeftInCycle / 600 * MAX_BLOCK_SIZE;
+ if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
+ return true;
+ }
+ else if (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit)
+ return true;
+
+ return false;
+}
+
+uint64_t CNode::GetOutboundTargetBytesLeft()
+{
+ LOCK(cs_totalBytesSent);
+ if (nMaxOutboundLimit == 0)
+ return 0;
+
+ return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) ? 0 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle;
}
uint64_t CNode::GetTotalBytesRecv()
diff --git a/src/net.h b/src/net.h
index 6842ee5edc..f90b3385af 100644
--- a/src/net.h
+++ b/src/net.h
@@ -400,6 +400,12 @@ private:
static uint64_t nTotalBytesRecv;
static uint64_t nTotalBytesSent;
+ // outbound limit & stats
+ static uint64_t nMaxOutboundTotalBytesSentInCycle;
+ static uint64_t nMaxOutboundCycleStartTime;
+ static uint64_t nMaxOutboundLimit;
+ static uint64_t nMaxOutboundTimeframe;
+
CNode(const CNode&);
void operator=(const CNode&);
@@ -701,6 +707,27 @@ public:
static uint64_t GetTotalBytesRecv();
static uint64_t GetTotalBytesSent();
+
+ //!set the max outbound target in bytes
+ static void SetMaxOutboundTarget(uint64_t limit);
+ static uint64_t GetMaxOutboundTarget();
+
+ //!set the timeframe for the max outbound target
+ static void SetMaxOutboundTimeframe(uint64_t timeframe);
+ static uint64_t GetMaxOutboundTimeframe();
+
+ //!check if the outbound target is reached
+ // if param historicalBlockServingLimit is set true, the function will
+ // response true if the limit for serving historical blocks has been reached
+ static bool OutboundTargetReached(bool historicalBlockServingLimit);
+
+ //!response the bytes left in the current max outbound cycle
+ // in case of no limit, it will always response 0
+ static uint64_t GetOutboundTargetBytesLeft();
+
+ //!response the time in second left in the current max outbound cycle
+ // in case of no limit, it will always response 0
+ static uint64_t GetMaxOutboundTimeLeftInCycle();
};
diff --git a/src/policy/policy.h b/src/policy/policy.h
index 0ea0d435ad..747c5ce8ce 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -3,8 +3,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_POLICY_H
-#define BITCOIN_POLICY_H
+#ifndef BITCOIN_POLICY_POLICY_H
+#define BITCOIN_POLICY_POLICY_H
#include "consensus/consensus.h"
#include "script/interpreter.h"
@@ -56,4 +56,4 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason);
*/
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
-#endif // BITCOIN_POLICY_H
+#endif // BITCOIN_POLICY_POLICY_H
diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp
index c5ac07cfc2..a488d298c4 100644
--- a/src/qt/addresstablemodel.cpp
+++ b/src/qt/addresstablemodel.cpp
@@ -218,7 +218,7 @@ QVariant AddressTableModel::data(const QModelIndex &index, int role) const
QFont font;
if(index.column() == Address)
{
- font = GUIUtil::bitcoinAddressFont();
+ font = GUIUtil::fixedPitchFont();
}
return font;
}
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 3cde2657cf..538b8912ab 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -13,6 +13,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"(1 = keep tx meta data e.g. account owner and payment request information, 2 "
"= drop tx meta data)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"-maxtxfee is set very high! Fees this large could be paid on a single "
+"transaction."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"-paytxfee is set very high! This is the transaction fee you will pay if you "
+"send a transaction."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Allow JSON-RPC connections from specified source. Valid for <ip> are a "
"single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or "
"a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times"),
@@ -42,10 +48,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Distributed under the MIT software license, see the accompanying file "
"COPYING or <http://www.opensource.org/licenses/mit-license.php>."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Error: Listening for incoming connections failed (listen returned error %s)"),
+"Do not keep transactions in the mempool longer than <n> hours (default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Error: Unsupported argument -socks found. Setting SOCKS version isn't "
-"possible anymore, only SOCKS5 proxies are supported."),
+"Error reading wallet.dat! All keys read correctly, but transaction data or "
+"address book entries might be missing or incorrect."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Error: Listening for incoming connections failed (listen returned error %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Execute command when a relevant alert is received or we see a really long "
"fork (%s in cmd is replaced by message)"),
@@ -127,9 +135,18 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"the OpenSSL Toolkit <https://www.openssl.org/> and cryptographic software "
"written by Eric Young and UPnP software written by Thomas Bernard."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Total length of network version string (%i) exceeds maximum length (%i). "
+"Reduce the number or size of uacomments."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = "
+"no limit (default: %d)"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Unable to bind to %s on this computer. Bitcoin Core is probably already "
"running."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Unsupported argument -socks found. Setting SOCKS version isn't possible "
+"anymore, only SOCKS5 proxies are supported."),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Use UPnP to map the listening port (default: 1 when listening and no -proxy)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: "
@@ -141,21 +158,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"WARNING: check your network connection, %d blocks received in the last %d "
"hours (%d expected)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Warning: -maxtxfee is set very high! Fees this large could be paid on a "
-"single transaction."),
-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", ""
"Warning: The network does not appear to fully agree! Some miners appear to "
"be experiencing issues."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Warning: We do not appear to fully agree with our peers! You may need to "
"upgrade, or other nodes may need to upgrade."),
QT_TRANSLATE_NOOP("bitcoin-core", ""
-"Warning: error reading wallet.dat! All keys read correctly, but transaction "
-"data or address book entries might be missing or incorrect."),
-QT_TRANSLATE_NOOP("bitcoin-core", ""
"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."),
@@ -171,6 +179,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
QT_TRANSLATE_NOOP("bitcoin-core", "(default: %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", "(default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", "(default: 1)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "-maxmempool must be at least %d MB"),
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)"),
@@ -212,7 +221,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Error reading from database, shutting down.")
QT_TRANSLATE_NOOP("bitcoin-core", "Error"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: A fatal internal error occurred, see debug.log for details"),
QT_TRANSLATE_NOOP("bitcoin-core", "Error: Disk space is low!"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Error: Unsupported argument -tor found, use -onion."),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to listen on any port. Use -listen=0 if you want this."),
QT_TRANSLATE_NOOP("bitcoin-core", "Fee (in %s/kB) to add to transactions you send (default: %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins (default: %u)"),
@@ -233,6 +241,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s' (
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid amount for -paytxfee=<amount>: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid netmask specified in -whitelist: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Keep at most <n> unconnectable transactions in memory (default: %u)"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Keep the transaction memory pool below <n> megabytes (default: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Listen for connections on <port> (default: %u or testnet: %u)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Loading addresses..."),
@@ -294,9 +303,12 @@ QT_TRANSLATE_NOOP("bitcoin-core", "UI Options:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to bind to %s on this computer (bind returned error %s)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Unable to start HTTP server. See debug log for details."),
QT_TRANSLATE_NOOP("bitcoin-core", "Unknown network specified in -onlynet: '%s'"),
+QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported argument -benchmark ignored, use -debug=bench."),
+QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported argument -debugnet ignored, use -debug=net."),
+QT_TRANSLATE_NOOP("bitcoin-core", "Unsupported argument -tor found, use -onion."),
QT_TRANSLATE_NOOP("bitcoin-core", "Upgrade wallet to latest format"),
QT_TRANSLATE_NOOP("bitcoin-core", "Use UPnP to map the listening port (default: %u)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Use the test network"),
+QT_TRANSLATE_NOOP("bitcoin-core", "User Agent comment (%s) contains unsafe characters."),
QT_TRANSLATE_NOOP("bitcoin-core", "Username for JSON-RPC connections"),
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying blocks..."),
QT_TRANSLATE_NOOP("bitcoin-core", "Verifying wallet..."),
@@ -305,8 +317,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Wallet needed to be rewritten: restart Bitcoi
QT_TRANSLATE_NOOP("bitcoin-core", "Wallet options:"),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning"),
QT_TRANSLATE_NOOP("bitcoin-core", "Warning: This version is obsolete; upgrade required!"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Unsupported argument -benchmark ignored, use -debug=bench."),
-QT_TRANSLATE_NOOP("bitcoin-core", "Warning: Unsupported argument -debugnet ignored, use -debug=net."),
QT_TRANSLATE_NOOP("bitcoin-core", "You need to rebuild the database using -reindex to change -txindex"),
QT_TRANSLATE_NOOP("bitcoin-core", "Zapping all transactions from wallet..."),
QT_TRANSLATE_NOOP("bitcoin-core", "ZeroMQ notification options:"),
diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp
index 781d8f7e02..81b2597c3b 100644
--- a/src/qt/coincontroldialog.cpp
+++ b/src/qt/coincontroldialog.cpp
@@ -567,7 +567,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
nChange -= nPayFee;
// Never create dust outputs; if we would, just add the dust to the fee.
- if (nChange > 0 && nChange < CENT)
+ if (nChange > 0 && nChange < MIN_CHANGE)
{
CTxOut txout(nChange, (CScript)std::vector<unsigned char>(24, 0));
if (txout.IsDust(::minRelayTxFee))
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 8917f77f22..1c0056a7bd 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -88,7 +88,7 @@ QString dateTimeStr(qint64 nTime)
return dateTimeStr(QDateTime::fromTime_t((qint32)nTime));
}
-QFont bitcoinAddressFont()
+QFont fixedPitchFont()
{
QFont font("Monospace");
#if QT_VERSION >= 0x040800
@@ -103,7 +103,7 @@ void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent)
{
parent->setFocusProxy(widget);
- widget->setFont(bitcoinAddressFont());
+ widget->setFont(fixedPitchFont());
#if QT_VERSION >= 0x040700
// We don't want translators to use own addresses in translations
// and this is the only place, where this address is supplied.
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 0ac3db6327..ec678c4af2 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -37,8 +37,8 @@ namespace GUIUtil
QString dateTimeStr(const QDateTime &datetime);
QString dateTimeStr(qint64 nTime);
- // Render Bitcoin addresses in monospace font
- QFont bitcoinAddressFont();
+ // Return a monospace font
+ QFont fixedPitchFont();
// Set up widgets for address and amounts
void setupAddressWidget(QValidatedLineEdit *widget, QWidget *parent);
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 3ebb4d0bf6..58921a9f8b 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -3706,7 +3706,7 @@
<context>
<name>bitcoin-core</name>
<message>
- <location filename="../bitcoinstrings.cpp" line="+249"/>
+ <location filename="../bitcoinstrings.cpp" line="+258"/>
<source>Options:</source>
<translation>Options:</translation>
</message>
@@ -3731,7 +3731,7 @@
<translation>Accept command line and JSON-RPC commands</translation>
</message>
<message>
- <location line="-117"/>
+ <location line="-118"/>
<source>Fees (in %s/kB) smaller than this are considered zero fee for relaying (default: %s)</source>
<translation type="unfinished"></translation>
</message>
@@ -3771,17 +3771,17 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+109"/>
+ <location line="+110"/>
<source>Error: A fatal internal error occurred, see debug.log for details</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
+ <location line="+3"/>
<source>Fee (in %s/kB) to add to transactions you send (default: %s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+37"/>
+ <location line="+38"/>
<source>Pruning blockstore...</source>
<translation type="unfinished"></translation>
</message>
@@ -3796,17 +3796,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
- <source>Use the test network</source>
- <translation>Use the test network</translation>
- </message>
- <message>
- <location line="-123"/>
+ <location line="-119"/>
<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="-157"/>
+ <location line="-160"/>
<source>Bind to given address and always listen on it. Use [host]:port notation for IPv6</source>
<translation>Bind to given address and always listen on it. Use [host]:port notation for IPv6</translation>
</message>
@@ -3821,7 +3816,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+11"/>
+ <location line="+13"/>
<source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
<translation>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</translation>
</message>
@@ -3841,12 +3836,12 @@
<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="+7"/>
+ <location line="+13"/>
<source>Unable to bind to %s on this computer. Bitcoin Core is probably already running.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+6"/>
<source>Use UPnP to map the listening port (default: 1 when listening and no -proxy)</source>
<translation type="unfinished"></translation>
</message>
@@ -3861,11 +3856,6 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
- <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>
- <message>
<location line="+3"/>
<source>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</source>
<translation>Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.</translation>
@@ -3877,11 +3867,6 @@
</message>
<message>
<location line="+3"/>
- <source>Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
- <translation>Warning: error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</translation>
- </message>
- <message>
- <location line="+3"/>
<source>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.</source>
<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>
@@ -3897,6 +3882,11 @@
</message>
<message>
<location line="+1"/>
+ <source>-maxmempool must be at least %d MB</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>&lt;category&gt; can be:</source>
<translation type="unfinished"></translation>
</message>
@@ -3986,7 +3976,7 @@
<translation>Error: Disk space is low!</translation>
</message>
<message>
- <location line="+2"/>
+ <location line="+1"/>
<source>Failed to listen on any port. Use -listen=0 if you want this.</source>
<translation>Failed to listen on any port. Use -listen=0 if you want this.</translation>
</message>
@@ -4006,7 +3996,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+20"/>
+ <location line="+9"/>
+ <source>Keep the transaction memory pool below &lt;n&gt; megabytes (default: %u)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+12"/>
<source>Not enough file descriptors available.</source>
<translation>Not enough file descriptors available.</translation>
</message>
@@ -4041,12 +4036,32 @@
<translation>Specify wallet file (within data directory)</translation>
</message>
<message>
- <location line="+17"/>
+ <location line="+16"/>
+ <source>Unsupported argument -benchmark ignored, use -debug=bench.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Unsupported argument -debugnet ignored, use -debug=net.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Unsupported argument -tor found, use -onion.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
<source>Use UPnP to map the listening port (default: %u)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+1"/>
+ <source>User Agent comment (%s) contains unsafe characters.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
<source>Verifying blocks...</source>
<translation>Verifying blocks...</translation>
</message>
@@ -4071,17 +4086,17 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+3"/>
+ <location line="+1"/>
<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>
<message>
- <location line="-89"/>
+ <location line="-91"/>
<source>Imports blocks from external blk000??.dat file</source>
<translation>Imports blocks from external blk000??.dat file</translation>
</message>
<message>
- <location line="-206"/>
+ <location line="-208"/>
<source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times</source>
<translation type="unfinished"></translation>
</message>
@@ -4111,17 +4126,12 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+11"/>
<source>Error: Listening for incoming connections failed (listen returned error %s)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+2"/>
- <source>Error: Unsupported argument -socks found. Setting SOCKS version isn&apos;t possible anymore, only SOCKS5 proxies are supported.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+3"/>
<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>
@@ -4171,12 +4181,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+18"/>
- <source>Warning: -maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+22"/>
+ <location line="+40"/>
<source>Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway</source>
<translation type="unfinished"></translation>
</message>
@@ -4191,7 +4196,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+5"/>
+ <location line="+6"/>
<source>Accept public REST requests (default: %u)</source>
<translation type="unfinished"></translation>
</message>
@@ -4231,12 +4236,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+4"/>
- <source>Error: Unsupported argument -tor found, use -onion.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+9"/>
+ <location line="+12"/>
<source>Information</source>
<translation>Information</translation>
</message>
@@ -4276,7 +4276,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+11"/>
<source>Need to specify a port with -whitebind: &apos;%s&apos;</source>
<translation type="unfinished"></translation>
</message>
@@ -4391,7 +4391,7 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+6"/>
+ <location line="+9"/>
<source>Username for JSON-RPC connections</source>
<translation>Username for JSON-RPC connections</translation>
</message>
@@ -4406,17 +4406,7 @@
<translation>Warning</translation>
</message>
<message>
- <location line="+2"/>
- <source>Warning: Unsupported argument -benchmark ignored, use -debug=bench.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+1"/>
- <source>Warning: Unsupported argument -debugnet ignored, use -debug=net.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location line="+2"/>
+ <location line="+3"/>
<source>Zapping all transactions from wallet...</source>
<translation type="unfinished"></translation>
</message>
@@ -4436,22 +4426,22 @@
<translation>wallet.dat corrupt, salvage failed</translation>
</message>
<message>
- <location line="-64"/>
+ <location line="-65"/>
<source>Password for JSON-RPC connections</source>
<translation>Password for JSON-RPC connections</translation>
</message>
<message>
- <location line="-195"/>
+ <location line="-196"/>
<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="+242"/>
+ <location line="+246"/>
<source>Upgrade wallet to latest format</source>
<translation>Upgrade wallet to latest format</translation>
</message>
<message>
- <location line="-36"/>
+ <location line="-39"/>
<source>Rescan the block chain for missing wallet transactions</source>
<translation>Rescan the block chain for missing wallet transactions</translation>
</message>
@@ -4476,12 +4466,32 @@
<translation>Error loading wallet.dat: Wallet corrupted</translation>
</message>
<message>
- <location line="-196"/>
+ <location line="-205"/>
<source>(1 = keep tx meta data e.g. account owner and payment request information, 2 = drop tx meta data)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+49"/>
+ <location line="+3"/>
+ <source>-maxtxfee is set very high! Fees this large could be paid on a single transaction.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+32"/>
+ <source>Do not keep transactions in the mempool longer than &lt;n&gt; hours (default: %u)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>Error reading wallet.dat! All keys read correctly, but transaction data or address book entries might be missing or incorrect.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+17"/>
<source>How thorough the block verification of -checkblocks is (0-4, default: %u)</source>
<translation type="unfinished"></translation>
</message>
@@ -4501,17 +4511,32 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+51"/>
+ <location line="+46"/>
+ <source>Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Tries to keep outbound traffic under the given target (in MiB per 24h), 0 = no limit (default: %d)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>Unsupported argument -socks found. Setting SOCKS version isn&apos;t possible anymore, only SOCKS5 proxies are supported.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location line="+5"/>
<source>Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+37"/>
+ <location line="+28"/>
<source>(default: %s)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location line="+10"/>
+ <location line="+11"/>
<source>Always query for peer addresses via DNS lookup (default: %u)</source>
<translation type="unfinished"></translation>
</message>
@@ -4521,7 +4546,7 @@
<translation>Error loading wallet.dat</translation>
</message>
<message>
- <location line="+11"/>
+ <location line="+10"/>
<source>Generate coins (default: %u)</source>
<translation type="unfinished"></translation>
</message>
@@ -4541,7 +4566,7 @@
<translation>Invalid -proxy address: &apos;%s&apos;</translation>
</message>
<message>
- <location line="+8"/>
+ <location line="+9"/>
<source>Listen for JSON-RPC connections on &lt;port&gt; (default: %u or testnet: %u)</source>
<translation type="unfinished"></translation>
</message>
@@ -4641,7 +4666,7 @@
<translation>Cannot resolve -externalip address: &apos;%s&apos;</translation>
</message>
<message>
- <location line="+47"/>
+ <location line="+46"/>
<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>
@@ -4651,7 +4676,7 @@
<translation>Insufficient funds</translation>
</message>
<message>
- <location line="+13"/>
+ <location line="+14"/>
<source>Loading block index...</source>
<translation>Loading block index...</translation>
</message>
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index f387a3ec8c..8401701821 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -462,13 +462,19 @@ void RPCConsole::clear()
}
// Set default style sheet
+ QFontInfo fixedFontInfo(GUIUtil::fixedPitchFont());
+ // Try to make fixed font adequately large on different OS
+ QString ptSize = QString("%1pt").arg(QFontInfo(QFont()).pointSize() * 8.5 / 9);
ui->messagesWidget->document()->setDefaultStyleSheet(
+ QString(
"table { }"
"td.time { color: #808080; padding-top: 3px; } "
+ "td.message { font-family: %1; font-size: %2; white-space:pre-wrap; } "
"td.cmd-request { color: #006060; } "
"td.cmd-error { color: red; } "
"b { color: #006060; } "
- );
+ ).arg(fixedFontInfo.family(), ptSize)
+ );
message(CMD_REPLY, (tr("Welcome to the Bitcoin Core RPC console.") + "<br>" +
tr("Use up and down arrows to navigate history, and <b>Ctrl-L</b> to clear screen.") + "<br>" +
@@ -494,7 +500,7 @@ void RPCConsole::message(int category, const QString &message, bool html)
if(html)
out += message;
else
- out += GUIUtil::HtmlEscape(message, true);
+ out += GUIUtil::HtmlEscape(message, false);
out += "</td></tr></table>";
ui->messagesWidget->append(out);
}
@@ -849,4 +855,4 @@ void RPCConsole::showOrHideBanTableIfRequired()
bool visible = clientModel->getBanTableModel()->shouldShow();
ui->banlistWidget->setVisible(visible);
ui->banHeading->setVisible(visible);
-} \ No newline at end of file
+}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index b86f776786..d5932ff149 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -71,6 +71,7 @@ private Q_SLOTS:
public Q_SLOTS:
void clear();
+ /** Append the message to the message widget */
void message(int category, const QString &message, bool html = false);
/** Set number of connections shown in the UI */
void setNumConnections(int count);
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index 44aa8ad1af..4f4b5b70d5 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -40,7 +40,7 @@ SendCoinsEntry::SendCoinsEntry(const PlatformStyle *platformStyle, QWidget *pare
// normal bitcoin address field
GUIUtil::setupAddressWidget(ui->payTo, this);
// just a label for displaying bitcoin address(es)
- ui->payTo_is->setFont(GUIUtil::bitcoinAddressFont());
+ ui->payTo_is->setFont(GUIUtil::fixedPitchFont());
// Connect signals
connect(ui->payAmount, SIGNAL(valueChanged()), this, SIGNAL(payAmountChanged()));
diff --git a/src/qt/signverifymessagedialog.cpp b/src/qt/signverifymessagedialog.cpp
index 60e8e36ebe..96f50a2656 100644
--- a/src/qt/signverifymessagedialog.cpp
+++ b/src/qt/signverifymessagedialog.cpp
@@ -51,8 +51,8 @@ SignVerifyMessageDialog::SignVerifyMessageDialog(const PlatformStyle *platformSt
ui->messageIn_VM->installEventFilter(this);
ui->signatureIn_VM->installEventFilter(this);
- ui->signatureOut_SM->setFont(GUIUtil::bitcoinAddressFont());
- ui->signatureIn_VM->setFont(GUIUtil::bitcoinAddressFont());
+ ui->signatureOut_SM->setFont(GUIUtil::fixedPitchFont());
+ ui->signatureIn_VM->setFont(GUIUtil::fixedPitchFont());
}
SignVerifyMessageDialog::~SignVerifyMessageDialog()
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 20c0c1fb2f..146eb3905a 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -539,13 +539,15 @@ UniValue gettxout(const UniValue& params, bool fHelp)
UniValue verifychain(const UniValue& params, bool fHelp)
{
+ int nCheckLevel = GetArg("-checklevel", DEFAULT_CHECKLEVEL);
+ int nCheckDepth = GetArg("-checkblocks", DEFAULT_CHECKBLOCKS);
if (fHelp || params.size() > 2)
throw runtime_error(
"verifychain ( checklevel numblocks )\n"
"\nVerifies blockchain database.\n"
"\nArguments:\n"
- "1. checklevel (numeric, optional, 0-4, default=3) How thorough the block verification is.\n"
- "2. numblocks (numeric, optional, default=288, 0=all) The number of blocks to check.\n"
+ "1. checklevel (numeric, optional, 0-4, default=" + strprintf("%d", nCheckLevel) + ") How thorough the block verification is.\n"
+ "2. numblocks (numeric, optional, default=" + strprintf("%d", nCheckDepth) + ", 0=all) The number of blocks to check.\n"
"\nResult:\n"
"true|false (boolean) Verified or not\n"
"\nExamples:\n"
@@ -555,8 +557,6 @@ UniValue verifychain(const UniValue& params, bool fHelp)
LOCK(cs_main);
- int nCheckLevel = GetArg("-checklevel", 3);
- int nCheckDepth = GetArg("-checkblocks", 288);
if (params.size() > 0)
nCheckLevel = params[0].get_int();
if (params.size() > 1)
@@ -773,6 +773,9 @@ UniValue mempoolInfoToJSON()
ret.push_back(Pair("size", (int64_t) mempool.size()));
ret.push_back(Pair("bytes", (int64_t) mempool.GetTotalTxSize()));
ret.push_back(Pair("usage", (int64_t) mempool.DynamicMemoryUsage()));
+ size_t maxmempool = GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
+ ret.push_back(Pair("maxmempool", (int64_t) maxmempool));
+ ret.push_back(Pair("mempoolminfee", ValueFromAmount(mempool.GetMinFee(maxmempool).GetFeePerK())));
return ret;
}
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index c49c3e5194..f42b31627c 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -211,7 +211,7 @@ UniValue setgenerate(const UniValue& params, bool fHelp)
if (params.size() > 0)
fGenerate = params[0].get_bool();
- int nGenProcLimit = -1;
+ int nGenProcLimit = GetArg("-genproclimit", DEFAULT_GENERATE_THREADS);
if (params.size() > 1)
{
nGenProcLimit = params[1].get_int();
@@ -259,7 +259,7 @@ UniValue getmininginfo(const UniValue& 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("genproclimit", (int)GetArg("-genproclimit", -1)));
+ obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", DEFAULT_GENERATE_THREADS)));
obj.push_back(Pair("networkhashps", getnetworkhashps(params, false)));
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index 7746be25f7..9bf017e385 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -29,7 +29,7 @@ UniValue getconnectioncount(const UniValue& params, bool fHelp)
throw runtime_error(
"getconnectioncount\n"
"\nReturns the number of connections to other nodes.\n"
- "\nbResult:\n"
+ "\nResult:\n"
"n (numeric) The connection count\n"
"\nExamples:\n"
+ HelpExampleCli("getconnectioncount", "")
@@ -83,7 +83,7 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp)
throw runtime_error(
"getpeerinfo\n"
"\nReturns data about each connected network node as a json array of objects.\n"
- "\nbResult:\n"
+ "\nResult:\n"
"[\n"
" {\n"
" \"id\": n, (numeric) Peer index\n"
@@ -379,6 +379,15 @@ UniValue getnettotals(const UniValue& params, bool fHelp)
obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv()));
obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent()));
obj.push_back(Pair("timemillis", GetTimeMillis()));
+
+ UniValue outboundLimit(UniValue::VOBJ);
+ outboundLimit.push_back(Pair("timeframe", CNode::GetMaxOutboundTimeframe()));
+ outboundLimit.push_back(Pair("target", CNode::GetMaxOutboundTarget()));
+ outboundLimit.push_back(Pair("target_reached", CNode::OutboundTargetReached(false)));
+ outboundLimit.push_back(Pair("serve_historical_blocks", !CNode::OutboundTargetReached(true)));
+ outboundLimit.push_back(Pair("bytes_left_in_cycle", CNode::GetOutboundTargetBytesLeft()));
+ outboundLimit.push_back(Pair("time_left_in_cycle", CNode::GetMaxOutboundTimeLeftInCycle()));
+ obj.push_back(Pair("uploadtarget", outboundLimit));
return obj;
}
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index fa60f8c833..8bda5a0373 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -563,7 +563,7 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
deadlineTimers.erase(name);
RPCTimerInterface* timerInterface = timerInterfaces[0];
LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
- deadlineTimers.insert(std::make_pair(name, timerInterface->NewTimer(func, nSeconds*1000)));
+ deadlineTimers.insert(std::make_pair(name, boost::shared_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000))));
}
const CRPCTable tableRPC;
diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp
index dd3c51d09b..468eda1c9b 100644
--- a/src/test/alert_tests.cpp
+++ b/src/test/alert_tests.cpp
@@ -217,10 +217,12 @@ BOOST_AUTO_TEST_CASE(PartitionAlert)
// use them
}
+ strMiscWarning = "";
+
// Test 1: chain with blocks every nPowTargetSpacing seconds,
// as normal, no worries:
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
- BOOST_CHECK(strMiscWarning.empty());
+ BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning);
// Test 2: go 3.5 hours without a block, expect a warning:
now += 3*60*60+30*60;
diff --git a/src/test/data/tx_invalid.json b/src/test/data/tx_invalid.json
index d3c8594342..cc059e814f 100644
--- a/src/test/data/tx_invalid.json
+++ b/src/test/data/tx_invalid.json
@@ -64,9 +64,13 @@
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff655151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", "P2SH"],
-["Null txin"],
-[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "HASH160 0x14 0x02dae7dbbda56097959cba59b1989dd3e47937bf EQUAL"]],
-"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6e49304602210086f39e028e46dafa8e1e3be63906465f4cf038fbe5ed6403dc3e74ae876e6431022100c4625c675cfc5c7e3a0e0d7eaec92ac24da20c73a88eb40d09253e51ac6def5201232103a183ddc41e84753aca47723c965d1b5c8b0e2b537963518355e6dd6cf8415e50acffffffff010000000000000000015100000000", "P2SH"],
+["Null txin, but without being a coinbase (because there are two inputs)"],
+[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"],
+ ["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
+"01000000020000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015100000000", "P2SH"],
+[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"],
+ ["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
+"010000000200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff010000000000000000015100000000", "P2SH"],
["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"],
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index a74fbfc0d7..23e5e66d84 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -36,6 +36,7 @@ BasicTestingSetup::BasicTestingSetup(const std::string& chainName)
{
ECC_Start();
SetupEnvironment();
+ SetupNetworking();
fPrintToDebugLog = false; // don't want to write to debug.log file
fCheckBlockIndex = true;
SelectParams(chainName);
diff --git a/src/txdb.cpp b/src/txdb.cpp
index f0868a1ebf..cd76c0155c 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -121,7 +121,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const {
nTotalAmount += out.nValue;
}
}
- stats.nSerializedSize += 32 + pcursor->GetKeySize();
+ stats.nSerializedSize += 32 + pcursor->GetValueSize();
ss << VARINT(0);
} else {
return error("CCoinsViewDB::GetStats() : unable to read value");
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index bb148005cd..a772e7adea 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -309,12 +309,12 @@ void CTxMemPoolEntry::UpdateState(int64_t modifySize, CAmount modifyFee, int64_t
CTxMemPool::CTxMemPool(const CFeeRate& _minReasonableRelayFee) :
nTransactionsUpdated(0)
{
- clear();
+ _clear(); //lock free clear
// Sanity checks off by default for performance, because otherwise
// accepting transactions becomes O(N^2) where N is the number
// of transactions in the pool
- fSanityCheck = false;
+ nCheckFrequency = 0;
minerPolicyEstimator = new CBlockPolicyEstimator(_minReasonableRelayFee);
minReasonableRelayFee = _minReasonableRelayFee;
@@ -487,7 +487,7 @@ void CTxMemPool::removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned in
if (it2 != mapTx.end())
continue;
const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
- if (fSanityCheck) assert(coins);
+ if (nCheckFrequency != 0) assert(coins);
if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) {
transactionsToRemove.push_back(tx);
break;
@@ -512,6 +512,7 @@ void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>
if (txConflict != tx)
{
remove(txConflict, removed, true);
+ ClearPrioritisation(txConflict.GetHash());
}
}
}
@@ -546,9 +547,8 @@ void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned i
blockSinceLastRollingFeeBump = true;
}
-void CTxMemPool::clear()
+void CTxMemPool::_clear()
{
- LOCK(cs);
mapLinks.clear();
mapTx.clear();
mapNextTx.clear();
@@ -560,9 +560,18 @@ void CTxMemPool::clear()
++nTransactionsUpdated;
}
+void CTxMemPool::clear()
+{
+ LOCK(cs);
+ _clear();
+}
+
void CTxMemPool::check(const CCoinsViewCache *pcoins) const
{
- if (!fSanityCheck)
+ if (nCheckFrequency == 0)
+ return;
+
+ if (insecure_rand() >= nCheckFrequency)
return;
LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
diff --git a/src/txmempool.h b/src/txmempool.h
index d44995eefe..7b5843a8d0 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -278,7 +278,7 @@ public:
class CTxMemPool
{
private:
- bool fSanityCheck; //! Normally false, true if -checkmempool or -regtest
+ uint32_t nCheckFrequency; //! Value n means that n times in 2^32 we check.
unsigned int nTransactionsUpdated;
CBlockPolicyEstimator* minerPolicyEstimator;
@@ -360,7 +360,7 @@ public:
* check does nothing.
*/
void check(const CCoinsViewCache *pcoins) const;
- void setSanityCheck(bool _fSanityCheck) { fSanityCheck = _fSanityCheck; }
+ void setSanityCheck(double dFrequency = 1.0) { nCheckFrequency = dFrequency * 4294967295.0; }
// addUnchecked must updated state for all ancestors of a given transaction,
// to track size/count of descendant transactions. First version of
@@ -375,6 +375,7 @@ public:
void removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
std::list<CTransaction>& conflicts, bool fCurrentEstimate = true);
void clear();
+ void _clear(); //lock free
void queryHashes(std::vector<uint256>& vtxid);
void pruneSpent(const uint256& hash, CCoins &coins);
unsigned int GetTransactionsUpdated() const;
diff --git a/src/util.cpp b/src/util.cpp
index 8192a7c71c..e8514a2ef0 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -108,6 +108,7 @@ bool fDaemon = false;
bool fServer = false;
string strMiscWarning;
bool fLogTimestamps = false;
+bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS;
bool fLogIPs = false;
volatile bool fReopenDebugLog = false;
CTranslationInterface translationInterface;
@@ -263,9 +264,13 @@ static std::string LogTimestampStr(const std::string &str, bool *fStartedNewLine
if (!fLogTimestamps)
return str;
- if (*fStartedNewLine)
- strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()) + ' ' + str;
- else
+ if (*fStartedNewLine) {
+ int64_t nTimeMicros = GetLogTimeMicros();
+ strStamped = DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nTimeMicros/1000000);
+ if (fLogTimeMicros)
+ strStamped += strprintf(".%06d", nTimeMicros%1000000);
+ strStamped += ' ' + str;
+ } else
strStamped = str;
if (!str.empty() && str[str.size()-1] == '\n')
diff --git a/src/util.h b/src/util.h
index 0b2dc01ac6..b2779fe782 100644
--- a/src/util.h
+++ b/src/util.h
@@ -28,6 +28,8 @@
#include <boost/signals2/signal.hpp>
#include <boost/thread/exceptions.hpp>
+static const bool DEFAULT_LOGTIMEMICROS = false;
+
/** Signals for translation. */
class CTranslationInterface
{
@@ -44,6 +46,7 @@ extern bool fPrintToDebugLog;
extern bool fServer;
extern std::string strMiscWarning;
extern bool fLogTimestamps;
+extern bool fLogTimeMicros;
extern bool fLogIPs;
extern volatile bool fReopenDebugLog;
extern CTranslationInterface translationInterface;
diff --git a/src/utiltime.cpp b/src/utiltime.cpp
index d316288999..3202c47f1d 100644
--- a/src/utiltime.cpp
+++ b/src/utiltime.cpp
@@ -40,6 +40,14 @@ int64_t GetTimeMicros()
boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_microseconds();
}
+/** Return a time useful for the debug log */
+int64_t GetLogTimeMicros()
+{
+ if (nMockTime) return nMockTime*1000000;
+
+ return GetTimeMicros();
+}
+
void MilliSleep(int64_t n)
{
diff --git a/src/utiltime.h b/src/utiltime.h
index 900992f871..241b5211e9 100644
--- a/src/utiltime.h
+++ b/src/utiltime.h
@@ -12,6 +12,7 @@
int64_t GetTime();
int64_t GetTimeMillis();
int64_t GetTimeMicros();
+int64_t GetLogTimeMicros();
void SetMockTime(int64_t nMockTimeIn);
void MilliSleep(int64_t n);
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index e5bc653c33..cf6122813c 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -293,7 +293,7 @@ void CDB::Flush()
if (fReadOnly)
nMinutes = 1;
- bitdb.dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0);
+ bitdb.dbenv->txn_checkpoint(nMinutes ? GetArg("-dblogsize", DEFAULT_WALLET_DBLOGSIZE) * 1024 : 0, nMinutes, 0);
}
void CDB::Close()
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 64071caa3a..46bc0ac0a9 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -20,6 +20,8 @@
#include <db_cxx.h>
+static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
+
extern unsigned int nWalletDBUpdated;
class CDBEnv
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index a5bc52b8dc..8b9292bd14 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
// try making 34 cents from 1,2,5,10,20 - we can't do it exactly
BOOST_CHECK( wallet.SelectCoinsMinConf(34 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
- BOOST_CHECK_GT(nValueRet, 34 * CENT); // but should get more than 34 cents
+ BOOST_CHECK_EQUAL(nValueRet, 35 * CENT); // but 35 cents is closest
BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U); // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible)
// when we try making 7 cents, the smaller coins (1,2,5) are enough. We should see just 2+5
@@ -185,33 +185,34 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
BOOST_CHECK_EQUAL(nValueRet, 2 * COIN); // we should get 2 BTC in 1 coin
BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U);
- // empty the wallet and start again, now with fractions of a cent, to test sub-cent change avoidance
+ // empty the wallet and start again, now with fractions of a cent, to test small change avoidance
+
empty_wallet();
- add_coin(0.1*CENT);
- add_coin(0.2*CENT);
- add_coin(0.3*CENT);
- add_coin(0.4*CENT);
- add_coin(0.5*CENT);
-
- // try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 = 1.5 cents
- // we'll get sub-cent change whatever happens, so can expect 1.0 exactly
- BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
- BOOST_CHECK_EQUAL(nValueRet, 1 * CENT);
+ add_coin(0.1*MIN_CHANGE);
+ add_coin(0.2*MIN_CHANGE);
+ add_coin(0.3*MIN_CHANGE);
+ add_coin(0.4*MIN_CHANGE);
+ add_coin(0.5*MIN_CHANGE);
+
+ // try making 1 * MIN_CHANGE from the 1.5 * MIN_CHANGE
+ // we'll get change smaller than MIN_CHANGE whatever happens, so can expect MIN_CHANGE exactly
+ BOOST_CHECK( wallet.SelectCoinsMinConf(MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, MIN_CHANGE);
- // but if we add a bigger coin, making it possible to avoid sub-cent change, things change:
- add_coin(1111*CENT);
+ // but if we add a bigger coin, small change is avoided
+ add_coin(1111*MIN_CHANGE);
- // try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + 1111 = 1112.5 cents
- BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
- BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount
+ // try making 1 from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + 1111 = 1112.5
+ BOOST_CHECK( wallet.SelectCoinsMinConf(1 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1 * MIN_CHANGE); // we should get the exact amount
- // if we add more sub-cent coins:
- add_coin(0.6*CENT);
- add_coin(0.7*CENT);
+ // if we add more small coins:
+ add_coin(0.6*MIN_CHANGE);
+ add_coin(0.7*MIN_CHANGE);
- // and try again to make 1.0 cents, we can still make 1.0 cents
- BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
- BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount
+ // and try again to make 1.0 * MIN_CHANGE
+ BOOST_CHECK( wallet.SelectCoinsMinConf(1 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1 * MIN_CHANGE); // we should get the exact amount
// run the 'mtgox' test (see http://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf)
// they tried to consolidate 10 50k coins into one 500k coin, and ended up with 50k in change
@@ -223,45 +224,65 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
BOOST_CHECK_EQUAL(nValueRet, 500000 * COIN); // we should get the exact amount
BOOST_CHECK_EQUAL(setCoinsRet.size(), 10U); // in ten coins
- // if there's not enough in the smaller coins to make at least 1 cent change (0.5+0.6+0.7 < 1.0+1.0),
+ // if there's not enough in the smaller coins to make at least 1 * MIN_CHANGE change (0.5+0.6+0.7 < 1.0+1.0),
// we need to try finding an exact subset anyway
// sometimes it will fail, and so we use the next biggest coin:
empty_wallet();
- add_coin(0.5 * CENT);
- add_coin(0.6 * CENT);
- add_coin(0.7 * CENT);
- add_coin(1111 * CENT);
- BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
- BOOST_CHECK_EQUAL(nValueRet, 1111 * CENT); // we get the bigger coin
+ add_coin(0.5 * MIN_CHANGE);
+ add_coin(0.6 * MIN_CHANGE);
+ add_coin(0.7 * MIN_CHANGE);
+ add_coin(1111 * MIN_CHANGE);
+ BOOST_CHECK( wallet.SelectCoinsMinConf(1 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 1111 * MIN_CHANGE); // we get the bigger coin
BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U);
// but sometimes it's possible, and we use an exact subset (0.4 + 0.6 = 1.0)
empty_wallet();
- add_coin(0.4 * CENT);
- add_coin(0.6 * CENT);
- add_coin(0.8 * CENT);
- add_coin(1111 * CENT);
- BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
- BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount
+ add_coin(0.4 * MIN_CHANGE);
+ add_coin(0.6 * MIN_CHANGE);
+ add_coin(0.8 * MIN_CHANGE);
+ add_coin(1111 * MIN_CHANGE);
+ BOOST_CHECK( wallet.SelectCoinsMinConf(MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, MIN_CHANGE); // we should get the exact amount
BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); // in two coins 0.4+0.6
- // test avoiding sub-cent change
+ // test avoiding small change
empty_wallet();
- add_coin(0.0005 * COIN);
- add_coin(0.01 * COIN);
- add_coin(1 * COIN);
+ add_coin(0.05 * MIN_CHANGE);
+ add_coin(1 * MIN_CHANGE);
+ add_coin(100 * MIN_CHANGE);
- // trying to make 1.0001 from these three coins
- BOOST_CHECK( wallet.SelectCoinsMinConf(1.0001 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
- BOOST_CHECK_EQUAL(nValueRet, 1.0105 * COIN); // we should get all coins
+ // trying to make 100.01 from these three coins
+ BOOST_CHECK( wallet.SelectCoinsMinConf(100.01 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 101.05 * MIN_CHANGE); // we should get all coins
BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U);
- // but if we try to make 0.999, we should take the bigger of the two small coins to avoid sub-cent change
- BOOST_CHECK( wallet.SelectCoinsMinConf(0.999 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
- BOOST_CHECK_EQUAL(nValueRet, 1.01 * COIN); // we should get 1 + 0.01
+ // but if we try to make 99.9, we should take the bigger of the two small coins to avoid small change
+ BOOST_CHECK( wallet.SelectCoinsMinConf(99.9 * MIN_CHANGE, 1, 1, vCoins, setCoinsRet, nValueRet));
+ BOOST_CHECK_EQUAL(nValueRet, 101 * MIN_CHANGE);
BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U);
+ // test with many inputs
+ for (CAmount amt=1500; amt < COIN; amt*=10) {
+ empty_wallet();
+ // Create 676 inputs (= MAX_STANDARD_TX_SIZE / 148 bytes per input)
+ for (uint16_t j = 0; j < 676; j++)
+ add_coin(amt);
+ BOOST_CHECK(wallet.SelectCoinsMinConf(2000, 1, 1, vCoins, setCoinsRet, nValueRet));
+ if (amt - 2000 < MIN_CHANGE) {
+ // needs more than one input:
+ uint16_t returnSize = std::ceil((2000.0 + MIN_CHANGE)/amt);
+ CAmount returnValue = amt * returnSize;
+ BOOST_CHECK_EQUAL(nValueRet, returnValue);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), returnSize);
+ } else {
+ // one input is sufficient:
+ BOOST_CHECK_EQUAL(nValueRet, amt);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U);
+ }
+ }
+
// test randomness
{
empty_wallet();
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 8c0dad2381..cce3e40f38 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -47,7 +47,7 @@ bool fPayAtLeastCustomFee = true;
* Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
* Override with -mintxfee
*/
-CFeeRate CWallet::minTxFee = CFeeRate(1000);
+CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE);
/** @defgroup mapWallet
*
@@ -1497,9 +1497,6 @@ CAmount CWallet::GetImmatureWatchOnlyBalance() const
return nTotal;
}
-/**
- * populate vCoins with vector of available COutputs.
- */
void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeZeroValue) const
{
vCoins.clear();
@@ -1619,7 +1616,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int
nValueRet += coin.first;
return true;
}
- else if (n < nTargetValue + CENT)
+ else if (n < nTargetValue + MIN_CHANGE)
{
vValue.push_back(coin);
nTotalLower += n;
@@ -1654,14 +1651,14 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int
vector<char> vfBest;
CAmount nBest;
- ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
- if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
- ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
+ ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest);
+ if (nBest != nTargetValue && nTotalLower >= nTargetValue + MIN_CHANGE)
+ ApproximateBestSubset(vValue, nTotalLower, nTargetValue + MIN_CHANGE, vfBest, nBest);
// If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
// or the next bigger coin is closer), return the bigger coin
if (coinLowestLarger.second.first &&
- ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
+ ((nBest != nTargetValue && nBest < nTargetValue + MIN_CHANGE) || coinLowestLarger.first <= nBest))
{
setCoinsRet.insert(coinLowestLarger.second);
nValueRet += coinLowestLarger.first;
@@ -1844,6 +1841,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
LOCK2(cs_main, cs_wallet);
{
nFeeRet = 0;
+ // Start with no fee and loop until there is enough fee
while (true)
{
txNew.vin.clear();
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 22fe08670f..719f11f206 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -41,8 +41,12 @@ extern bool fPayAtLeastCustomFee;
static const CAmount DEFAULT_TRANSACTION_FEE = 0;
//! -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB
static const CAmount nHighTransactionFeeWarning = 0.01 * COIN;
+//! -mintxfee default
+static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
//! -maxtxfee default
static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.1 * COIN;
+//! minimum change amount
+static const CAmount MIN_CHANGE = CENT;
//! -txconfirmtarget default
static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2;
//! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
@@ -442,6 +446,11 @@ public:
class CWallet : public CCryptoKeyStore, public CValidationInterface
{
private:
+ /**
+ * Select a set of coins such that nValueRet >= nTargetValue and at least
+ * all coins from coinControl are selected; Never select unconfirmed coins
+ * if they are not ours
+ */
bool SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL) const;
CWalletDB *pwalletdbEncryption;
@@ -539,7 +548,17 @@ public:
//! check whether we are allowed to upgrade (or already support) to the named feature
bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
+ /**
+ * populate vCoins with vector of available COutputs.
+ */
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false) const;
+
+ /**
+ * Shuffle and select coins until nTargetValue is reached while avoiding
+ * small change; This method is stochastic for some inputs and upon
+ * completion the coin set and corresponding actual target value is
+ * assembled
+ */
bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const;
bool IsSpent(const uint256& hash, unsigned int n) const;
@@ -622,7 +641,17 @@ public:
CAmount GetWatchOnlyBalance() const;
CAmount GetUnconfirmedWatchOnlyBalance() const;
CAmount GetImmatureWatchOnlyBalance() const;
+
+ /**
+ * Insert additional inputs into the transaction by
+ * calling CreateTransaction();
+ */
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching);
+
+ /**
+ * Create a new transaction paying the recipients with a set of coins
+ * selected by SelectCoins(); Also create the change output, when needed
+ */
bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet,
std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true);
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp
index 0624e442d1..ea8a4eb043 100644
--- a/src/wallet/walletdb.cpp
+++ b/src/wallet/walletdb.cpp
@@ -512,8 +512,13 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
}
else if (strType == "ckey")
{
- vector<unsigned char> vchPubKey;
+ CPubKey vchPubKey;
ssKey >> vchPubKey;
+ if (!vchPubKey.IsValid())
+ {
+ strErr = "Error reading wallet database: CPubKey corrupt";
+ return false;
+ }
vector<unsigned char> vchPrivKey;
ssValue >> vchPrivKey;
wss.nCKeys++;
diff --git a/src/zmq/zmqnotificationinterface.cpp b/src/zmq/zmqnotificationinterface.cpp
index 388b86707b..09fe3aeb4c 100644
--- a/src/zmq/zmqnotificationinterface.cpp
+++ b/src/zmq/zmqnotificationinterface.cpp
@@ -21,8 +21,7 @@ CZMQNotificationInterface::CZMQNotificationInterface() : pcontext(NULL)
CZMQNotificationInterface::~CZMQNotificationInterface()
{
- // ensure Shutdown if Initialize is called
- assert(!pcontext);
+ Shutdown();
for (std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin(); i!=notifiers.end(); ++i)
{
@@ -59,6 +58,12 @@ CZMQNotificationInterface* CZMQNotificationInterface::CreateWithArguments(const
{
notificationInterface = new CZMQNotificationInterface();
notificationInterface->notifiers = notifiers;
+
+ if (!notificationInterface->Initialize())
+ {
+ delete notificationInterface;
+ notificationInterface = NULL;
+ }
}
return notificationInterface;
@@ -99,7 +104,7 @@ bool CZMQNotificationInterface::Initialize()
return false;
}
- return false;
+ return true;
}
// Called during shutdown sequence
diff --git a/src/zmq/zmqnotificationinterface.h b/src/zmq/zmqnotificationinterface.h
index 8eea15c068..3ccfaf341d 100644
--- a/src/zmq/zmqnotificationinterface.h
+++ b/src/zmq/zmqnotificationinterface.h
@@ -19,10 +19,11 @@ public:
static CZMQNotificationInterface* CreateWithArguments(const std::map<std::string, std::string> &args);
+protected:
bool Initialize();
void Shutdown();
-protected: // CValidationInterface
+ // CValidationInterface
void SyncTransaction(const CTransaction &tx, const CBlock *pblock);
void UpdatedBlockTip(const CBlockIndex *pindex);